mysql database | lock related

Mysql database lock related introduction

1. The type of lock

First divide the mysql lock:

  1. According to the granularity of locks: row locks, table locks, page locks
  2. Divided according to the way the lock is used: shared locks, exclusive locks (an implementation of pessimistic locks)
  3. There are also two types of ideological locks: pessimistic locks and optimistic locks.
  4. There are several row-level lock types in InnoDB: Record Lock, Gap Lock, Next-key Lock
    1. Record Lock: Lock on the index record
    2. Gap Lock: gap lock
    3. Next-key Lock:Record Lock+Gap Lock

1.1 Row lock

Row-level locks are the most granular locks in Mysql, and they only exist in InnoDB, which means that they are only locked for the row of the current operation. Row-level locks can greatly reduce conflicts in database operations. The locking granularity is the smallest, but the locking overhead is also the largest. There may be a deadlock situation. Row-level locks are divided into shared locks and exclusive locks according to their usage.


Row locks are divided into shared locks and exclusive locks

1.1.1 Shared lock usage (S lock read lock) :

If transaction T adds S lock to data object A, transaction T can read A but cannot modify A. Other transactions can only add S lock to A, but cannot add X lock until T releases the S lock on A. This ensures that other transactions can read A, but cannot make any changes to A before T releases the S lock on A.

select ... lock in share mode;

Shared lock is to allow multiple threads to acquire a lock at the same time, and a lock can be owned by multiple threads at the same time.


1.1.2 Exclusive lock usage (X lock write lock) :

If transaction T adds X lock to data object A, transaction T can read A or modify A , and other transactions cannot add any locks to A until T releases the lock on A. This ensures that other transactions can no longer read and modify A before T releases the lock on A.

Exclusive locks, also known as exclusive locks, can only be held by one thread at a certain time, and other threads must wait for the lock to be released before acquiring the lock.

In order to allow row locks and table locks to coexist and implement a multi-granularity lock mechanism, InnoDB also has two internally used intention locks (Intention Locks), both of which are table locks :

  • Intentional shared lock (IS): The transaction intends to add a row shared lock to a data row, and the transaction must first obtain the IS lock of the table before adding a shared lock to a data row.
  • Intentional exclusive lock (IX): The transaction intends to add an exclusive lock to a data row, and the transaction must first obtain an IX lock of the table before adding an exclusive lock to a data row.

Compatibility of lock modes:img

1.1.3 Intent lock related

  • The intention lock is automatically added by InnoDB without user intervention.

  • For UPDATE, DELETE and INSERT statements, InnoDB will automatically add exclusive locks (X) to the data sets involved;

  • For ordinary SELECT statements, InnoDB will not add any locks;
    transactions can explicitly add shared locks or exclusive locks to the record set through the following statement:

    • Shared lock SELECT * FROM table_name WHERE ...LOCK IN SHARE MODE(S): . Other sessions can still query the record, and can also add share modea shared lock to the record . But if the current transaction needs to update the record, it is likely to cause a deadlock.
    • Exclusive lock (the SELECT * FROM table_name WHERE ... FOR UPDATEX-): . Other sessions can query the record, but cannot add a shared lock or exclusive lock to the record, but wait for the lock to be obtained

  • Implicit lock:

InnoDB uses a two-phase lock protocol during transaction execution:

  1. Locking can be performed at any time, and InnoDB will automatically lock when needed according to the isolation level;
  2. The lock is released only when commit or rollback is executed, and all locks are released at the same time .
  • Explicit lock:

  • https://zhuanlan.zhihu.com/p/29150809 Reposted from this article for more details

select ... lock in share mode //共享锁 
select ... for update //排他锁 

select lock in share modeThe function of the: in share mode clause is to add a share lock to the data found. This means that other transactions can only perform simple select operations on these data, and cannot perform DML operations. select *** lock in share modeUsage scenario: In order to ensure that the data you find is not being modified by other transactions, that is to say, ensure that the data you find is the latest data and not allow others to modify the data. But that she may not be able to modify data, because there may be other matters also use these data in share modethe way on the S lock.

