Understand InnoDB locks in seconds

Re-organized the relationship between locks, locks and transactions, hoping to help you clarify some knowledge points. If no special instructions are given in this article, the default is the repeatable read isolation level.

Pessimistic lock and optimistic lock

Before talking about InnoDB locks, let’s talk about pessimistic locks and optimistic locks.

Pessimistic lock and optimistic lock explain a design concept.

Pessimistic locking means that no matter what you do, you need to acquire the lock first. Optimistic locking does not actually have the concept of a lock. It does not lock in any operation, but when updating the data, it will check whether the data to be updated has been modified. It is generally implemented with CAS (Compare-and-Set)

Pessimistic lock : fetch the lock first and then visit . Row locks, table locks, read locks (shared locks), and write locks (exclusive locks) in the database are all pessimistic locks

Optimistic lock : It will not be locked , but if you want to update the data, it will check before the update whether anyone else has modified the data during the period from read to update. If it has been modified, read it again, try to update again, and repeat the above steps until the update is successful

Pessimistic locks affect performance relatively, optimistic locks have better performance because they are not locked. You can choose different designs according to your specific situation.

InnoDB lock

Now let us talk about InnoDB locks, InnoDB supports two levels of locks

Row-level lock : shared lock (S) and exclusive lock (X)

Table-level locks : Intention Shared Lock (IS) and Intention Exclusive Lock (IX).

1) Intentional shared lock (IS lock): the transaction must obtain IS lock before requesting S lock
2) Intention exclusive lock (IX lock): transaction must obtain IX lock before requesting X lock

Because the InnoDB storage engine supports row-level locks, intent locks do not actually block any requests other than full table scans. In addition, the intention shared lock (IS) and the intention exclusive lock (IX) are locked and unlocked by InnoDB itself, so this article mainly talks about row-level locks.

Shared lock and exclusive lock

The characteristics of shared locks and exclusive locks

Shared lock :

  • Allow other transactions to also increase shared lock reads
  • No other things are allowed to add exclusive locks ( for update)
  • When the transaction increases the shared lock at the same time, the update of the transaction must wait for the transaction commit to be executed first. If the concurrent concurrent is too large, it may easily cause deadlock

Exclusive lock :

  • Other exclusive locks or shared locks are not allowed to read between transactions, and modification is even more impossible
  • Only one exclusive lock can execute commit before other transactions can be executed

The compatibility of the two is shown in the figure below:

Insert picture description here

How to add shared lock or exclusive lock in InnoDB?

Add a shared lock: SELECT...LOCK IN SHARE MODE, such as select * from test1 where id = 1 lock in share mode;

Add exclusive lock: SELECT...FOR UPDATE, such as select * from test1 where name = 5 for update;

If you don't use lock in share mode or for update, just use select, it won't be locked. At this time, it is easy to lose updates or phantom reads.

Demo

The table structure is as follows:

CREATE TABLE test1 (
id int unsigned NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

The available data are as follows:

Insert picture description here

Let's take a look at some of the problems that will occur without locking

Lost update :

Session1 Session2
1 start transaction; start transaction;
2 select name into @name from test1 where id =1; select name into @name from test1 where id =1;
3 update test1 set name = @name - 100;
4 commit;
5 update test1 set name = @name + 100;
6 commit;

In this case, the changes made by session1 are overwritten by session2, and the final value will become 188. Of course, the main reason for this situation is that SQL is not well written.

  • When updating, use update test1 set name = name-100 (without @) to avoid this problem. Do not query first, and then update with the value found
  • If sql is written rigorously, for any isolation level of mysql, the problem of missing updates will not occur, because mysql will lock DML operations, and when two transactions update the same data, subsequent updates will be blocked .

Phantom reading :

Session1 Session2
1 start transaction; start transaction;
2 select * from test1 where name =1; (display 2 5 6 three)
3 update test1 set name = 2 where id=2;
4 select * from test1 where name =1; (display 2 5 6 three)
5 commit;
6 select * from test1 where name =1; (display 2 5 6 three)
7 update test1 set name = 3 where name=1; ( only affects two rows )
8 commit;

It can be seen that although session2 updated the data, the data still remained unchanged when session1 was queried, but only two rows were changed during the update, which gave rise to a phantom

  • There are always three when session1 reads, because mysql select uses a consistent non-locking read operation, which is implemented through Multi Version Concur-rency Control (MVCC). Simply put, select reads a snapshot

    • In the repeatable read isolation level, the read snapshot is the snapshot before the transaction starts, so no matter how other transactions change the data, the data read by the current transaction is unchanged

    • Under the read committed isolation level, the read snapshot is the latest data snapshot, so after other transactions are committed, the current transaction reads will read the latest value

Insert picture description here

  • When updating, because the data needs to be really modified, at this time it is found that there is a non-conformity, so only two are updated

In order to have no bugs when writing the code, we can add locks and lock the resources to be changed, so that only the transaction can operate on the data, and other transactions are not afraid of update delete insert operations on the data. Here is a simple exclusive lock

Exclusive lock

Session1 Session2
1 start transaction; start transaction;
2 select * from test1 where name =1 for update; (display 2 5 6 three)
3 update test1 set name = 2 where id=2; (阻塞)
4 select * from test1 where name =1; (display 2 5 6 three)
5 update test1 set name = 3 where name=1; ( affects three lines )
6 commit;
7 update is executed
8 commit;

It can be seen that compared with the phantom reading example, this example only adds for update (exclusive lock) when selecting session1. This operation locks the resources and the update of session2 cannot be executed. I believe everyone here has a clearer understanding of the role of mysql lock.

Locking algorithm

The InnoDB storage engine has three row lock algorithm designs, namely:

  • Record Lock: The lock on a single row record.
  • Gap Lock: Gap lock, lock a range, but does not include the record itself.
  • Next-Key Lock: Gap Lock+Record Lock, lock a range, and lock the record itself.

In REPEATABLE READ mode, the Next-Key Lock algorithm is the default row record locking algorithm. However, the InnoDB storage engine will choose the smallest algorithm model according to the situation, that is, Next-Key Lock will degenerate into Record Lock or Gap Lock.

Record Lock is easier to understand. It is to lock a single row, and only lock one row. For example, the row lock is used when where = is common. Gap Lock and Next Key Lock lock a range. Generally, the range is locked when where <. If I use select * from test1 where id <100 for update;, then other transactions will be blocked whether it is insert or update id <100. , But there is no problem beyond 100. So Mysql solves the problem of phantom reading through Record Lock in REPEATABLE READ mode.

Problems caused by incorrect use of locks

If the lock is used incorrectly, it will cause some problems, such as deadlock or accidentally locking the entire table.

Deadlock

Session1 Session2
1 start transaction; start transaction;
2 select * from test1 where id =1 for update;
3 select * from test1 where id =2 for update;
4 select * from test1 where id =1 for update;
5 select * from test1 where id =2 for update;(ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction)

There are many cases of deadlocks, and only one of them is shown above. MySQL has a mechanism to remove deadlocks: After a deadlock is found, the InnoDB storage engine will immediately roll back a transaction. But everyone try not to write deadlock code.

Lock the entire table

Using select...for update will lock the data, but we need to pay attention to some lock levels. MySQL InnoDB defaults to Row-Level Lock, so MySQL will only execute Row lock (only lock the selected Data), otherwise MySQL will execute Table Lock (lock the entire data form).

Only by retrieving data through index conditions, InnoDB will use row-level locks, otherwise, InnoDB will use table locks!

大家可以用select * from performance_schema.data_locks;查看被锁住的数据。

锁与事务的关系

上面讲述了锁的很多信息,那么锁与事务有什么关系呢?

大家都知道到Mysql的事务有四个特性,即ACID,原子性(Atomicity)、一致性(Correspondence)、隔离
性(Isolation)、持久性(Durability)。

锁和事务的关系:事务的隔离性通过锁来实现。

为什么锁能实现隔离性,因为加了锁之后,数据就不能被别人随便更改了。

常用命令

  1. 查看是否自动提交 show session variables like ‘autocommit’;

  2. 查询正在执行的事务 SELECT * FROM information_schema.INNODB_TRX;

  3. 查看正在锁的事务

    • SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
    • select * from performance_schema.data_locks; - mysql8.0
  4. 查看等待锁的事务

    • SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

    • SELECT * FROM sys.innodb_lock_waits; - mysql8.0

  5. 查看mysql当前默认的存储引擎 show variables like ‘%storage_engine%’;

  6. 查看mysql版本 select version();

  7. 查看隔离级别 select @@transaction_isolation;

参考资料

  1. 悲观锁与乐观锁的实现(详情图解)
  2. MySQL的SELECT …for update
  3. MySQL 共享锁 (lock in share mode),排他锁 (for update)
  4. MySQL的自动提交模式
  5. mac 安装[email protected] (brew 安装配置)
  6. MySQL 函数
  7. mysql8.0查看锁信息
  8. https://www.jianshu.com/p/32904ee07e56 Intermittent lock
  9. Mysql lock process detailed explanation (9)-record lock, gap lock, next-key lock under innodb
  10. The relationship between mysql shared lock (S), exclusive lock (X), intention shared lock (IS), and intention exclusive lock (IX)
  11. Mysql-missing updates
  12. " MySQL Technology Insider: InnoDB Storage Engine "

At last

If you like my article, you can follow my public account (Programmer Mala Tang)

Review of previous articles:

  1. Detailed explanation of CDN request process
  2. Thoughts on the career development of programmers
  3. The history of blog service being crushed
  4. Common caching techniques
  5. How to efficiently connect with third-party payment
  6. Gin framework concise version
  7. Thinking about code review
  8. A brief analysis of InnoDB locks and transactions
  9. Markdown editor recommendation-typora

Guess you like

Origin blog.csdn.net/shida219/article/details/106887149