• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

whole database locking in B&S / Denny's DVDs

 
Ranch Hand
Posts: 126
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

I'm considering using a locking scheme similar to that in the Denny's DVDs example presented in the SCJD book by Habibi, et. al.

For those not familiar with this scheme, I've outlined it in this previous posting Denny's locking scheme

The assignment I'm working on is B&S v.2.2.2. This database scheme (unlike Denny's DVDs) doesn't have a natural primary key, but it seems you are expected to use the record number to uniquely identify each row, because various methods in the DBAccess interface which you must implement require/return the record number(s). Some methods in this interface can throw a DuplicateKeyException, but using the record number as the primary key would negate the possibility of ever throwing this (assuming your application isn't faulty), because the client should never specify where a new record would be inserted. Therefore, my interpretation is that you use the record number to uniquely identify records, but you must also insist that some field or combination of fields is unique (e.g. name + location).

It seems to me that you would want exclusive access to the database before
updating one of these fields, in order to check all records and ensure that none of them already have the same name and location value.

In the case of Denny's DVDs this could be achieved by adding the following method to DVDDatabase:

public void updatePKRecord(DVD aDVD) throws InterruptedException,
DuplicateKeyException{
synchronized(reservedDVDs){
while(!reservedDVDs.isEmpty()){
reservedDVDs.wait();
}

/* code to check whether name and location value pair is unique and
* update the record or throw DuplicateKeyException goes here
*/

reservedDVDs.notifyAll();
}
}

I think I'm right in saying that this method does not need to be synchronized because we are getting the lock on the static reservedDVDs object within the method body?

I'm not entirely happy about the fact that this method implements the full lock-update-unlock protocol, whereas the other methods in this class each perform only one of these tasks, and rely upon DVDDbAdapter to call them in the correct order. I'd be interested to know how I can do something similar to this when I need exclusive access to the whole database?

A related point is that it seems I shouldn't allow concurrent addition of records to the database. An obvious way to achieve this is by treating the addition of a record like an update to record number -1. All clients attempting to add a record check whether this is already in reservedDVDs, and if so, wait for it to be removed. In the Denny's DVDs example, the DVDDatabase.addDVD() method is not made available to clients (in DVDDbAdapter) so it's not clear how they would cope with concurrent attempts to add a record. Maybe I don't need to worry too much about this as the ability to add/delete records must be provided in the class implementing DBAccess, but access to the functionality is not required from the GUI?

Another scenario where one might want to lock the whole database is when retrieving the initial list of DVDs, in order to prevent dirty reads? This possibility seems (to a fool such as I) to have been overlooked in the Denny's DVDs example?

I'm very grateful for any advice about this, particularly with regard to the DVDs example.

Cheers,
Dan
 
author and jackaroo
Posts: 12200
280
Mac IntelliJ IDE Firefox Browser Oracle C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Dan,

I think I'm right in saying that this method does not need to be synchronized because we are getting the lock on the static reservedDVDs object within the method body?



Correct.

However it is probably worth thinking about whether primary keys should ever be updated. Most commercial databases wont allow this. You could save yourself a lot of trouble by making the assumption that primary keys are not allowed to be updated. Then all you need is the validation on primary key for the create method .

A related point is that it seems I shouldn't allow concurrent addition of records to the database. An obvious way to achieve this is by treating the addition of a record like an update to record number -1.



Or even just ensure that the create method has a synchronized block on a static object (Data.class?) so that only one client can ever be running the create code at any given time.

Maybe I don't need to worry too much about this as the ability to add/delete records must be provided in the class implementing DBAccess, but access to the functionality is not required from the GUI?





Another scenario where one might want to lock the whole database is when retrieving the initial list of DVDs, in order to prevent dirty reads? This possibility seems (to a fool such as I) to have been overlooked in the Denny's DVDs example?



It is generally agreed that non-repeatable reads (slightly different to dirty reads) are acceptable, since it is impossible to ensure that you get repeatable reads unless you give up concurrent access.

Regards, Andrew
 
Dan Murphy
Ranch Hand
Posts: 126
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for your reply Andrew!

It is generally agreed that non-repeatable reads (slightly different to dirty reads) are acceptable, since it is impossible to ensure that you get repeatable reads unless you give up concurrent access.



I'm familiar with the concept of a non-repeatable reads, but I'm not sure what a dirty read is? I think it occurs when a client reads a reord while it is being updated.

I don't know whether you have access to the Denny's DVDs code, but as far as I can tell the getDVDs() method doesn't preclude dirty reads, becase none of the records are locked (added to reservedDVDs) before they are read.

I'd be very interested to know whether you (or Max, or anyone else....) agrees/disagrees with this?

Thanks in Advance,
Dan
 
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's correct: Dirty reads are ok, IMO.
 
Dan Murphy
Ranch Hand
Posts: 126
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Max,

Am I correct in my understanding of dirty reads? Are you agreeing that the getDVDs() allows dirty reads? If so, then this contradicts what it says in your book on P.126:

"The advantage of this interpretation is it will avoid dirty reads in addition to dirty writes"

If this is not what you're saying, then I'd be very grateful if you could explain how this method doesn't allow dirty reads.

Thanks in Advance,
Dan
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Dan,

I'm not sure I'm being clear. Dirty reads are ok for things such as sorting, refreshing, etc. I don't have time to dig into the book right now, but I'm pretty sure that's a consistant approach with what's in the book.
 
Dan Murphy
Ranch Hand
Posts: 126
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Dan,

I hope I don't sound like a jerk - I'm very grateful for the advice you've provided both in your book and on this forum - but I don't think your book is consistent with the notion that dirty reads are OK, because it says on P.126 that Denny's DVDs prevents dirty reads