select *** for update Usage scenario: In order to ensure that the data you find is the latest data, and the data you find is only allowed to be modified by yourself, you need to use the for update clause.

The difference between for update and lock in share mode:

  1. The previous one is an exclusive lock (X lock). Once a transaction acquires this lock, other transactions cannot perform for update on the data;
  2. The latter is a shared lock, multiple transactions can perform lock in share mode on the same data at the same time.

1.1.4 InnoDB row lock implementation

  • InnoDB row locks are implemented by locking the index items on the index. MySQL is different from Oracle, which is implemented by locking the corresponding data rows in the data block. InnoDB's row lock implementation feature means: Only when data is retrieved through index conditions, InnoDB will use row-level locks, otherwise, InnoDB will use table locks!
  • Whether using primary key indexes, unique indexes or ordinary indexes, InnoDB will use row locks to lock data.
  • Row locks can only be used if the execution plan actually uses the index: even if the index field is used in the condition, whether to use the index to retrieve data is determined by MySQL by judging the cost of different execution plans. If MySQL considers the full table scan efficiency Higher, for example, for some very small tables, it will not use indexes, in this case InnoDB will use table locks instead of row locks. Therefore, when analyzing lock conflicts, don't forget to check the SQL execution plan (you can check the SQL execution plan through explain) to confirm whether the index is actually used. (More reading: MySQL index summary )
  • Because MySQL row locks are locks for indexes, not records, although multiple sessions access records of different rows, if the same index key is used, there will be lock conflicts (after using these The indexed session needs to wait for the indexed session to release the lock before acquiring the lock). Pay attention to this when applying design.

1.2 Table lock

Table-level locks are the largest granular locks in mysql locks, which means that the current operation locks the entire table, and the resource overhead is less than row locks, and there will be no deadlocks, but the probability of lock conflicts is high . Supported by most mysql engines, both MyISAM and InnoDB support table-level locks, but InnoDB defaults to row-level locks.

Shared lock usage :

LOCK TABLE table_name [ AS alias_name ] READ

Exclusive lock usage :

LOCK TABLE table_name [AS alias_name][ LOW_PRIORITY ] WRITE

Unlock usage :

unlock tables;

1.3 Page lock

Page-level locks are a type of lock that has a locking granularity between row-level locks and table-level locks in MySQL. Table-level locking is fast, but there are many conflicts, and row-level conflicts are few, but the speed is slow. Therefore, a compromised page level is taken, and a set of adjacent records is locked at a time. BDB supports page-level locks

1.4 Pessimistic lock/optimistic lock

1.4.1 Pessimistic lock

In relational database management systems, pessimistic concurrency control (also known as "pessimistic lock", Pessimistic Concurrency Control, abbreviated "PCC") is a method of concurrency control. It can prevent a transaction from modifying data in a way that affects other users. If an operation performed by a transaction applies a lock to a row of data, only when the transaction releases the lock, other transactions can perform operations that conflict with the lock. Pessimistic concurrency control is mainly used in environments with intense data contention, and in environments where the cost of using locks to protect data when concurrency conflicts occurs is lower than the cost of rolling back transactions.


The implementation process of pessimistic locking:
Before modifying any record, try to add exclusive locking to the record.

  1. If the lock fails, indicating that the record is being modified, the current query may have to wait or throw an exception . The specific response method is determined by the developer according to actual needs.
  2. If the lock is successfully locked, then the record can be modified, and the transaction will be unlocked after the transaction is completed.
    • In the meantime, if there are other operations that modify the record or add an exclusive lock, it will wait for us to unlock it or throw an exception directly.

Use pessimistic lock in mysql/InnoDB

First of all, we have to turn off the autocommit attribute in mysql, because mysql uses auto-commit mode by default, which means that when we perform a sql operation, mysql treats this operation as a transaction and automatically commits the operation.

1.开始事务
begin;/begin work;/start transaction; (三者选一就可以)
2.查询出商品信息
select ... for update;
4.提交事务
commit;/commit work;

