Optimistic locks and pessimistic locks of Hibernate and Their Applications

Source: Internet
Author: User

Lock(Locking)
During the implementation of business logic, data access needs to be exclusive. For example, in the daily final computing process of the financial system, we want to process the data at a cut-off time point instead of the settlement process (which may be several seconds, or several hours), and the data changes again. At this point, we need to use some mechanisms to ensure that the data will not be modified by the outside world during an operation. This mechanism is called a "Lock" here ", locks the selected target data so that it cannot be used by others.ProgramModify. Hibernate supports two lock mechanisms: Pessimistic locking and Optimistic Locking )".

Pessimistic lock(Pessimistic locking)
Pessimistic lock, as it is called, refers to a conservative attitude towards data being modified by the outside world (including other transactions of the current system, as well as transactions from the external system). Therefore, the data is locked during the entire data processing process. Pessimistic locks often rely on the locks provided by the database (and only the locks provided by the database layer can truly guarantee the exclusive data access; otherwise, even if the locking mechanism is implemented in the system, it cannot be ensured that the external system will not modify the data ).
A typical pessimistic lock call that relies on databases:
Select * from account where name = "Erica" for update
This SQL statement locks all records that meet the search criteria (name = "Erica") in the account table. Before the transaction is committed (the lock in the transaction process will be released when the transaction is committed), these records cannot be modified by the outside world. The pessimistic lock of Hibernate is also implemented based on the database lock mechanism.
The followingCodeLocks the query records:

String hqlstr = "from Tuser as user where user. name = 'erica '"; query = session. createquery (hqlstr); query. setlockmode ("user", lockmode. upgrade); // lock list userlist = query. list (); // execute the query to obtain data

Query. setlockmode locks the records corresponding to a specific alias in the query statement (we have specified an alias "user" for the Tuser class). Here, all the returned user records are locked.
Observe the SQL statements generated by hibernate during runtime:

 
<Span style = "font-size: 13px;"> select tuser0 _. ID as ID, tuser0 _. name as name, tuser0 _. group_idas group_id, tuser0 _. user_type as user_type, tuser0 _. sex as sexfrom t_user tuser0 _ Where (tuser0 _. name = 'erica ') for update </span>

Here, Hibernate implements the pessimistic lock mechanism by using the for update clause of the database.
The locking modes of hibernate include:
Lockmode. None:No lock mechanism.
Lockmode. Write:Hibernate automatically obtains the insert and update records.
Lockmode. Read:Hibernate automatically obtains the read records.
The above three lock mechanisms are generally used internally by hibernate. For example, in order to ensure that objects in the update process are not modified by the outside world, Hibernate will automatically add the write lock to the target object in the implementation of the Save method.
Lockmode. Upgrade:Lock the database by using the for update clause.
Lockmode. upgrade_nowait:The specific implementation of Oracle uses the Oracle for update Nowait clause to implement locking.
The above two locking mechanisms are commonly used at the application layer. The locking is generally implemented through the following methods:
Criteria. setlockmode
Query. setlockmode
Session. Lock

Note: Only when the lock is set before the query starts (that is, before the hiberate generates the SQL statement) Will the database lock mechanism be used for the lock process. Otherwise, data has been loaded through select SQL that does not contain the for update clause. The so-called database locking is impossible.

