Deadlock case eight

Source: public account yangyidba

I. Introduction

Deadlock is actually a very interesting and challenging technical problem. Probably every DBA and some development friends will encounter it in the process of work. Regarding deadlock, I will continue to write a series of case studies, hoping to help friends who want to understand deadlock.

Two case analysis

2.1 Business scenario

The main business logic:

First execute the insert data, if the insert is successful, then submit. If a unique key conflict is reported when inserting, the update is performed. If three concurrent data initialization actions occur at the same time, sess1 inserts successfully, sess2 and sess3 inserts encounter a unique key conflict, and the insert fails, both of them will execute the update, so deadlock occurs.

2.2 Environmental preparation

MySQL 5.6.24 transaction isolation level is RR

create table ty (
  id int not null primary key auto_increment ,
  c1 int not null default 0,
  c2 int not null default 0,
  c3 int not null default 0,
  unique key uc1(c1),
  unique key uc2(c2)
) engine=innodb ;

insert into ty(c1,c2,c3) values(1,3,4),(6,6,10),(9,9,14);

2.3 Test case

In order to facilitate the analysis of the deadlock log, the values ​​of c3 inserted in the three sessions are 1 2 3 respectively, which are actually the same value in production.


sess1

sess2

sess3


begin;

begin;

begin;

T1

insert into ty (c1,c2,c3) values(4,4,1);



T2


insert into ty (c1,c2,c3) values(4,4,2);


T3



insert into ty (c1,c2,c3) values(4,4,3);

T4

commit



T5


update ty set c3=5 where c1=4;


T6



update ty set c3=5 where c1=4;

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

2.4 Deadlock log

2018-03-28 10:04:52 0x7f75bf2d9700
*** (1) TRANSACTION:
TRANSACTION 1870, ACTIVE 76 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 399265, OS thread handle 12, query id 9 root updating
update ty set c3=5 where c1=4
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 28 page no 4 n bits 72 index uc1 of table 
`test`.`ty` trx id 1870 lock_mode X locks rec but not gap waiting
*** (2) TRANSACTION:
TRANSACTION 1871, ACTIVE 32 sec starting index read, 
thread declared inside InnoDB 5000
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 399937, OS thread handle 16, query id 3 root updating
update ty set c3=5 where c1=4
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 28 page no 4 n bits 72 index uc1 of table 
`test`.`ty` trx id 1871 lock mode S
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 28 page no 4 n bits 72 index uc1 of table 
`test`.`ty` trx id 1871 lock_mode X locks rec but not gap waiting
*** WE ROLL BACK TRANSACTION (2)

In fact, just looking at the log from the log only sees that the updates of the two transactions compete with each other. In the absence of business logic scenarios, it is difficult to get an effective idea for analyzing the deadlock because it is not known that there is an insert operation.

2.5 Analyze the deadlock log

T1 s1 executes the insert operation, checks the uniqueness and inserts successfully, and holds the row lock of the c1=4 record row.

T2 s2 insert encounters a unique key conflict, apply for lock Lock S Next-key Lock log shows index uc1 of table test.ty trx id 1870 lock mode S waiting

T3 is the same as s2, s3 insert encounters a unique key conflict, apply for lock Lock S Next-key Lock log shows index uc1 of table test.ty trx id 1870 lock mode S waiting

T4 sess1 executes the commit operation, at this time sess2 and sess3 acquire Lock S Next-key Lock at the same time.

The T5 application receives a unique key conflict. The update operation of sess2 needs to apply for a row lock of c=4, which is incompatible with the Lock S Next-key Lock held by sess3. Wait for sess3 to release Lock S Next-key Lock.

T6 is similar to sess2. The update operation of sess3 needs to apply for a row lock of c=4, which is incompatible with the Lock S Next-key Lock held by sess2. Waiting for sess2 to release Lock S Next-key Lock. There is a loop waiting, and a deadlock occurs.

2.6 Solution

The solution in this case and in fact earlier deadlock seven cases the same, using insert on duplicate key. Case 7 is very similar to the business logic that caused the deadlock in this article. Why? Because it was written by the same group of developers.

Three summary

The root cause of the deadlock is that the order of applying locks for different transactions is different and there is cyclic waiting. When designing high-concurrency business scenarios , developers need to focus on this point and try to avoid deadlocks caused by unreasonable business scenarios.

In addition, the locking mechanism of insert is actually more complicated than update, which requires more hands-on practice to clarify the locking process.

Scan the QR code to follow the author's WeChat public account

Extended reading

The full text is over.

Enjoy MySQL :)

Teacher Ye's "MySQL Core Optimization" class has been upgraded to MySQL 8.0, scan the code to start the journey of MySQL 8.0 practice

Guess you like

Origin blog.csdn.net/n88Lpo/article/details/109233495