This is illustrated by the following example:

1. When you manually add exclusive locks, but do not turn off autocommit in mysql.

SESSION1:
mysql> select * from user for update;
+----+------+--------+
| id | name | psword |
+----+------+--------+
|  1 | a    | 1      |
|  2 | b    | 2      |
|  3 | c    | 3      |
+----+------+--------+
3 rows in set

这里他会一直提示Unknown
mysql> update user set name=aa where id=1;
1054 - Unknown column 'aa' in 'field list'
mysql> insert into user values(4,d,4);
1054 - Unknown column 'd' in 'field list'

2. Normal process

窗口1:
mysql> set autocommit=0;
Query OK, 0 rows affected
我这里锁的是表
mysql> select * from user for update;
+----+-------+
| id | price |
+----+-------+
|  1 |   500 |
|  2 |   800 |
+----+-------+
2 rows in set

窗口2:
mysql> update user set price=price-100 where id=1;
执行上面操作的时候,会显示等待状态,一直到窗口1执行commit提交事务才会出现下面的显示结果
Database changed
Rows matched: 1  Changed: 1  Warnings: 0

窗口1:
mysql> commit;
Query OK, 0 rows affected
mysql> select * from user;
+----+-------+
| id | price |
+----+-------+
|  1 |   400 |
|  2 |   800 |
+----+-------+
2 rows in set

The above example shows the principle of exclusive locks: a lock can only be occupied by one thread at a certain time, and other threads must wait for the lock to be released before acquiring the lock or performing data operations.


1.4.2 Optimistic Locking

Optimistic Locking (Optimistic Locking) Relative to pessimistic locking, the assumption of optimistic locking believes that data will not cause conflicts under normal circumstances. Therefore, when the data is submitted and updated, the data conflicts will be formally detected . If conflicts are found , Let the user return the wrong information and let the user decide how to do it.

Compared with pessimistic locking, optimistic locking does not use the locking mechanism provided by the database when processing the database. The general way to achieve optimistic locking is to record the data version.

数据版本 : 为数据增加的一个版本标识。当读取数据时,将版本标识的值一同读出,数据每更新一次,同时对版本标识进行更新。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的版本标识进行比对,如果数据库表当前版本号与第一次取出来的版本标识值相等,则予以更新,否则认为是过期数据。


Advantages and disadvantages of optimistic lock:

  1. Advantages: Any locks and deadlocks. Fast efficiency
  2. Disadvantages: If both transactions read a certain row of the database and write it back to the database after modification, a problem is encountered at this time.

1.5 Record Lock、Gap Lock、Next-key Lock锁

1.5.1 Record Lock

A single index is locked, and record lock always locks the index, not the data itself . If there is no index in the innodb table, a hidden clustered index is automatically created, and it is this clustered index that is locked. So when a SQL does not take any index, then X lock will be added after each clustered index. This is similar to a table lock, but in principle it should be completely different from a table lock.

1.5.2 Gap Lock

The gap lock is to add a lock between the gaps of the index, which is the main reason why the Repeatable Read isolation level can prevent phantom reads.

Detailed explanation about phantom reading


InnoDB gap lock:

When we retrieve data using range conditions instead of equal conditions and request shared or exclusive locks, InnoDB will lock the index entries of existing data records that meet the conditions; for records whose key values ​​are within the condition range but do not exist, It is called a "gap (GAP)", and InnoDB will also lock this "gap". This lock mechanism is the so-called gap lock (Next-Key lock).

Obviously, when using range conditions to retrieve and lock records, InnoDB's locking mechanism will block the concurrent insertion of key values ​​within the qualified range, which often causes serious lock waits. Therefore, in actual application development, especially for applications with more concurrent insertions, we must try to optimize business logic, try to use equal conditions to access and update data, and avoid using range conditions.


What is a gap lock, directly through an example:

