MySQL optimistic lock summary and practice (RPM)

Source: Internet
Author: User
Tags cas cdata serialization

The previous article, "MySQL pessimistic lock summary and practice" talked about the MySQL pessimistic lock, but pessimistic lock is not suitable for any scenario, it also has some shortcomings, because pessimistic lock in most cases rely on the lock mechanism of the database implementation, to ensure the maximum degree of exclusivity of the operation. If the lock time is too long, other users can not access for a long time, affecting the program's concurrent access, but also the database performance cost impact is very large, especially for long transactions, such overhead is often unbearable. So, in contrast to pessimistic locking, we have an optimistic lock, see below for details:

Introduction to optimistic Locking:

Optimistic lock (optimistic Locking) relative pessimistic lock, optimistic locking hypothesis that the data generally do not cause conflict, so when the data is submitted to update the data will be formally conflicting or not detected, if a conflict is found, then let the return of the user error information, Let the user decide how to do it. So how do we achieve optimistic locking, there are generally the following 2 ways:

1. Using the data version recording mechanism is implemented, which is the most common way to implement optimistic locking. What is a data version? is to add a version identifier to the data, typically by adding a "version" field of a numeric type to the database table. When the data is read, the value of the version field is read together, and the data is updated each time, adding one to this version value. When we submit an update, the current version of the corresponding record of the database table is judged to be compared with the first fetch, if the current version number of the database table is equal to the first one taken out, it is updated, otherwise it is considered to be outdated data. Use one of the following diagrams to illustrate:

As shown, if the update operation is executed sequentially, the version of the data is incremented sequentially, and no conflict occurs. However, if there are different business operations to modify the same version of the data, then the first commit operation (Figure B) will update the data version to 2, when a after B commits the update found that the data version has been modified, then A's update operation will fail.

2. The second way to achieve optimistic locking is similar to the first one, as well as adding a field to the table that requires optimistic lock control, the name does not matter, the field type uses the timestamp (timestamp), and the above version is like The time stamp of the data in the current database is also checked at the time of the update submission, and the timestamp is compared before the update, if the consistency is OK, otherwise it is the version conflict.

Examples of Use : MySQL InnoDB as an example

Or take the previous example to lift: the commodity goods table has a field Status,status 1 for the product is not under the order, status is 2 for the product has been put orders, then we have to order a product to ensure that the product status is 1. Suppose the product has an ID of 1.

The order operation consists of 3 steps:

1. Check out the product information

Select (Status,status,version) from T_goods where Id=#{id}

2. Generate orders based on product information

3. Change the item status to 2

Update T_goods

Set status=2,version=version+1

Where Id=#{id} and version=#{version};

So in order to use optimistic lock, we first modify the T_goods table, add a version field, the data default version value is 1.

T_goods table initial data is as follows:

SQL code
  1. Mysql> SELECT * from t_goods;
  2. +----+--------+------+---------+  
  3. | ID | Status |  Name | version |
  4. +----+--------+------+---------+  
  5. |      1 | 1 |       Props | 1 |
  6. |      2 | 2 |       Equipment | 2 |
  7. +----+--------+------+---------+  
  8. 2 rows in set
  9. Mysql>
Mysql> SELECT * from t_goods;+----+--------+------+---------+| ID | Status | name | Version |+----+--------+------+---------+|  1 |      1 | Props |       1 | |  2 |      2 | Equipment |       2 |+----+--------+------+---------+2 rows in setmysql>

For the implementation of optimistic locking, I use MyBatis to practice, specifically as follows:

Goods entity classes:

Java code
  1. /**
  2. * Classname:goods <br/>
  3. * Function: Commodity entity. <br/>
  4. * Date:2013-5-8 Morning 09:16:19 <br/>
  5. * @author [email protected]
  6. */
  7. Public class Goods implements Serializable {
  8. /** 
  9. * Serialversionuid: Serialization ID.
  10. */
  11. private Static final long serialversionuid = 6803791908148880587L;
  12. /** 
  13. * ID: PRIMARY key ID.
  14. */
  15. private int id;
  16. /** 
  17. * Status: Commodity: 1 No orders, 2 orders.
  18. */
  19. private int status;
  20. /** 
  21. * Name: Product name.
  22. */
  23. private String name;
  24. /** 
  25. * Version: Product data version number.
  26. */
  27. private int version;
  28. @Override
  29. Public String toString () {
  30. return "Good ID:" +id+", goods Status:" +status+", goods name:" +name+", goods version:" +version;
  31. }
  32. //setter and Getter
  33. }