Optimistic lock (Optimistic Locking)
Compared with pessimistic locks, optimistic locks adopt a more loose locking mechanism. Pessimistic locks are implemented by the database lock mechanism in most cases to ensure maximum operation exclusiveness. However, there is a large amount of database performance overhead, especially for long transactions, which is often unbearable.
For example, if a financial system uses a pessimistic lock mechanism, when an operator reads user data and modifies the user data based on the user data, such as changing the user account balance, this means that the database record is always locked during the entire operation (from the operator to the entire process of reading the number, starting the modification, and submitting the Modification result, or even the time when the operator goes through coffee cooking, we can imagine what the consequences would be if we were dealing with hundreds of thousands of concurrent jobs. The Optimistic Locking Mechanism solves this problem to some extent. Optimistic locks are mostly implemented based on the data version record mechanism. What is the data version? Add a version ID for the data. In the database table-based version solution, you can add a "version" field to the database table.
When reading the data, read the version number together, and then add one to the version number when updating the data. In this case, the version data of the submitted data is compared with the current version information recorded in the database table. If the submitted data version number is greater than the current version number of the database table, it is updated, otherwise, expired data is considered.
For the example of modifying user account information above, assume that there is a version field in the account information table in the database, the current value is 1, and the current account balance field (balance) is $100.
1 operator A reads it (version = 1) and deducts $50 ($100-$50) from its account balance ).
2 during operator A's operations, operator B also reads this user information (version = 1) and deducts $20 ($100-$20) from its account balance ).
3. Operator A completes the modification and submits the data version number plus one (version = 2), along with the account balance after deduction (balance = $50), to the database for updates, at this time, because the submitted data version is later than the current version of the database record, the data is updated, and the database record version is updated to 2.
4. When operator B completes the operation and tries to submit data (balance = $80) to the database with version 1 (version = 2), it finds that, the version number of the data submitted by operator B is 2, and the current version of the database record is 2, which does not meet the optimistic lock policy of "The submitted version must be later than the current version to be updated". Therefore, the submission of operator B is rejected. This avoids the possibility that operator B overwrites operator A's operation results with the old data modification Result Based on version = 1.
From the above example, we can see that the Optimistic Locking mechanism avoids the database lock overhead in long transactions (no database data lock is applied during operator A and operator B operations ), this greatly improves the overall performance of the system with high concurrency. It should be noted that the optimistic lock mechanism is often based on the data storage logic in the system, so it also has certain limitations. In the above example, because the optimistic lock mechanism is implemented in our system, the user balance update operation from the external system is not controlled by our system, so dirty data may be updated to the database. In the system design phase, we should fully consider the possibility of such situations and make appropriate adjustments (for example, implementing Optimistic Locking policies in database storage processes, only the data update path based on this stored procedure is open to the outside, rather than the database table is open to the outside ).
Hibernate has built-in optimistic lock implementation in its data access engine. If you do not need to consider the update operations of the external system on the database, using the transparent optimistic lock provided by hibernate will greatly improve our productivity.
In hibernate, the optimistic-lock attribute of the class descriptor can be used together with the version descriptor.

Now, we add an optimistic lock mechanism to the Tuser in the previous example.
1. First, add the optimistic-lock attribute for the Tuser class descriptor:

 
<Span style = "font-size: 13px;">  

the optimistic-lock attribute has the following optional values:
none: no optimistic lock
Version: Optimistic Locking through version mechanism
dirty: Optimistic Locking is achieved by checking changed attributes
All: optimistic lock implemented by checking all attributes
the optimistic Lock Mechanism Implemented by version is officially recommended by hibernate., it is also the only lock mechanism in hibernate that is still effective when the data object is modified out of the session. Therefore, we generally choose the version method as the hibernate optimistic lock implementation mechanism.
2. Add a version attribute descriptor

<Span style = "font-size: 13px;">  

Note that the version node must appear after the ID node. Here, we declare a version attribute to store the user's version information and store it in the version field of the Tuser table.
At this point, if we try to write a piece of code to update the record data in the Tuser table, such:
Criteria = session. createcriteria (Tuser. Class );
Criteria. Add (expression. eq ("name", "Erica "));
List userlist = criteria. List ();
Tuser user = (Tuser) userlist. Get (0 );
Transaction Tx = session. begintransaction ();
User. setusertype (1); // update the usertype Field
TX. Commit ();
Every time we update the Tuser, we can find that the version in the database is increasing progressively. If we try to start another session before Tx. Commit and operate the user named Erica to simulate concurrent updates:
Session session = getsession ();
Criteria = session. createcriteria (Tuser. Class );
Criteria. Add (expression. eq ("name", "Erica "));
Session session2 = getsession ();
Criteria criteria2 = session2.createcriteria (Tuser. Class );
Criteria2.add (expression. eq ("name", "Erica "));
List userlist = criteria. List ();
List userlist2 = criteria2.list (); Tuser user = (Tuser) userlist. Get (0 );
Tuser user2 = (Tuser) userlist2.get (0 );
Transaction Tx = session. begintransaction ();
Transaction tx2 = session2.begintransaction ();
User2.setusertype (99 );
Tx2.commit ();
User. setusertype (1 );
TX. Commit ();
Run the preceding Code. The Code throws a staleobjectstateexception exception at Tx. Commit () and indicates that the version check fails. The current transaction is trying to submit an expired data. By capturing this exception, we can handle it when optimistic lock validation fails.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.