mysql> select * from product_copy;
+----+--------+-------+-----+
| id | name   | price | num |
+----+--------+-------+-----+
|  1 | 伊利   |    68 |   1 |
|  2 | 蒙牛   |    88 |   1 |
|  6 | tom    |  2788 |   3 |
| 10 | 优衣库 |   488 |   4 |
+----+--------+-------+-----+
其中id为主键 num为普通索引
窗口A:
mysql> select * from product_copy where num=3 for update;
+----+------+-------+-----+
| id | name | price | num |
+----+------+-------+-----+
|  6 | tom  |  2788 |   3 |
+----+------+-------+-----+
1 row in set

窗口B:
mysql> insert into product_copy values(5,'kris',1888,2);
这里会等待  直到窗口A commit才会显示下面结果
Query OK, 1 row affected

但是下面是不需要等待的
mysql> update product_copy set price=price+100 where num=1;
Query OK, 2 rows affected
Rows matched: 2  Changed: 2  Warnings: 0
mysql> insert into product_copy values(5,'kris',1888,5);
Query OK, 1 row affected

Through the above example, it can be seen that the function of Gap lock is to add a lock between the gap of 1, 3. And it's not that the table is locked. I can update the data with num=1 and 5. It can be seen that the locked range is (1,3]U[3,4).


Why is the gap lock the main reason to prevent phantom reads under the RR isolation level?

The way to solve the phantom read is very simple, that is, when the transaction is performing the current read, it is necessary to ensure that other transactions cannot perform data operations within the range that meets the current read conditions.

According to the order of the index, we can infer from the above example that the data that meets the where condition can only be inserted into the two intervals num=(1,3]U[3,4), as long as we combine these two intervals Locked, then no phantom reading will occur.


Extension:

  1. Primary key index/unique index + current read will add Gap lock?

    窗口A:
    mysql> select * from product_copy where id=6 for update;
    +----+------+-------+-----+
    | id | name | price | num |
    +----+------+-------+-----+
    |  6 | tom  |  2788 |   3 |
    +----+------+-------+-----+
    
    窗口B:并不会发生等待
    mysql> insert into product_copy values(5,'kris',1888,3);
    Query OK, 1 row affected
    

    The example shows the reason for the row lock. I only locked the row data with id=6. To explain it with the principle of Gap lock: Because there is only one value for the primary key index and the unique index, there is only one row that meets the retrieval conditions. , So there will be no phantom reading, so Gap lock will not be added.


  2. Whether to add Gap lock through range query

    窗口A:
    mysql> select * from product_copy where num>3 for update;
    +----+--------+-------+-----+
    | id | name   | price | num |
    +----+--------+-------+-----+
    | 10 | 优衣库 |   488 |   4 |
    +----+--------+-------+-----+
    
    窗口B:会等待
    mysql> insert into product_copy values(11,'kris',1888,5);
    Query OK, 1 row affected
    不会等待
    mysql> insert into product_copy values(3,'kris',1888,2);
    Query OK, 1 row affected
    

    In fact, the reason is the same, as long as the search conditions are met, the Gap lock will be added.


Will Gap be added to the current read where the search condition does not exist?

窗口A:
mysql> select * from product_copy where num=5 for update;
Empty set

窗口B:64都会等待
mysql> insert into product_copy values(11,'kris',1888,6);
Query OK, 1 row affected

mysql> insert into product_copy values(11,'kris',1888,4);
Query OK, 1 row affected

The same reason will lock the interval (4,5]U[5,n)


Range query

It will be a little different here

窗口A:
mysql> select * from product_copy where num>6 for update;
Empty set
窗口B:84 都会锁住
mysql> insert into product_copy values(11,'kris',1888,4);
Query OK, 1 row affected

mysql> insert into product_copy values(11,'kris',1888,8);
Query OK, 1 row affected

The above 2 examples show that when you query data that does not exist, mysql will lock all possible intervals.

1.5.3 Next-Key Lock

This lock mechanism is actually a combination of the previous two locks, which not only locks the record itself but also locks the gap between the indexes.

Guess you like

Origin blog.csdn.net/weixin_40597409/article/details/115273603