/** * Classname:goods <br/> * Function: Commodity entity. <br/> * date:2013-5-8 Morning 09:16:19 <br/> * @author [email protected] */public class Goods implements Serializab Le {/** * Serialversionuid: Serialization ID. */private static final Long Serialversionuid = 6803791908148880587l;/** * ID: Primary key ID. */pri vate int id;/** * Status: Item Status: 1 No orders, 2 orders. */private int status;/** * Name: Product name. */private String name;/** * Version: Product data version number. */private int version; @Overridepublic String toString () {return good ID: "+id+", goods Status: "+status+", goods name: "+ Name+ ", goods version:" +version;} Setter and Getter}

Goodsdao

Java code
    1. /**
    2. * Updategoodsusecas: Use CAS (Compare and set) to update product information. <br/>
    3. *
    4. * @author [email protected]
    5. * @param Goods Product Object
    6. * Number of rows affected by @return
    7. */
    8. int Updategoodsusecas (Goods Goods);
/** * Updategoodsusecas: Use CAS (Compare and set) to update product information. <br/> * * @author [email protected] * @param goods Commodity Object * @return The number of rows affected */int Updategoodsusecas (goods goods);

Mapper.xml

XML code
  1. <update id="Updategoodsusecas" parametertype="Goods">
  2. <! [Cdata[
  3. Update T_goods
  4. Set status=#{status},name=#{name},version=version+1
  5. Where Id=#{id} and Version=#{version}
  6. ]]>
  7. </update>
<update id= "Updategoodsusecas" parametertype= "Goods" ><! [Cdata[update t_goodsset Status=#{status},name=#{name},version=version+1where Id=#{id} and Version=#{version}]]> </update>

Goodsdaotest Test class

Java code
  1. @Test
  2. Public void Goodsdaotest () {
  3. int goodsid = 1;
  4. //Query the product information according to the same ID, assign to 2 objects
  5. Goods goods1 = this.goodsDao.getGoodsById (GOODSID);
  6. Goods goods2 = this.goodsDao.getGoodsById (GOODSID);
  7. //Print current product information
  8. System.out.println (GOODS1);
  9. System.out.println (GOODS2);
  10. //Update product information 1
  11. Goods1.setstatus (2); Modify status to 2
  12. int updateResult1 = This.goodsDao.updateGoodsUseCAS (GOODS1);
  13. System.out.println ("Modify product Information 1" + (updateresult1==1?")  Success ":" Failure "));
  14. //Update product Information 2
  15. Goods1.setstatus (2); Modify status to 2
  16. int updateResult2 = This.goodsDao.updateGoodsUseCAS (GOODS1);
  17. System.out.println ("Modify product Information 2" + (updateresult2==1?")  Success ":" Failure "));
  18. }
@Testpublic void Goodsdaotest () {int goodsid = 1;//queries the product information based on the same ID, assigns 2 objects goods GOODS1 = This.goodsDao.getGoodsById ( GOODSID); Goods goods2 = this.goodsDao.getGoodsById (GOODSID);//print Current product information System.out.println (GOODS1); System.out.println (GOODS2);//Update product Information 1goods1.setstatus (2);//Modify status to 2int UPDATERESULT1 = This.goodsDao.updateGoodsUseCAS (GOODS1); SYSTEM.OUT.PRINTLN ("Modify product Information 1" + (updateresult1==1? ") Success ":" Failure ");//Update product Information 2goods1.setstatus (2);//Modify status to 2int UpdateResult2 = This.goodsDao.updateGoodsUseCAS (GOODS1); SYSTEM.OUT.PRINTLN ("Modify product Information 2" + (updateresult2==1? ") Success ":" Failure "));}

Output Result:

Shell Code
    1. Good ID:1,goods Status:1,goods name: prop, goods version:1
    2. Good ID:1,goods Status:1,goods name: prop, goods version:1
    3. Modify product Information 1 success
    4. Modify product Information 2 failed
Good id:1,goods status:1,goods Name: props, goods version:1good id:1,goods status:1,goods Name: props, goods version : 1 Modify Product information 1 successfully modified product Information 2 failed

Description

In the Goodsdaotest test method, we also identify the same version of the data, assign to different goods objects, and then modify the Good1 object and then perform the update operation, the execution succeeds. Then we modify the GOODS2, and the prompt operation fails when the update operation is performed. At this point the data in the T_goods table is as follows:

SQL code
  1. Mysql> SELECT * from t_goods;
  2. +----+--------+------+---------+  
  3. | ID | Status |  Name | version |
  4. +----+--------+------+---------+  
  5. |      1 | 2 |       Props | 2 |
  6. |      2 | 2 |       Equipment | 2 |
  7. +----+--------+------+---------+  
  8. 2 rows in set
  9. Mysql>
Mysql> SELECT * from t_goods;+----+--------+------+---------+| ID | Status | name | Version |+----+--------+------+---------+|  1 |      2 | Props |       2 | |  2 |      2 | Equipment |       

We can see that the data version with ID 1 has been modified to 2 on the first update. So when we update good2, the update where condition already does not match, so the updates will not succeed, the specific SQL is as follows:

SQL code
    1. Update T_goods
    2. Set status=2,version=version+1
    3. Where Id=#{id} and version=#{version};
Update t_goods set Status=2,version=version+1where Id=#{id} and Version=#{version};

So we can achieve an optimistic lock.

MySQL optimistic lock summary and practice (RPM)

Related Article

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.