【MySQL】如何閱讀死鎖日誌
一 前言
工欲善其事必先利其器,前面分析了很多死鎖案例,並沒有詳細的介紹如何透過死鎖日誌來診斷死鎖的成因。本文將介紹如何讀懂死鎖日誌,儘可能的獲取資訊來輔助我們解決死鎖問題。
二 日誌分析
2.1 場景
為了更好的學習死鎖日誌,我們需要提前瞭解死鎖場景
MySQL 5.6 事務隔離級別為RR
2.2 測試用例
2.3 我們透過show engine innodb status 檢視的日誌是最新一次記錄死鎖的日誌。
2.4 日誌分析
*** (1) TRANSACTION: #事務1
TRANSACTION 462308399, ACTIVE 33 sec starting index read
事務編號為 462308399 ,活躍33秒,starting index read 表示事務狀態為根據索引讀取資料。常見的其他狀態:
mysql tables in use 1, 說明當前的事務使用一個表。locked 1 表示表上有一個表鎖,對於DML語句為LOCK_IX
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
LOCK WAIT表示正在等待鎖, 2 lock struct(s) 表示trx->trx_locks鎖連結串列的長度為2,每個連結串列節點代表該事務持有的一個鎖結構,包括表鎖,記錄鎖以及auto_inc鎖等。本案例中2locks 表示IX鎖和lock_mode X(Next-key lock)
heap size 360 表示事務分配的鎖堆記憶體大小,一般沒有什麼具體的用處。
1 row lock(s)表示當前事務持有的行記錄鎖/gap 鎖的個數。
delete from ty where a=5 表示事務1在執行的sql ,不過比較悲傷的事情是show engine innodb status 是檢視不到完整的事務的sql 的,通常顯示當前正在等待鎖的sql。
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308399 lock_mode X waiting
RECORD LOCKS 表示記錄鎖,space id為219,page號4 ,n bits 72表示這個聚集索引記錄鎖結構上留有72個Bit位
表示事務1 正在等待表 ty 上的 idxa 的 X 鎖本案例中其實是Next-Key lock
事務2的log 和上面分析類似,
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X
顯示了事務2 insert into ty(a,b) values(2,10)持有了a=5 的Lock mode X |LOCK_GAP ,不過我們從日誌裡面看不到 事務2 執行的 delete from ty where a=5;這點也是造成DBA 僅僅根據日誌難以分析死鎖的問題的根本原因。
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X locks gap before rec insert intention waiting
表示事務2的insert 語句正在等待插入意向鎖 lock_mode X locks gap before rec insert intention waiting (LOCK_X + LOCK_REC_GAP )
這裡需要各位注意的是鎖組合,類似lock_mode X waiting ,lock_mode X,lock_mode X locks gap before rec insert intention waiting 是我們分析死鎖的核心重點。如何理解鎖組合呢?
首先我們要知道對於MySQL有兩種常規鎖模式
LOCK_S(讀鎖,共享鎖)
LOCK_X(寫鎖,排它鎖)
最容易理解的鎖模式,讀加共享鎖,寫加排它鎖.
有如下幾種鎖的屬性
LOCK_REC_NOT_GAP (鎖記錄)
LOCK_GAP (鎖記錄前的GAP)
LOCK_ORDINARY (同時鎖記錄+記錄前的GAP 。傳說中的Next Key鎖)
LOCK_INSERT_INTENTION(插入意向鎖,其實是特殊的GAP鎖)
鎖的屬性可以與鎖模式任意組合。例如.
lock->type_mode 可以是Lock_X 或者Lock_S
locks gap before rec 表示為gap鎖:lock->type_mode & LOCK_GAP
locks rec but not gap 表示為記錄鎖,非gap鎖:lock->type_mode & LOCK_REC_NOT_GAP
insert intention 表示為插入意向鎖:lock->type_mode & LOCK_INSERT_INTENTION
waiting 表示鎖等待:lock->type_mode & LOCK_WAIT
三 小結
本文算是簡單的死鎖分析入門,能夠提供部分死鎖分析的所需要的技術知識。死鎖分析確是一門技術活兒,想要透徹的分析死鎖的成因,我們必須要了解造成死鎖的業務邏輯sql 的執行場景,MySQL的鎖機制 ,各種鎖之間的相容性,必要時還需要透徹的理解原始碼。
工欲善其事必先利其器,前面分析了很多死鎖案例,並沒有詳細的介紹如何透過死鎖日誌來診斷死鎖的成因。本文將介紹如何讀懂死鎖日誌,儘可能的獲取資訊來輔助我們解決死鎖問題。
二 日誌分析
2.1 場景
為了更好的學習死鎖日誌,我們需要提前瞭解死鎖場景
MySQL 5.6 事務隔離級別為RR
-
CREATE TABLE `ty` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`a` int(11) DEFAULT NULL,
-
`b` int(11) DEFAULT NULL,
-
PRIMARY KEY (`id`),
-
KEY `idxa` (`a`)
-
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4
- insert into ty(a,b) values(2,3),(5,4),(6,7);
T2 |
T1 |
begin; |
|
delete from ty where a=5; |
begin; |
|
delete from ty where a=5; |
insert into ty(a,b) values(2,10); |
|
|
delete from ty where a=5; ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
2.3 我們透過show engine innodb status 檢視的日誌是最新一次記錄死鎖的日誌。
-
------------------------
-
LATEST DETECTED DEADLOCK
-
------------------------
-
2017-09-09 22:34:13 7f78eab82700
-
*** (1) TRANSACTION: #事務1
-
TRANSACTION 462308399, ACTIVE 33 sec starting index read
-
mysql tables in use 1, locked 1
-
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
-
MySQL thread id 3525577, OS thread handle 0x7f896cc4b700, query id 780039657 localhost root updating
-
delete from ty where a=5
-
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
-
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308399 lock_mode X waiting
-
*** (2) TRANSACTION:
-
TRANSACTION 462308398, ACTIVE 61 sec inserting, thread declared inside InnoDB 5000
-
mysql tables in use 1, locked 1
-
5 lock struct(s), heap size 1184, 4 row lock(s), undo log entries 2
-
MySQL thread id 3525490, OS thread handle 0x7f78eab82700, query id 780039714 localhost root update
-
insert into ty(a,b) values(2,10)
-
*** (2) HOLDS THE LOCK(S):
-
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X
-
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
-
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X locks gap before rec insert intention waiting
- *** WE ROLL BACK TRANSACTION (1)
*** (1) TRANSACTION: #事務1
TRANSACTION 462308399, ACTIVE 33 sec starting index read
事務編號為 462308399 ,活躍33秒,starting index read 表示事務狀態為根據索引讀取資料。常見的其他狀態:
-
fetching rows 表示事務狀態在row_search_for_mysql中被設定,表示正在查詢記錄。
-
updating or deleting 表示事務已經真正進入了Update/delete的函式邏輯(row_update_for_mysql)
- thread declared inside InnoDB 說明事務已經進入innodb層。通常而言 不在innodb層的事務大部分是會被回滾的。
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
LOCK WAIT表示正在等待鎖, 2 lock struct(s) 表示trx->trx_locks鎖連結串列的長度為2,每個連結串列節點代表該事務持有的一個鎖結構,包括表鎖,記錄鎖以及auto_inc鎖等。本案例中2locks 表示IX鎖和lock_mode X(Next-key lock)
heap size 360 表示事務分配的鎖堆記憶體大小,一般沒有什麼具體的用處。
1 row lock(s)表示當前事務持有的行記錄鎖/gap 鎖的個數。
delete from ty where a=5 表示事務1在執行的sql ,不過比較悲傷的事情是show engine innodb status 是檢視不到完整的事務的sql 的,通常顯示當前正在等待鎖的sql。
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308399 lock_mode X waiting
RECORD LOCKS 表示記錄鎖,space id為219,page號4 ,n bits 72表示這個聚集索引記錄鎖結構上留有72個Bit位
表示事務1 正在等待表 ty 上的 idxa 的 X 鎖本案例中其實是Next-Key lock
事務2的log 和上面分析類似,
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X
顯示了事務2 insert into ty(a,b) values(2,10)持有了a=5 的Lock mode X |LOCK_GAP ,不過我們從日誌裡面看不到 事務2 執行的 delete from ty where a=5;這點也是造成DBA 僅僅根據日誌難以分析死鎖的問題的根本原因。
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X locks gap before rec insert intention waiting
表示事務2的insert 語句正在等待插入意向鎖 lock_mode X locks gap before rec insert intention waiting (LOCK_X + LOCK_REC_GAP )
這裡需要各位注意的是鎖組合,類似lock_mode X waiting ,lock_mode X,lock_mode X locks gap before rec insert intention waiting 是我們分析死鎖的核心重點。如何理解鎖組合呢?
首先我們要知道對於MySQL有兩種常規鎖模式
LOCK_S(讀鎖,共享鎖)
LOCK_X(寫鎖,排它鎖)
最容易理解的鎖模式,讀加共享鎖,寫加排它鎖.
有如下幾種鎖的屬性
LOCK_REC_NOT_GAP (鎖記錄)
LOCK_GAP (鎖記錄前的GAP)
LOCK_ORDINARY (同時鎖記錄+記錄前的GAP 。傳說中的Next Key鎖)
LOCK_INSERT_INTENTION(插入意向鎖,其實是特殊的GAP鎖)
鎖的屬性可以與鎖模式任意組合。例如.
lock->type_mode 可以是Lock_X 或者Lock_S
locks gap before rec 表示為gap鎖:lock->type_mode & LOCK_GAP
locks rec but not gap 表示為記錄鎖,非gap鎖:lock->type_mode & LOCK_REC_NOT_GAP
insert intention 表示為插入意向鎖:lock->type_mode & LOCK_INSERT_INTENTION
waiting 表示鎖等待:lock->type_mode & LOCK_WAIT
三 小結
本文算是簡單的死鎖分析入門,能夠提供部分死鎖分析的所需要的技術知識。死鎖分析確是一門技術活兒,想要透徹的分析死鎖的成因,我們必須要了解造成死鎖的業務邏輯sql 的執行場景,MySQL的鎖機制 ,各種鎖之間的相容性,必要時還需要透徹的理解原始碼。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22664653/viewspace-2145133/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL列印死鎖日誌MySql
- MySQL 死鎖日誌分析MySql
- MySQL 死鎖與日誌二三事MySql
- 簡單介紹MySQL列印死鎖日誌的方法MySql
- mysql-innodb 日誌機制分析----寫在死鎖前面MySql
- 面試:什麼是死鎖,如何避免或解決死鎖;MySQL中的死鎖現象,MySQL死鎖如何解決面試MySql
- Mysql如何處理死鎖MySql
- mysql 鎖的慢日誌MySql
- MySQL InnoDB如何應付死鎖MySql
- MySQL 死鎖和鎖等待MySql
- MySQL死鎖系列-線上死鎖問題排查思路MySql
- MySQL 死鎖解決MySql
- MySQL死鎖問題MySql
- 【MySQL】漫談死鎖MySql
- MySQL解決死鎖MySql
- 什麼是死鎖?如何解決死鎖?
- mysql行鎖和死鎖檢測MySql
- Mysql 兩階段鎖和死鎖MySql
- MySQL:一個死鎖分析 (未分析出來的死鎖)MySql
- MySQL 死鎖問題分析MySql
- MySQL:死鎖一例MySql
- MySQL:MTS和mysqldump死鎖MySql
- 【MySQL】死鎖案例之六MySql
- 【MySQL】死鎖案例之七MySql
- 【MySQL】死鎖案例之八MySql
- 【MySQL】死鎖案例之四MySql
- 【MySQL】死鎖案例之一MySql
- 【MySQL】死鎖案例之二MySql
- 【MySQL】死鎖案例之三MySql
- mysql死鎖最佳化MySql
- LNAV:基於 Ncurses 的日誌檔案閱讀器
- MySQL鎖等待與死鎖問題分析MySql
- MySQL 事務、日誌、鎖、索引學習總結,MySql索引
- 研發日誌技術篇(上)——如何死磕GPUGPU
- MySQL批量更新死鎖案例分析MySql
- MySQL:Innodb 一個死鎖案例MySql
- 故障分析 | MySQL死鎖案例分析MySql
- 解讀MySQL的InnoDB引擎日誌工作原理MySql