Mysql how to troubleshoot a deadlock: insert on duplicate deadlock once the process of investigation and analysis

640?wx_fmt=jpeg

Foreword

Mysql deadlock encounter problems, we should analyze how to troubleshoot it? Before the emergence of a line of insert on duplicate deadlock problem, this will be based on this deadlock, share troubleshooting analysis process, we want to help.

Deadlock crime reduction

Table Structure:

CREATE TABLE `song_rank` (	
  `id` int(11) NOT NULL AUTO_INCREMENT,	
  `songId` int(11) NOT NULL,	
  `weight` int(11) NOT NULL DEFAULT '0',	
  PRIMARY KEY (`id`),	
  UNIQUE KEY `songId_idx` (`songId`) USING BTREE	
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Isolation level:

mysql> select @@tx_isolation;	
+-----------------+	
| @@tx_isolation  |	
+-----------------+	
| REPEATABLE-READ |	
+-----------------+	
1 row in set, 1 warning (0.00 sec)

Database version:

+------------+	
| @@version  |	
+------------+	
| 5.7.21-log |	
+------------+	
1 row in set (0.00 sec)

Turn off the automatic submission:

mysql> select @@autocommit;	
+--------------+	
| @@autocommit |	
+--------------+	
|            1 |	
+--------------+	
1 row in set (0.00 sec)	
mysql> set autocommit=0;	
Query OK, 0 rows affected (0.00 sec)	
mysql> select @@autocommit;	
+--------------+	
| @@autocommit |	
+--------------+	
|            0 |	
+--------------+	
1 row in set (0.00 sec)

Data in the table:

mysql> select * from song_rank;	
+----+--------+--------+	
| id | songId | weight |	
+----+--------+--------+	
|  1 |     10 |     30 |	
|  2 |     20 |     30 |	
+----+--------+--------+	
2 rows in set (0.01 sec)

Deadlock incident reasons:

Concurrent environment, execute insert into ... on duplicate key update ... lead to a deadlock

Deadlock analog reproduction:

Execute a transaction:

mysql> begin;    //第一步	
Query OK, 0 rows affected (0.00 sec)	
mysql> insert into  song_rank(songId,weight) values(15,100) on duplicate key update  weight=weight+1;  //第二步	
Query OK, 1 row affected (0.00 sec)	
mysql> rollback;   //第七步	
Query OK, 0 rows affected (0.00 sec)

Affairs II. Implementation:

mysql> begin;   //第三步	
Query OK, 0 rows affected (0.00 sec)	
mysql> insert into  song_rank(songId,weight) values(16,100) on duplicate key update  weight=weight+1;  //   第四步	
Query OK, 1 row affected (40.83 sec)

III Operative Affairs:

mysql> begin;  //第五步	
Query OK, 0 rows affected (0.00 sec)	
mysql> insert into  song_rank(songId,weight) values(18,100) on duplicate key update  weight=weight+1; //第六步

A transaction, the transaction two, three transactions executed:

step A transaction Two affairs Three affairs
first step begin;    
The second step insert into song_rank(songId,weight) values(15,100) on duplicate key update weight=weight+1; (Query OK, 1 row affected (0.00 sec) )    
third step   begin;  
the fourth step   insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1; //被阻塞  
the fifth step     begin;
Step Six     insert into song_rank(songId,weight) values(18,100) on duplicate key update weight=weight+1; //被阻塞
Step Seven rollback;    
result   Query OK, 1 row affected (40.83 sec) ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

Deadlock surfaced:

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

Deadlock detection investigation and analysis

Deadlock encountered problems, how should we deal with it? Several points about steps

1. Check the log deadlock

When the database deadlock, a deadlock may obtain a log with the following command:

show engine innodb status;

Examples of the above insert on duplicate log deadlock problems as follows:

*** (1) TRANSACTION:	
TRANSACTION 27540, ACTIVE 19 sec inserting	
mysql tables in use 1, locked 1	
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1	
MySQL thread id 23, OS thread handle 14896, query id 582 localhost ::1 root update	
insert into  song_rank(songId,weight) values(18,100) on duplicate key update  weight=weight+1	
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:	
RECORD LOCKS space id 116 page no 4 n bits 72 index songId_idx of table `test2`.`song_rank` trx id 27540 lock_mode X 	
locks gap before rec insert intention waiting	
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0	
 0: len 4; hex 80000014; asc     ;;	
 1: len 4; hex 80000002; asc     ;;	
*** (2) TRANSACTION:	
TRANSACTION 27539, ACTIVE 41 sec inserting, thread declared inside InnoDB 1	
mysql tables in use 1, locked 1	
4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 1	
MySQL thread id 22, OS thread handle 6976, query id 580 localhost ::1 root update	
insert into  song_rank(songId,weight) values(16,100) on duplicate key update  weight=weight+1	
*** (2) HOLDS THE LOCK(S):	
RECORD LOCKS space id 116 page no 4 n bits 72 index songId_idx of table `test2`.`song_rank` trx id 27539 lock_mode X 	
locks gap before rec	
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0	
 0: len 4; hex 80000014; asc     ;;	
 1: len 4; hex 80000002; asc     ;;	
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:	
RECORD LOCKS space id 116 page no 4 n bits 72 index songId_idx of table `test2`.`song_rank` trx id 27539 lock_mode X 	
locks gap before rec insert intention waiting	
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0	
 0: len 4; hex 80000014; asc     ;;	
 1: len 4; hex 80000002; asc     ;;

2. Analysis deadlock log

Deadlock how to analyze the log it? Share my ideas

  • Deadlock transaction log points 1, 2 split transaction

  • Find SQL deadlock

  • Find out what the transaction holding the lock, what are waiting for the lock

  • SQL lock analysis

Transaction Log section 1

640?wx_fmt=png

We can see from the SQL transaction log 1 is being executed as follows:

insert into  song_rank(songId,weight) values(18,100) on duplicate key update  weight=weight+1

The article is waiting index songId_idx statement of intent exclusive lock insert:

lock_mode X locks gap before rec insert intention waiting

Transaction Part 2

640?wx_fmt=png

We can see from the log 2 SQL transaction being executed as follows:

insert into  song_rank(songId,weight) values(16,100) on duplicate key update  weight=weight+1

This statement holds a lock gap index songId_idx:

lock_mode X locks gap before rec

The article is waiting index songId_idx statement of intent exclusive lock insert:

lock_mode X locks gap before rec insert intention waiting

Lock related concepts supplement (attached):

Considering that some readers may not be familiar with the above insert intention lock, so here here make up a section lock concepts. Official Documents

FIG mind InnoDB lock type:640?wx_fmt=png

We mainly introduce compatibility mode and lock type of lock

1. shared locks and exclusive locks:

InnoDB implements standard row-level locks, including two types: a shared lock (s abbreviated lock), an exclusive lock (lock abbreviated x).

  • Share locks (S locks): Allow holders lock transaction reads a row.

  • Exclusive lock (X lock): Allow holders lock transaction update or delete a row.

If the transaction T1 holds the lock row r s, then another transaction T2 requests a lock r, the process will be as follows:

  • S lock request immediately T2 is allowed, the results are in possession s T1 T2 lock rows r

  • T2 x requested lock can not be allowed immediately

If the r x T1 holds the lock, then the requested T2 of r x, S lock can not allow immediate, release T1 x T2 must wait before they can lock, since the lock is not compatible with any of the X lock.

2. Intent locks

  • Intention shared lock (IS lock): Transaction want to get a table shared lock a few lines

  • Intent exclusive locks (IX lock): Transaction want to get a table row a few lines of his lock

For example: Transaction 1 in Table 1 plus the S lock, the transaction 2 wants to change a line record, you need to add IX lock, due to incompatibility, it is necessary to wait for the S lock release; if the transaction is 1 plus 1 IS lock on the table transaction 2 Add the lock IX lock is compatible with iS, can operate, which achieved a more fine-grained locking.

InnoDB storage engine lock compatibility in the following table:

compatibility IS IX S X
IS compatible compatible compatible Not compatible
IX compatible compatible Not compatible Not compatible
S compatible Not compatible compatible Not compatible
X Not compatible Not compatible Not compatible Not compatible

3. Record Lock (Record Locks)

  • Record lock is the simplest row locks, only lock the line . Such as: SELECT c1 FROM t WHERE c1=10FOR UPDATE

  • Record locks are always added to the index , even if the table has no indexes, InnoDB will implicitly create an index, and use the index implement record locking.

  • It will block other transactions insert, update, delete

Lock transaction data record (keyword: lock_mode X locks rec butnotgap), recorded as follows:

RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t` 	
trx id 10078 lock_mode X locks rec but not gap	
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0	
 0: len 4; hex 8000000a; asc     ;;	
 1: len 6; hex 00000000274f; asc     'O;;	
 2: len 7; hex b60000019d0110; asc        ;;

4. Lock the gap (Gap Locks)

  • Lock is a gap between the two indices is applied lock, or added before the first index or the last index after the gap.

  • The gap is locked using a lock range, rather than the interval of each data.

  • Gap lock prevents other transactions only inserted into the gap, they do not prevent other transactions to obtain a lock on the same clearance gap, the gap x lock gap s lock and have the same effect.

5.Next-Key Locks

  • Next-key lock is a combination lock and the recording gap lock, it refers to a record is added to the record, and that the gap in front of the lock.

6. Insert intent lock (Insert Intention)

  • An interstitial provided before inserting the lock intent lock inserts a row in operation, the lock signal a plug release mode, i.e., a plurality of the same transaction upon insertion gap index is not inserted into the same position if the gap is not We need to wait for each other.

  • Suppose an index value of 4,7, ready to be inserted several different transactions 5,6, each lock in obtaining an exclusive lock insert rows with intent locks inserted before each locked gap between 4 and 7, but do not block insert rows because the other side does not conflict.

Transaction data similar to the following:

RECORD LOCKS space id 31 page no 3 n bits 72 index `PRIMARY` of table `test`.`child`	
trx id 8731 lock_mode X locks gap before rec insert intention waiting	
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0	
 0: len 4; hex 80000066; asc    f;;	
 1: len 6; hex 000000002215; asc     " ;;	
 2: len 7; hex 9000000172011c; asc     r  ;;...

SQL locking Analysis:

By analyzing the log deadlock, we can find the SQL deadlocks, locks and related waiting, we'll be locked on the corresponding SQL analysis, in fact, the problem is solved.

OK, we return to the corresponding SQL, insert into song_rank (songId, weight) values ​​(16,100) on duplicate key update weight = weight + 1 plus the implementation process in the end what lock it? Locking mechanism for official documents

insert locking strategy:

insert statement would insert this record plus exclusive record lock, the lock will be added before recording plus one kind of GAP lock, called the insertion of intent (insert intention) lock, if the unique key conflict, but also add a shared record (S )lock.

(SQL locking analysis is very important here to recommend an article in a very good way to resolve the deadlock - lock common analysis SQL statement)

insert on duplicate key lock verification

In order to verify insert on duplicate key lock, we get the above demo transaction 1 and 2 to go about the process. Transaction 1:

mysql> begin;    //第一步	
Query OK, 0 rows affected (0.00 sec)	
mysql> insert into  song_rank(songId,weight) values(15,100) on duplicate key	
update  weight=weight+1;  //第二步	
Query OK, 1 row affected (0.00 sec)

Services 2 (open another window):

mysql> begin;   //第三步	
Query OK, 0 rows affected (0.00 sec)	
mysql> insert into  song_rank(songId,weight) values(16,100) on duplicate key 	
update  weight=weight+1;  //   第四步

Use show engine innodb status to view the current lock request information, as shown:640?wx_fmt=png

FIG there can be obtained:

Services 2 holds: IX lock (lock table), gap x lock, insert intention lock (waiting for the lock transaction gap 1)

So, insert on duplicate execution at this three locks.

Deadlock Analysis

Return to the beginning of this article describes the simulation deadlock incident site (transaction 1,2,3) and a deadlock logging site,

After the incident the transaction lock 1: 640?wx_fmt=pngafter the incident transaction 2 locks:640?wx_fmt=png

Incident recovery route:

1. First, the enforcement branch 1 to perform: begin; insertintosong_rank(songId,weight)values(15,100)on duplicate key update weight=weight+1;get gap lock (10,20), insert intention lock (insert intent lock)

2. Next, perform the transaction 2: begin; insertintosong_rank(songId,weight)values(16,100)on duplicate key update weight=weight+1;get gap lock (10, 20), while waiting for the transaction insert intention lock 1 of (insert intent locks).

3. Then again, execute the transaction 3: begin; insertintosong_rank(songId,weight)values(18,100)on duplicate key update weight=weight+1;get gap lock (10, 20), while waiting for the transaction insert intention lock 1 of (insert intent locks).

4. Finally, the transaction a rollback (rollback), insert the intention to release the lock, resulting in 2,3 affairs while holding gap locks, waiting insert intention locks, deadlocks form !

Lock mode is compatible with the matrix (lateral is already holds the lock, the lock being requested longitudinal):

compatibility Gap Insert Intention Record Next-Key
Gap compatible compatible compatible compatible
Insert Intention conflict compatible compatible conflict
Record compatible compatible conflict conflict
Next-Key compatible compatible conflict conflict

This is a bug MySql5.7 of

How to avoid the insert on duplicate deadlock

1. insert on duplicate changed to insert

   try{	
       insert();	
   }catch(DuplicateKeyException e){	
       update();	
   }

Because the insert does not add gap locks, so the problem can be avoided.

2. Change MySql version

Since this is a bug MySql5.7, then you can consider changing the Mysql version.

3. Minimize the use of unique index.

lock gap with the relevant index, and unique key and foreign key can cause additional index check, we need more overhead, so we try to reduce the use of unnecessary indexes.

This paper summarizes the (important)

This article describes MySql5.7 a bug deadlock. How should we go to troubleshoot the deadlock it?

  • 1.show engine innodb status; to view log deadlock

  • 2. Find SQL Deadlock

  • 3.SQL lock analysis

  • 4. Analyze the deadlock log (what holds the lock, waiting for what lock)

  • The familiar lock mode compatible matrix, InnoDB storage engine lock compatibility matrix.

Reference and thanks

  • Insert on duplicate a Murder Caused

  • Read MySQL source code look INSERT locking process

  • The way to resolve the deadlock - Learn about common types of locks

  • MySQL InnoDB lock - official documents

  • MySQL locking mechanism - record locks, lock gap, temporary key lock

  • Locking common analysis SQL statement - to resolve the deadlock of the road

  • "MySQL Technology Insider"

Personal Public Number

  • If you are a love of learning boy, I can focus on the public number, learning together discussion.
  • What if you feel that this article is not the right place, can comment, I can also concerned about the number of public, private chat me, we will study together progress Kazakhstan

 

Published 23 original articles · won praise 195 · views 20000 +

Guess you like

Origin blog.csdn.net/weiwenhou/article/details/100059604