Summary and practice of mysql optimistic locking

The previous article "MySQL Pessimistic Lock Summary and Practice" talked about MySQL pessimistic locks, but pessimistic locks are not suitable for any scenario, and they also have some shortcomings, because pessimistic locks are mostly implemented by the database lock mechanism. to ensure maximum exclusivity of operations. If the locking time is too long, other users cannot access for a long time, which affects the concurrent access of the program, and also has a great impact on the database performance overhead, especially for long transactions, such overhead is often unbearable. Therefore, in contrast to pessimistic locks, we have optimistic locks. For details, please refer to the following introduction:

Optimistic lock introduction:
Optimistic Locking Compared with pessimistic locks, optimistic locks assume that data will not cause conflicts in general, so in the data When the update is submitted, the data conflict will be formally detected. If a conflict is found, the user's wrong information will be returned to let the user decide what to do. So how do we implement optimistic locking? Generally speaking, there are two ways:
1. Use the data version (Version) record mechanism to implement, which is the most commonly used implementation of optimistic locking. What is a data version? That is, adding a version identifier to the data is generally realized by adding a numeric "version" field to the database table. When reading data, read the value of the version field together, and add one to the version value every time the data is updated. When we submit the update, compare the current version information of the corresponding record in the database table with the version value taken out for the first time. If the current version number of the database table is equal to the version value taken out for the first time, it will be updated. Otherwise, it is considered to be expired data. Use the following figure to illustrate:
As shown in the figure above, if the update operations are performed in sequence, the version of the data will be incremented sequentially, and there will be no conflict. However, if there are different business operations that modify the same version of the data, the operation submitted first (B in the figure) will update the data version to 2. When A submits the update after B, it finds that the version of the data has been modified. , then the update operation of A will fail.

2. The second implementation method of optimistic locking is similar to the first one. It also adds a field to the table that needs optimistic locking control. The name does not matter. The field type uses timestamp, which is similar to the above version. When the update is submitted, check the timestamp of the data in the current database and compare it with the timestamp obtained before the update. If it is consistent, it is OK, otherwise it is a version conflict.

Example of use: Take MySQL InnoDB as an example,
or take the previous example: there is a field status in the goods table. If the status is 1, it means that the product has not been ordered, and if the status is 2, it means that the product has been ordered. When placing an order for a product, you must ensure that the product status is 1. Suppose the id of the item is 1.

The ordering operation includes 3 steps:
1. Query the product information
select (status, status, version) from t_goods where id=#{id}
2. Generate an order based on the product information
3. Modify the product status to 2
update t_goods
set status=2 ,version=version+1
where id=#{id} and version=#{version};

Then in order to use optimistic locking, we first modify the t_goods table, add a version field, and the default version value of the data is 1.
The initial data of the t_goods table is as follows:
Sql code Favorite code
mysql> select * from t_goods; 
+----+--------+------+---------+ 
| id | status | name | version | 
+----+-------+------+---------+ 
| 1 | 1 | props | 1 | 
| 2 | 2 | equip| 2 | 
+----+--------+------+---------+ 
2 rows in set 
 
mysql> 
for optimistic locking For the implementation, I use MyBatis to practice, as follows:
Goods entity class:
Java code Collection code
/**
* ClassName: Goods 
* Function: commodity entity. 
* date: 2013-5-8 09:16:19 am 
* @ author [email protected]
*/ 
public class Goods implements Serializable { 
 
    /**
     * serialVersionUID: Serialization ID.
     */ 
    private static final long serialVersionUID = 6803791908148880587L; 
     
    /**
     * id: primary key id.
     */ 
    private int id; 
     
    /**
     * status: product status: 1 has not placed an order, 2 has placed an order.
     */ 
    private int status; 
     
    /**
     * name: product name.
     */ 
    private String name; 
     
    /**
     * version: product data version number.
     */ 
    private int version; 
     
    @Override 
    public String toString(){ 
        return "good id:"+id+",goods status:"+status+" ;,goods name:"+name+",goods version:"+version; 
    } 
 
    //setter and getter 
 

GoodsDao
Java code Favorite code
/**
* updateGoodsUseCAS: Use CAS (Compare and set) to update product information. 
*
* @author [email protected]
* @param goods commodity object
* @return the number of rows affected
*/ 
int updateGoodsUseCAS(Goods goods); 
mapper.xml
Xml code Collection code
 
GoodsDaoTest test class
Java code Collection code
@Test 
public void goodsDaoTest(){ 
    int goodsId = 1; 
    //Query the product information according to the same id and assign it to 2 objects 
    Goods goods1 = this.goodsDao.getGoodsById(goodsId); 
    Goods goods2 = this.goodsDao.getGoodsById(goodsId); 
     
    //Print current commodity information 
    System.out.println(goods1); 
    System.out.println(goods2); 
     
    //Update commodity information 1 
    goods1.setStatus(2);//Modify status to 2 
    int updateResult1 = this.goodsDao.updateGoodsUseCAS(goods1); 
    System.out.println("Modify product information 1"+(updateResult1==1?"Success" :"Failed")); 
     
    //Update product information 2 
    goods1.setStatus(2);//Modify status to 2 
    int updateResult2 = this.goodsDao.updateGoodsUseCAS(goods1); 
    System.out.println("Modify goods Information 2"+(updateResult2==1?"success":"failure")); 

output result:
Shell code Collection code
good id:1,goods status:1,goods name:props,goods version: 1 
good id: 1, goods status: 1, goods name: props, goods version: 1 
Modify product information 1 Successfully 
modify product information 2 Failure 
description:
In the GoodsDaoTest test method, we simultaneously find out the data of the same version, assign them to different goods objects, and then modify the good1 object first and then perform the update operation, which is successful. Then we modify goods2, and the operation fails when the update operation is performed. At this time, the data in the t_goods table is as follows:
Sql code Favorite code
mysql> select * from t_goods; 
+----+--------+------+--------- + 
| id | status | name | version | 
+----+--------+------+---------+ 
| 1 | 2 | props | 2 | 
| 2 | 2 | equip| 2 | 
+----+-------+------+---------+ 
2 rows in set 
 
mysql>  
we can It can be seen that the data version with id 1 has been modified to 2 during the first update. Therefore, when we update good2, the update where condition does not match, so the update will not succeed. The specific sql is as follows:
Sql code Collection code
update t_goods  
set status=2,version=version+1 
where id=#{id} and version=# {version}; 
This way we implement optimistic locking

The above is my summary and practice of MySQL optimistic locking.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326716538&siteId=291194637