mysql死鎖(dead lock)與鎖等待(lock wait)的出現(xiàn)解決
很多人都分不清死鎖和鎖等待的區(qū)別,也有不同IT口的人叫法的差異。在運(yùn)維側(cè):
死鎖最明顯的特征是會(huì)自動(dòng)解開(kāi),是需要我們?nèi)ナ潞蠼鉀Q邏輯缺陷。
鎖等待則是業(yè)務(wù)卡住了(一般是某個(gè)大事務(wù)還在執(zhí)行,或有事務(wù)沒(méi)提交),需要?dú)⒌舫钟墟i的進(jìn)城讓業(yè)務(wù)正常進(jìn)行
做幾個(gè)實(shí)驗(yàn)詳細(xì)演示一下。
表結(jié)構(gòu)及數(shù)據(jù)情況
mysql> desc ttt; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | x | int(11) | NO | PRI | NULL | | | y | datetime | YES | | NULL | | | z | varchar(10) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 3 rows in set (0.00 sec) mysql> select * from ttt; +---+---------------------+------+ | x | y | z | +---+---------------------+------+ | 1 | 2023-05-30 23:50:13 | 123 | | 2 | 2023-04-26 17:58:18 | av3 | | 3 | 2023-05-30 22:52:35 | at | | 4 | 2023-04-26 17:58:29 | attt | | 5 | 2023-05-30 22:52:55 | zxz | +---+---------------------+------+ 5 rows in set (0.00 sec)
死鎖(dead lock)
上文說(shuō)了,死鎖會(huì)自動(dòng)解除,這里主要展示一下怎么追查。這里就不演示具體執(zhí)行順序了
前臺(tái)報(bào)錯(cuò)
session1,這個(gè)先持有
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> update ttt set y=now() where x=1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update ttt set y=now() where x=3; Query OK, 1 row affected (7.04 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql>
session2,這個(gè)來(lái)跳出錯(cuò)誤
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> update ttt set y=now() where x=3; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update ttt set y=now() where x=1; ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction mysql>
事后追查
innodb status的last dead lock只會(huì)記錄上一次,建議是使用innodb_print_all_deadlocks參數(shù),將記錄打印到error.log中,該參數(shù)默認(rèn)為off,可以動(dòng)態(tài)修改
mysql> show variables like '%innodb_print_all_deadlocks%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | innodb_print_all_deadlocks | OFF | +----------------------------+-------+ 1 row in set (0.00 sec) mysql> set global innodb_print_all_deadlocks=on; Query OK, 0 rows affected (0.00 sec) mysql> show variables like '%innodb_print_all_deadlocks%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | innodb_print_all_deadlocks | ON | +----------------------------+-------+ 1 row in set (0.00 sec)
innodb status
show engine innodb status; ********* ------------------------ LATEST DETECTED DEADLOCK ------------------------ 2023-05-30 22:42:09 0x7f9fd41ba700 *** (1) TRANSACTION: TRANSACTION 5454, ACTIVE 26 sec starting index read 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 18, OS thread handle 140324434298624, query id 440 localhost root updating update ttt set y=now() where x=3 *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5454 lock_mode X locks rec but not gap waiting Record lock, heap no 10 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000003; asc ;; 1: len 6; hex 00000000154f; asc O;; 2: len 7; hex 390000014e0110; asc 9 N ;; 3: len 5; hex 99b03d6a76; asc =jv;; 4: len 2; hex 6174; asc at;; *** (2) TRANSACTION: TRANSACTION 5455, ACTIVE 15 sec starting index read mysql tables in use 1, locked 1 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1 MySQL thread id 20, OS thread handle 140324435109632, query id 441 localhost root updating update ttt set y=now() where x=1 *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5455 lock_mode X locks rec but not gap Record lock, heap no 10 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000003; asc ;; 1: len 6; hex 00000000154f; asc O;; 2: len 7; hex 390000014e0110; asc 9 N ;; 3: len 5; hex 99b03d6a76; asc =jv;; 4: len 2; hex 6174; asc at;; *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5455 lock_mode X locks rec but not gap waiting Record lock, heap no 7 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000001; asc ;; 1: len 6; hex 00000000154e; asc N;; 2: len 7; hex 380000014d0110; asc 8 M ;; 3: len 5; hex 99b03d6a6b; asc =jk;; 4: len 3; hex 313233; asc 123;; *** WE ROLL BACK TRANSACTION (2) ********
error.log
[root@mysql57-1 data]# tail -100f mysql57-1.err 2023-05-25T07:42:37.677851Z 14 [Note] Access denied for user 'root'@'localhost' (using password: YES) 2023-05-25T07:44:15.360390Z 15 [Note] Access denied for user 'roo'@'localhost' (using password: YES) 2023-05-25T07:44:28.477560Z 16 [Note] Access denied for user 'roo'@'localhost' (using password: YES) 2023-05-30T14:53:00.101403Z 22 [Note] InnoDB: Transactions deadlock detected, dumping detailed information. 2023-05-30T14:53:00.101475Z 22 [Note] InnoDB: *** (1) TRANSACTION: TRANSACTION 5458, ACTIVE 25 sec starting index read 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 21, OS thread handle 140324434298624, query id 473 localhost root updating update ttt set y=now() where x=5 2023-05-30T14:53:00.101516Z 22 [Note] InnoDB: *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5458 lock_mode X locks rec but not gap waiting Record lock, heap no 6 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000005; asc ;; 1: len 6; hex 000000001553; asc S;; 2: len 7; hex 3b00000130036d; asc ; 0 m;; 3: len 5; hex 99b03d6d32; asc =m2;; 4: len 3; hex 7a787a; asc zxz;; 2023-05-30T14:53:00.101718Z 22 [Note] InnoDB: *** (2) TRANSACTION: TRANSACTION 5459, ACTIVE 10 sec starting index read mysql tables in use 1, locked 1 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1 MySQL thread id 22, OS thread handle 140324435109632, query id 474 localhost root updating update ttt set y=now() where x=3 2023-05-30T14:53:00.101748Z 22 [Note] InnoDB: *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5459 lock_mode X locks rec but not gap Record lock, heap no 6 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000005; asc ;; 1: len 6; hex 000000001553; asc S;; 2: len 7; hex 3b00000130036d; asc ; 0 m;; 3: len 5; hex 99b03d6d32; asc =m2;; 4: len 3; hex 7a787a; asc zxz;; 2023-05-30T14:53:00.101912Z 22 [Note] InnoDB: *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5459 lock_mode X locks rec but not gap waiting Record lock, heap no 10 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000003; asc ;; 1: len 6; hex 000000001552; asc R;; 2: len 7; hex 3a0000012e03d1; asc : . ;; 3: len 5; hex 99b03d6d23; asc =m#;; 4: len 2; hex 6174; asc at;; 2023-05-30T14:53:00.102084Z 22 [Note] InnoDB: *** WE ROLL BACK TRANSACTION (2)
鎖等待(lock wait)
1個(gè)參數(shù)
innodb_lock_wait_timeout
行鎖等待的時(shí)間,如果超過(guò)這個(gè)時(shí)間,session2(后發(fā)起那個(gè))會(huì)自動(dòng)跳出
session1
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> update ttt set y=now() where x=1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0
session2
mysql> update ttt set y=now() where x=1; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
怎么處理
省略構(gòu)造鎖
通過(guò)information_schema.innodb_lock_waits視圖獲得鎖等待的關(guān)系
mysql> select * from information_schema.innodb_lock_waits; +-------------------+-------------------+-----------------+------------------+ | requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id | +-------------------+-------------------+-----------------+------------------+ | 5467 | 5467:23:3:7 | 5466 | 5466:23:3:7 | +-------------------+-------------------+-----------------+------------------+ 1 row in set, 1 warning (0.00 sec)
再結(jié)合information_schema.innodb_trx視圖得到語(yǔ)句和線(xiàn)程ID
這里提供一個(gè)sql
SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread, b.trx_query blocking_query, b.trx_autocommit_non_locking FROM information_schema.innodb_lock_waits w INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id; mysql> SELECT r.trx_id waiting_trx_id, -> r.trx_mysql_thread_id waiting_thread, -> r.trx_query waiting_query, -> b.trx_id blocking_trx_id, -> b.trx_mysql_thread_id blocking_thread, -> b.trx_query blocking_query, -> b.trx_autocommit_non_locking -> FROM information_schema.innodb_lock_waits w -> INNER JOIN information_schema.innodb_trx b ON -> b.trx_id = w.blocking_trx_id -> INNER JOIN information_schema.innodb_trx r ON -> r.trx_id = w.requesting_trx_id; +----------------+----------------+----------------------------------+-----------------+-----------------+----------------+----------------------------+ | waiting_trx_id | waiting_thread | waiting_query | blocking_trx_id | blocking_thread | blocking_query | trx_autocommit_non_locking | +----------------+----------------+----------------------------------+-----------------+-----------------+----------------+----------------------------+ | 5470 | 22 | update ttt set y=now() where x=1 | 5466 | 26 | NULL | 0 | +----------------+----------------+----------------------------------+-----------------+-----------------+----------------+----------------------------+ 1 row in set, 1 warning (0.00 sec)
再對(duì)blocking thread的狀態(tài)進(jìn)行確認(rèn),然后kill
mysql> select * from information_schema.PROCESSLIST where id=26; +----+------+-----------+------+---------+------+-------+------+ | ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO | +----+------+-----------+------+---------+------+-------+------+ | 26 | root | localhost | ddd | Sleep | 1221 | | NULL | +----+------+-----------+------+---------+------+-------+------+ 1 row in set (0.00 sec)
殺線(xiàn)程
mysql> kill 26; Query OK, 0 rows affected (0.00 sec)
級(jí)聯(lián)鎖或大量鎖
這里構(gòu)造一個(gè)多個(gè)爭(zhēng)用的情況。
session1,線(xiàn)程id為27,這個(gè)先發(fā)起
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> update ttt set y=now() where x=1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0
session,線(xiàn)程id為22,第二個(gè)發(fā)起
mysql> update ttt set y=now() where x=1;
session3,線(xiàn)程id為28,最后一個(gè)發(fā)起
mysql> update ttt set y=now();
鎖關(guān)系情況
mysql> select * from information_schema.innodb_lock_waits; +-------------------+-------------------+-----------------+------------------+ | requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id | +-------------------+-------------------+-----------------+------------------+ | 5479 | 5479:23:3:7 | 5478 | 5478:23:3:7 | | 5479 | 5479:23:3:7 | 5473 | 5473:23:3:7 | | 5478 | 5478:23:3:7 | 5473 | 5473:23:3:7 | +-------------------+-------------------+-----------------+------------------+ 3 rows in set, 1 warning (0.01 sec)
查詢(xún)sql的展示情況
mysql> SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread, b.trx_query blocking_query, b.trx_autocommit_non_locking FROM information_schema.innodb_lock_waits w INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id; +----------------+----------------+----------------------------------+-----------------+-----------------+----------------------------------+----------------------------+ | waiting_trx_id | waiting_thread | waiting_query | blocking_trx_id | blocking_thread | blocking_query | trx_autocommit_non_locking | +----------------+----------------+----------------------------------+-----------------+-----------------+----------------------------------+----------------------------+ | 5479 | 28 | update ttt set y=now() | 5478 | 22 | update ttt set y=now() where x=1 | 0 | | 5479 | 28 | update ttt set y=now() | 5473 | 27 | NULL | 0 | | 5478 | 22 | update ttt set y=now() where x=1 | 5473 | 27 | NULL | 0 | +----------------+----------------+----------------------------------+-----------------+-----------------+----------------------------------+----------------------------+
這個(gè)時(shí)候一般的做法是先找到最多的那個(gè)blocking_thread
確認(rèn)他的進(jìn)程狀態(tài)后來(lái)考慮是否殺
如果他是活動(dòng)的thread,在干活,就可以刪掉釋放資源。
如果他是非活動(dòng),就要看他這個(gè)thread的blocking_thread,找到活動(dòng)持有資源的,來(lái)殺掉。
當(dāng)然也有執(zhí)行了完了不提交的情況,innodb_trx的trx_autocommit_non_locking列的值就是為了標(biāo)記是否是提交了。0表示沒(méi)有提交。
到此這篇關(guān)于mysql死鎖(dead lock)與鎖等待(lock wait)的出現(xiàn)解決的文章就介紹到這了,更多相關(guān)mysql死鎖與鎖等待內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
DataGrip連接Mysql并創(chuàng)建數(shù)據(jù)庫(kù)的方法實(shí)現(xiàn)
本文主要介紹了DataGrip連接Mysql并創(chuàng)建數(shù)據(jù)庫(kù)的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02利用SQL注入漏洞登錄后臺(tái)的實(shí)現(xiàn)方法
工作需要,得好好補(bǔ)習(xí)下關(guān)于WEB安全方面的相關(guān)知識(shí),故撰此文,權(quán)當(dāng)總結(jié),別無(wú)它意。讀這篇文章,我假設(shè)讀者有過(guò)寫(xiě)SQL語(yǔ)句的經(jīng)歷,或者能看得懂SQL語(yǔ)句2012-01-01mysql字符集和校對(duì)規(guī)則(Mysql校對(duì)集)
字符集的概念大家都清楚,校對(duì)規(guī)則很多人不了解,一般數(shù)據(jù)庫(kù)開(kāi)發(fā)中也用不到這個(gè)概念,mysql在這方便貌似很先進(jìn),大概介紹一下2012-07-07MySQL忘記密碼恢復(fù)密碼的實(shí)現(xiàn)方法
流傳較廣的方法,mysql中文參考手冊(cè)上的,各位vps主機(jī)租用客戶(hù)和服務(wù)器托管用戶(hù)忘記mysql5.1管理員密碼時(shí),可以使用這種方法破解下2008-07-07淺談MySql整型索引和字符串索引失效或隱式轉(zhuǎn)換問(wèn)題
本文主要介紹了MySql整型索引和字符串索引失效或隱式轉(zhuǎn)換問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11Mysql中日期和時(shí)間函數(shù)應(yīng)用不用求人
Mysql中日期和時(shí)間函數(shù)應(yīng)用不用求人,學(xué)習(xí)mysql的朋友可以參考下。2010-11-11簡(jiǎn)述MySQL分片中快速數(shù)據(jù)遷移
這篇文章主要介紹了MySQL分片中快速數(shù)據(jù)遷移的相關(guān)資料,需要的朋友可以參考下2016-03-03MySQL5.7.27-winx64版本win10下載安裝教程圖解
這篇文章主要介紹了MySQL5.7.27-winx64版本win10下載安裝教程,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09