Discussions

EJB design: Handling Concurrent users for avoiding dirty reads

  1. A very basi query regarding how to avoid dirty reads in an application, for example
    Time 00:00 person A retrieves a record onto a jsp.
    Time 00:01 person B retrieves the same record onto his browser
    Time 00:05 person B changes the record and updates the same onto the database
    Time 00:10 person A changes the OLD record and updates the same onto the database

    This was the user has updated the old record and overwritten the changes done by the first user without seeing them.
    So how do we ensure that this prblem doesnt occur?
    EJBs support the TXN_SERIALIZABLE mode which is supoosed to prevent these dirty reads if the support is available in RDBMS.
    Could anyone please explain how this attribute solves the problem of dirty reads, does it locks the records and the record is not available for simple reads also or is it something else?In addition to setting this attribute in the EJB, do we need to take care of this using timestamps in our applications(comparing time of retrieval and time of updation etc)
    thanx in advance

  2. Forget about RDBMS, JTS targets EJB objects, not database tables. Database records usually have nothing to do with locking, the EJBs themselves get locked when a method marked for transaction is invoked, as long as as the client request is being served by the container. During this time, other clients trying to access the EJB will wait until the processing finishes, when the the object transactions are mirrored onto the data store and EJB locks are revoked.

    Timestamp you EJBs and use the timestamp to validate user modified data. Take care when deciding which timestamps to store, though; most of the times you don't need to store them.
  3. Serializable isolation level does stop dirty reads, but only during a transaction.

    In your scenario, it would be *possible* to have a client managed transaction which locked the data from when person A reads it, to when person A writes it, but this would be a bad idea because the transaction may be open a long time, consuming a DB connection. In fact the user may simply close their browser and never send another request!

    A better solution is to use 'optimistic locking', which means that when person A (in your scenario) tries to save their changes your application detects that the data has been updated, and presents them with an error message.

    The common ways of doing this are to have a column in each table for a timestamp or version number, and to read this column before deciding whether the update can be made, or to use the version number which was read originally in the where clause of the update.

    Note that the read timestamp and write update operations must be in the same transaction, and that the read must be 'for update', otherwise there is still a race condition.

    Tom
  4. If you really, really have to keep the timestamp in the data store, you have to do an atomic update and not "read timestamp, write update". The way to do it is to include the timestamp in the WHERE clause of the UPDATE statement:

    UPDATE xbeanstore SET foo=bar, timeStamp=newTimeStamp
      WHERE OID=xxx and timeStamp=oldTimeStamp