Results 1 to 2 of 2

Thread: synchronized methods in transactional business logic beans

  1. #1

    Default synchronized methods in transactional business logic beans

    Hi.
    I post this thread to talk about transactional behavior.
    I'm using Spring 2.5.
    I have (as almost every body) the transactional behavior in the business objects layer. Also, I'm using the Spring 2.0 tx namespace to do it.
    Of course, it works well.
    I have a method in one business object that returns a long data.
    To simplify, let's think that the method is

    public long getNumber(){....}

    It's important to note that this method calls a DAO to update a field of the number (the number has a table in the database) to change its status (the number passes from an available status to a reserved status). The idea is that changing the status, the number is reserved for a client, and it's not possible to give that number to another client.

    In production, I had a lot of concurrency (there is a web service that requests this business method several times a second). Then, I got the same result (the same number) with some of the requests and this was not the result expected.

    So, my first fix was to introduce the synchronized, so the method was finally

    public synchronized long getNumber(){....}

    I thought this was a good idea, because the business object was in the Spring container (with only one instance in the container of this object).
    Then, all was good in a high percentage, but suddenly, a very few of the calls to the method returned the same number again. Most of the concurrent calls worked well, but few worked bad.

    I'd like to know the reason of this. By the way, the isolation level of the transaction is DEFAULT(<tx:method name="*" isolation="DEFAULT" />).
    Maybe, is it about the AOP behaviour? I.e., the synchronized is only for the target class and not for the proxied class that manages the transactional behavior for the target class.

    What's your opinion about this? (Bad operation with synchronized in few requests)

    Thank you very much in advance.

    P.D.: FInally, I fixed the problem introducing locks in a database level. I'm using Oracle, so I used "SELECT .... FOR UPDATE" before updating the status of the number. In any case, I'd like to know the possible reason of the results I get. Another possibility could be set the isolation level to serializable, for example, but I didn't want to lower the performance too much. Maybe, this isolation level could lock all the table. With "SELECT.. FOR UPDATE" I can only lock the rows I want.

  2. #2
    Join Date
    Nov 2004
    Location
    Hilversum - The Netherlands
    Posts
    1,054

    Default

    P.D.: FInally, I fixed the problem introducing locks in a database level. I'm using Oracle, so I used "SELECT .... FOR UPDATE" before updating the status of the number. In any case, I'd like to know the possible reason of the results I get.
    'select for ... update' is the easiest solution for Oracle. If you are using a more traditional database like SQL Server 2000, the REPEATABLE_READ would also automatically lock the read records to prevent updates.

    Another possibility could be set the isolation level to serializable, for example, but I didn't want to lower the performance too much.
    The implementation of concurrency control in database influences performance a lot. With classic lock based database it could lead to lock escalation. But on modern databases like Oracle that uses MVCC, multiple versions of the data can be reconstructed and thereby reducing the need for locking (readers don't block writers, writers don't block readers). But on the other hand, SERIALIZED transactions under oracle can fail. This is caused by an optimistic locking failure : ORA-08177. This won't happen with traditional lock based database. So on your case you might need to handle this error by retrying the transaction.

    Maybe, this isolation level could lock all the table. With "SELECT.. FOR UPDATE" I can only lock the rows I want.
    SERIALIZED isolation level doesn't need to lock the entire table in Oracle unlike lock oriented databases. That it is why it allows for a much higher concurrency.

    PS:Locks inside the JVM are not distributed, so what happens on one node doesn't influence other nodes. So if you are using multiple vm's connecting to the db, this could be the cause. Are you using proxies or bytecode weaving (something that is not always clear for me at first glance.. Spring can be a littlebit messy).
    Last edited by Alarmnummer; Jul 5th, 2008 at 02:11 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •