MySQL pessimistic locking and optimistic locking

Pessimistic locking

Pessimistic locking (Pessimistic Lock), by definition, is very pessimistic, pick up data every time think others will modify, so every time she took the data will be locked, so people want to take this data will block until it takes to lock.

Pessimistic locking: assume concurrency violation occurs, the shield may be in violation of all operational data integrity.

Java synchronized belongs to an implementation pessimistic locking, each thread to acquire a lock to modify data, ensuring that only one thread can manipulate the data, other threads will be block.

Pessimistic locking

Optimistic locking (Optimistic Lock), by definition, is very optimistic, pick up data every time that others are not modified, so it will not be locked, but when submitted updated during this time will determine what others do not have to update this data. Optimistic locking applies to read how much to write scenarios, this can increase the throughput

Optimistic locking: Suppose concurrency conflicts do not occur, just check at the time of the commit operation is a violation of data integrity

Optimistic locking in general the following two ways:

  1. Using data version (Version) recording mechanism to achieve, which is the most common kind of optimistic locking implementation. What version of the data? That is, a version identifier of data increases, is generally achieved by adding a digital type of database table "version" field. When reading data, the version value of the field is read out with the data updated every time, this version by one. When we submit updated information to determine the current version of the database table with the first taken out of the version corresponding to the value recorded for comparison, if the current version of the database table version number equal to the value of the first taken out, then be updated, otherwise considered stale data.
  2. Using the timestamp (timestamp). The second implementation optimistic locking and the first is almost the same in the required table optimistic locking control to add a field, the name does not matter, field type using the timestamp (timestamp), and the above version is similar, but also in the update submitted you can check the current time stamp data in the database and update themselves before taking to the timestamp comparison, if the same is OK, otherwise version conflicts.

One kind of atomic package is optimistic locking in Java JUC implementation, AtomicInteger increment to achieve thread-safe operations through CAS (Compare And Set).

MySQL InnoDB uses a two-phase locking protocol (two-phase locking protocol). During the transaction, the lock can be executed at any time, locks are released only when a COMMIT or ROLLBACK, and all locks are released at the same time. In front of the lock are described implicitly locked, InnoDB will automatically lock when needed based on transaction isolation level.

In addition, InnoDB also supports display lock by specific statements that do not belong to the SQL specification:

  • SELECT ... LOCK IN SHARE MODE
  • SELECT ... FOR UPDATE

Case

Demonstrate the use of optimistic and pessimistic locking by a small case

Consider electricity supplier spike system, to ensure that if the goods are not overbought, to ensure data consistency

Assume that a product table

create table tb_product(
	id int not null auto_increment primary key,
    stock int not null 
)ENGINE=InnoDB DEFAULT CHARSET=utf8

Without considering concurrent modification merchandise inventory pseudocode as follows:

 /**
     * 更新库存(不考虑并发)
     * @param productId
     * @return
     */
public boolean updateStockRaw(Long productId){
    ProductStock product = query("SELECT * FROM tb_product WHERE id=#{productId}", productId);
    if (product.getNumber() > 0) {
        int updateCnt = update("UPDATE tb_product SET stock=stock-1 WHERE id=#{productId}", productId);
        if(updateCnt > 0){    //更新库存成功
            return true;
        }
    }
    return false;
    }

However, this approach may appear oversold problems in case of multiple concurrent threads.

The following demonstrates the use pessimistic locking and optimistic locking to solve this problem.

Use pessimistic locking

/**
     * 更新库存(使用悲观锁)
     * @param productId
     * @return
     */
public boolean updateStock(Long productId){
    //先锁定商品库存记录
    ProductStock product = query("SELECT * FROM tb_product WHERE id=#{productId} FOR UPDATE", productId);
    if (product.getNumber() > 0) {
        int updateCnt = update("UPDATE tb_product SET stock=stock-1 WHERE id=#{productId}", productId);
        if(updateCnt > 0){    //更新库存成功
            return true;
        }
    }
    return false;
}

Use optimistic locking

/**
     * 下单减库存
     * @param productId
     * @return
     */
public boolean updateStock(Long productId){
    int updateCnt = 0;
    while (updateCnt == 0) {
        ProductStock product = query("SELECT * FROM tb_product WHERE product_id=#{productId}", productId);
        if (product.getNumber() > 0) {
            updateCnt = update("UPDATE tb_product SET stock=stock-1 WHERE product_id=#{productId} AND number=#{number}", productId, product.getNumber());
            if(updateCnt > 0){    //更新库存成功
                return true;
            }
        } else {    //卖完啦
            return false;
        }
    }
    return false;
}

Guess you like

Origin www.cnblogs.com/watertreestar/p/11780290.html