mysql insert 锁
擼了今年阿里、頭條和美團的面試,我有一個重要發(fā)現(xiàn).......>>>
多線程插入mysql時會發(fā)生死鎖。
數(shù)據(jù)庫test中,id1和id2是聯(lián)合主鍵
當前數(shù)據(jù)庫test內(nèi)容為空。mysql引擎是:InnoDB,隔離級別為REPEATABLE-READ
?
情況一:
線程A開啟事務(wù):
mysql> start transaction; Query OK, 0 rows affected mysql>線程B開啟事務(wù):
mysql> start transaction; Query OK, 0 rows affected mysql>線程A,插入數(shù)據(jù):
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT ignore into test values ('1', '1'),('2', '2'),('3','3'); Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0mysql>線程A沒有commit,所以數(shù)據(jù)('1', '1'),('2', '2'),('3','3')被上鎖,
線程B這時也插入數(shù)據(jù):
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT ignore into test values ('2', '2'),('4','4'); 等待中....因為數(shù)據(jù)('2','2')被上鎖,所以等待線程A釋放鎖,此時數(shù)據(jù)('4','4')還沒有被上鎖。線程A可以插入('4','4');
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT ignore into test values ('1', '1'),('2', '2'),('3','3'); Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0mysql> INSERT ignore into test values ('5', '5'),('4', '4') ; Query OK, 2 rows affected Records: 2 Duplicates: 0 Warnings: 0mysql>線程A提交:
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT ignore into test values ('1', '1'),('2', '2'),('3','3'); Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0mysql> INSERT ignore into test values ('5', '5'),('4', '4') ; Query OK, 2 rows affected Records: 2 Duplicates: 0 Warnings: 0mysql> commit; Query OK, 0 rows affectedmysql>線程B提交:
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT ignore into test values ('2', '2'),('4','4'); Query OK, 0 rows affected Records: 2 Duplicates: 2 Warnings: 2mysql> commit; Query OK, 0 rows affected情況二:
線程A開啟事務(wù):
mysql> start transaction; Query OK, 0 rows affected mysql>線程B開啟事務(wù):
mysql> start transaction; Query OK, 0 rows affected mysql>線程A,插入數(shù)據(jù):
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT ignore into test values ('1', '1'),('2', '2'),('3','3'); Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0mysql>線程A沒有commit,所以數(shù)據(jù)('1', '1'),('2', '2'),('3','3')被上鎖,
線程B這時也插入數(shù)據(jù):
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT ignore into test values ('4', '4'),('2','2'),('5','5'); 等待中....因為數(shù)據(jù)('2','2')被上鎖,所以等待線程A釋放鎖,此時數(shù)據(jù)('4','4')已經(jīng)成功執(zhí)行被上鎖。線程A插入('4','4');會造成死鎖
A線程插入('4','4'),('5','5'):
mysql> INSERT ignore into test values ('4', '4'),('6', '6') ; Query OK, 2 rows affected Records: 2 Duplicates: 0 Warnings: 0mysql>此時B線程檢測到死鎖:
mysql> INSERT ignore into test values ('4', '4'),('2','2'),('5','5'); 1213 - Deadlock found when trying to get lock; try restarting transaction mysql>也就是說
A線程執(zhí)行insert?ignore?into?test?values ('1', '1'),('2', '2');能執(zhí)行成功,會給('1', '1'),('2', '2')加鎖
B線程執(zhí)行insert?ignore?into?test?values ('3', '3'),('2', '2'),('4','4');檢測('3','3')沒有加鎖,然后給('3','3')加上鎖,('2','2')檢測到鎖,被A線程鎖住,等待鎖釋放,這時('4','4')這條數(shù)據(jù)沒有加鎖。
接下來:
?死鎖的方向
線程B死鎖:
線程A執(zhí)行:
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT ignore into test values ('1', '1'),('2', '2'); Query OK, 2 rows affected Records: 2 Duplicates: 0 Warnings: 0mysql>線程B執(zhí)行:
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT into test values ('3', '3'),('2','2'); 等待中....然后線程A執(zhí)行:
mysql> INSERT ignore into test values ('3', '3'); Query OK, 1 row affectedmysql>這時B線程檢測到死鎖,結(jié)束等待,并且自動回滾,線程A正常執(zhí)行。
B檢測到死鎖:
mysql> INSERT into test values ('3', '3'),('2','2'); 1213 - Deadlock found when trying to get lock; try restarting transaction mysql>========
A線程執(zhí)行:
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT ignore into test values ('1', '1'),('2', '2'),('9','9'),('8','8'); Query OK, 4 rows affected Records: 4 Duplicates: 0 Warnings: 0mysql>B線程執(zhí)行:
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT into test values ('3', '3'),('2','2'); 等待中然后A線程執(zhí)行:
mysql> INSERT ignore into test values ('3', '3'); Query OK, 1 row affectedmysql>B線程檢測到死鎖,停止等待,自動回滾:
ysql> INSERT into test values ('3', '3'),('2','2'); 1213 - Deadlock found when trying to get lock; try restarting transaction mysql>線程A死鎖:
線程A:
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT ignore into test values ('1', '1'),('2', '2'); Query OK, 2 rows affected Records: 2 Duplicates: 0 Warnings: 0mysql>線程B:
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT into test values ('3', '3'),('4','4'),('2','2'); 等待中這時A線程執(zhí)行:
mysql> INSERT ignore into test values ('3', '3'); 1213 - Deadlock found when trying to get lock; try restarting transaction mysql>檢測到死鎖,死鎖在A線程這邊,A線程自動回滾,B線程結(jié)束等待,正常提交
mysql> INSERT into test values ('3', '3'),('4','4'),('2','2'); Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0mysql>========
線程A執(zhí)行:
mysql> start transaction; Query OK, 0 rows affectedmysql> INSERT ignore into test values ('1', '1'),('2', '2'); Query OK, 2 rows affected Records: 2 Duplicates: 0 Warnings: 0mysql>線程B執(zhí)行:
mysql> start transaction; Query OK, 0 rows affectedmysql> insert into test values ('3','3'),('4','4'),('5','5'),('2','2'); Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0mysql>這時A線程執(zhí)行:
mysql> INSERT ignore into test values ('3', '3'); 1213 - Deadlock found when trying to get lock; try restarting transaction mysql>?A線程檢測到死鎖,并且自動回滾,釋放鎖,B線程結(jié)束等待。
猜想:誰加鎖的數(shù)據(jù)少,那么誰就檢測到死鎖,就先釋放鎖。
例如:線程A執(zhí)行:
mysql> start transaction; Query OK, 0 rows affectedmysql> insert ignore into test values ('1','1'),('2','2'); Query OK, 2 rows affected Records: 2 Duplicates: 0 Warnings: 0mysql>線程A加鎖數(shù)據(jù):('1','1'),('2','2')
線程B:
mysql> start transaction; Query OK, 0 rows affectedmysql> insert into test values ('3','3'),('4','4'),('5','5'),('2','2'); 等待中....線程B加鎖數(shù)據(jù):('3','3'),('4','4'),('5','5')
然后A線程執(zhí)行:
mysql> insert ignore into test values ('6','6'),('7','7'),('8','8'),('9','9'),('3','3');此時A線程加鎖數(shù)據(jù)為:('1','1'),('2','2'),('6','6'),('7','7'),('8','8'),('9','9')
A線程加鎖數(shù)據(jù)多于B線程,所以B線程檢測到死鎖,主動釋放鎖,
B線程:
mysql> insert into test values ('3','3'),('4','4'),('5','5'),('2','2'); 1213 - Deadlock found when trying to get lock; try restarting transaction mysql>說明誰加鎖的數(shù)據(jù)少,那么誰就檢測到死鎖,就先釋放鎖。
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的mysql insert 锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tzselect 设置时间
- 下一篇: c3p0 高并发mysql 连接slee