Anyway, I'm very keen to know if you (or anyone else) agrees that Denny's DVDs does allow dirty reads. My understanding is that there is no reason why a client could not call getDVDs() on an instance of DVDDbAdapter and read a record which another another client is in the middle of updating using a different instance of DVDDbAdapter, is this correct?

If this is OK in the context of SCJD, then fair enough, but I'm surprised, because it seems like un-thread-safe behaviour to me.

Thanks again for your help!
- Dan
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Dan Murphy:
Hi Dan,

I hope I don't sound like a jerk - I'm very grateful for the advice you've provided both in your book and on this forum - but I don't think your book is consistent with the notion that dirty reads are OK, because it says on P.126 that Denny's DVDs prevents dirty reads - Dan



Dan, you're not being a jerk at all. Good engineers question each other all the time, and that's appropriate.

I think I may have been somewhat less then clear on a few points, so let me start out my apologizing for that. Let's see if I can provide some help now.

  • The ReadMe comment on p.126 does say that every public method on DVDDatabase is synchronized. And yes, this does prevent dirty reads, if we are using an approach consistent with figure 4-14. This is the whole point of the ensuing discussion on page 127, which says [i]the distinction between these options is important for threading. I probably should have elaborated on this relationship.......Remember that the synchronization for DVDDatabase is object-wide, not class-wide. Thus, using multiple DVDDatabase objects in various threads in not an inherently thread-safe activity
  • Locking the database for reads is impractical at best. Imagine that you have ten clients, all in various states of reserving and un reserving records. If client #11 wants a clean read of all the records, they'll have to wait until the entire DB is unlocked, which could take quite a bit of time. In addition, they won't be able to trust the data, because client #12 could be changing the data a nanosecond after the read. Ultimately, what's the point?
  • When I replied to your message, I was focusing on your implementation, not Denny's. IMO, you'll be fine if you provide dirty reads.
  • (this is another point on which I should have been more clear) The ReadMes are just suggestions on how you might justify your design decisions to the Sun graders: they are not gospel. They are simply examples of how you might/or might-not, justify a given design choice. You'll notice that the ReadMes on p.134 offer back-to-back support for two completely orthogonal design approaches.



  • HTH,
    M]
    [ April 08, 2005: Message edited by: Max Habibi ]
     
    Dan Murphy
    Ranch Hand
    Posts: 126
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Hi Max,

    I didn'r realise that the remark about preventing dirty reads is referring to the scenario where you only have a single instance of DVDDatabase - so thanks for making that clear!

    Regarding your comment about locking the entire database when the client wants to get an initial (or fresh) list of records, I agree that this would be very inefficient. But wouldn't the following be OK (and reasonably efficient):

    - call getRecords() which returns a list of record numbers (or primary keys)
    - for each record in the list, reserve(), read(), and unreserve()

    Obviously it could happen that a record returned by getRecords() is added/removed before read() is called, but this wouldn't be a disaster because:

    - if a record is deleted after getRecords() and before read(), read() should throw an exception which you could just ignore

    - if a new record is added after getRecords() and before read(), although it wouldn't be returned, this is an example of a non-repeatable read, rather than a dirty read

    It seems to me this scheme would prevent dirty reads (i.e. reading a record which is the middle of being updated), without requiring the entire database to be locked.

    I appreciate that it's not realistic to prevent non-repeatable reads, but I'm really surprised that SCJD allows dirty reads, because they seem like un-thread safe behaviour to me.

    I'd be very interested to hear what you (or anyone else) thinks of this scheme.

    Best Wishes,
    Dan
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Dan,

    I don't think that solves your problem of getting an inaccurate snap shop of the whole DB. Consider: If client #1 reads locks-reads-unlocks record X, then client #2, say, lock-deletes-unlocks record X, then client #1 reads locks-read-unlocks record X+1. Client #1 is still getting a 'dirty' read of the entire DB, even if the read of a given record wasn't dirty at the time it was read. That is, client #1 will think that record X exists, when, in fact, it was deleted by client #2.

    The only way I can think of to support what you seem to be talking about is using some sort of callback methodology, so that when client #2 updates record X, it automagically updates on client #1's screen. IMO, that's way outside of scope.

    M
     
    Dan Murphy
    Ranch Hand
    Posts: 126
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Hi Max,

    My sole concern is ensuring that client #1 cannot read a record while client #2 is updating it - this is what I consider to be a 'dirty' read. The following scenario:

    If client #1 reads locks-reads-unlocks record X, then client #2, say, lock-deletes-unlocks record X, then client #1 reads locks-read-unlocks record X+1. Client #1 is still getting a 'dirty' read of the entire DB, even if the read of a given record wasn't dirty at the time it was read. That is, client #1 will think that record X exists, when, in fact, it was deleted by client #2.



    I consider to be a 'non-repeatable' read, which I'm happy to allow. I think we're agreed that the locking scheme I proposed will prevent (what I call) dirty reads, but are possibly just using different terminology?

    Best Wishes,
    Dan
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Dan Murphy:
    Hi Max,

    My sole concern is ensuring that client #1 cannot read a record while client #2 is updating it - this is what I consider to be a 'dirty' read.



    Dan: yes, I agree that your concern is addressed, but not to any practical benefit, as I understand it. That is, the effect of a dirty record read is achieved(at a large efficiency cost), but reality of a dirty database read is not.

    M
     
    It's a tiny ad only because the water is so cold.
    Gift giving made easy with the permaculture playing cards
    https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
    reply
      Bookmark Topic Watch Topic
    • New Topic