MYSQL:1213 Deadlock問題排查歷程

mark下自己近期在電商開發(fā)中遇到的一個(gè)問題-數(shù)據(jù)庫(kù)死鎖及其排查過程。
先拋一個(gè)業(yè)務(wù)報(bào)錯(cuò)日志做為這次梳理的開始



上圖是我接收到的錯(cuò)誤報(bào)警,SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction,錯(cuò)誤信息顯示我們業(yè)務(wù)中有一條數(shù)據(jù)庫(kù)操作遇到了死鎖情況。接下來就開始我們的追查之旅。

1.執(zhí)行“show engine innodb status”獲取INNODB引擎當(dāng)前信息(show engine innodb status 詳細(xì)介紹

------------------------

LATEST DETECTED DEADLOCK

------------------------

2017-01-04 09:25:17 7f553477d700

*** (1) TRANSACTION:

TRANSACTION 124378994, ACTIVE 0.007 sec starting index read

mysql tables in use 1, locked 1

LOCK WAIT 4 lock struct(s), heap size 1184, 8 row lock(s), undo log entries 7

LOCK BLOCKING MySQL thread id: 11573556 block 11572504

MySQL thread id 11572504, OS thread handle 0x7f56342fb700, query id 3368968901 10.44.182.0 shzfstore updating

UPDATE `sku` SET `quantity`=quantity-'1',`lock_stock`=lock_stock+'1',`sys_version`=sys_version+1 WHERE `id` = '15608' AND `quantity` >= '1' limit 1

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 393 page no 45 n bits 248 index `PRIMARY` of table `store_product`.`sku` trx id 124378994 lock_mode X locks rec but not gap waiting

Record lock, heap no 19 PHYSICAL RECORD: n_fields 19; compact format; info bits 0

......

*** (2) TRANSACTION:

TRANSACTION 124378995, ACTIVE 0.004 sec starting index read

mysql tables in use 1, locked 1

3 lock struct(s), heap size 1184, 2 row lock(s), undo log entries 1

MySQL thread id 11573556, OS thread handle 0x7f553477d700, query id 3368968902 10.172.221.117 shzfstore updating

UPDATE `sku` SET `quantity`=quantity-'1',`lock_stock`=lock_stock+'1',`sys_version`=sys_version+1 WHERE `id` = '15504' AND `quantity` >= '1' limit 1

*** (2) HOLDS THE LOCK(S):

RECORD LOCKS space id 393 page no 45 n bits 248 index `PRIMARY` of table `store_product`.`sku` trx id 124378995 lock_mode X locks rec but not gap

Record lock, heap no 19 PHYSICAL RECORD: n_fields 19; compact format; info bits 0

......

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 393 page no 43 n bits 240 index `PRIMARY` of table `store_product`.`sku` trx id 124378995 lock_mode X locks rec but not gap waiting

Record lock, heap no 81 PHYSICAL RECORD: n_fields 19; compact format; info bits 0

......

*** WE ROLL BACK TRANSACTION (2)

LATEST DETECTED DEADLOCK記錄了最近一次的死鎖情況士八。
2017-01-04 09:25:17時(shí)間跟我們接收到的報(bào)錯(cuò)日志時(shí)間吻合。
上面還可以看出兩個(gè)事務(wù)之間發(fā)生鎖競(jìng)爭(zhēng)時(shí)梁呈,給我們留下的部分?jǐn)?shù)據(jù)
事務(wù)1
UPDATEskuSETquantity=quantity-'1',lock_stock=lock_stock+'1',sys_version=sys_version+1 WHEREid= '15608' ANDquantity>= '1' limit 1
事務(wù)2
UPDATEskuSETquantity=quantity-'1',lock_stock=lock_stock+'1',sys_version=sys_version+1 WHEREid= '15504' ANDquantity>= '1' limit 1
死鎖的兩個(gè)資源均被lock_mode X locks了

最后婚度,mysql給了很重要的一個(gè)數(shù)據(jù)“WE ROLL BACK TRANSACTION (2)” MYSQL回滾了事務(wù)2。既然mysql回滾了事務(wù)2官卡,那么肯定是事務(wù)2的語(yǔ)句觸發(fā)了死鎖蝗茁,被mysql回滾了醋虏,也就是應(yīng)該為報(bào)錯(cuò)日志所記錄的那部分。同時(shí)哮翘,MYSQL執(zhí)行了事務(wù)1颈嚼,那么事務(wù)1的SQL語(yǔ)句肯定被記錄在BINLOG中了。

2.查看binlog日志饭寺,找出事務(wù)1所執(zhí)行的語(yǔ)句

查找依據(jù):

  • SQL語(yǔ)句,根據(jù)LATEST DETECTED DEADLOCK提供的死鎖時(shí)記錄的sql語(yǔ)句阻课。
  • 線程ID(mysql的唯一標(biāo)識(shí)): MySQL thread id 11572504
  • 執(zhí)行時(shí)間(時(shí)間線):2017-01-04 09:25:17 7f553477d700

根據(jù)以上三個(gè)標(biāo)識(shí),以及BINLOG的起始標(biāo)志“BEGIN佩研、COMMIT”柑肴,幾乎可以100%確定事務(wù)1所包含的SQL語(yǔ)句。

binlog信息大致如下

#170104  9:25:17 server id 3194178605  end_log_pos 137170469 CRC32 0x1b6559de   Query   thread_id=11572504  exec_time=0 error_code=0
SET TIMESTAMP=1483493117/*!*/;
BEGIN
......
### UPDATE `store_product`.`sku`
### WHERE
###   @1=15504
###   @2=11516
###   @3=0.01
###   @4=120065
###   @5=109433
###   @6=19
### SET
###   @1=15504
###   @2=11516
###   @3=0.01
###   @4=120065
###   @5=109432
###   @6=20
# at 137172557
......
### UPDATE `store_product`.`sku`
### WHERE
###   @1=15608
###   @2=11551
###   @3=0.01
###   @4=120077
###   @5=109426
###   @6=19
### SET
###   @1=15608
###   @2=11551
###   @3=0.01
###   @4=120077
###   @5=109425
###   @6=20
......
COMMIT/*!*/;

3.還原事務(wù)2所包含的執(zhí)行語(yǔ)句

事務(wù)1的語(yǔ)句找齊了旬薯,接下來找事務(wù)2的語(yǔ)句,還記得我們開頭提供的報(bào)錯(cuò)日志嗎适秩,那個(gè)日志里也詳細(xì)記錄了發(fā)起請(qǐng)求時(shí)的參數(shù)情況(截圖未展示)绊序,根據(jù)參數(shù)和我們處理業(yè)務(wù)的代碼,可以復(fù)現(xiàn)事務(wù)2所要執(zhí)行的語(yǔ)句

BEGIN
......
### UPDATE `store_product`.`sku`
### WHERE
###   @1=15608
###   @2=11516
###   @3=0.01
###   @4=120065
###   @5=109433
###   @6=19
### SET
###   @1=15608
###   @2=11516
###   @3=0.01
###   @4=120065
###   @5=109432
###   @6=20
......
### UPDATE `store_product`.`sku`
### WHERE
###   @1=15504
###   @2=11551
###   @3=0.01
###   @4=120077
###   @5=109426
###   @6=19
### SET
###   @1=15504
###   @2=11551
###   @3=0.01
###   @4=120077
###   @5=109425
###   @6=20
......
COMMIT/*!*/;

根據(jù)兩個(gè)事務(wù)所執(zhí)行的sql語(yǔ)句秽荞,目前可以還原死鎖產(chǎn)生的原因了

4.查看兩個(gè)事務(wù)執(zhí)行語(yǔ)句的順序:

順序 事務(wù)1 事務(wù)2 說明
1 begin
2 begin
3 UPDATE sku
SET quantity=quantity-'1',
lock_stock=lock_stock+'1',
sys_version=sys_version+1
WHERE id = '15504' AND
quantity >= '1' limit 1
事務(wù)1 給 sku表 id 15504記錄上 X 鎖
4 UPDATE sku
SET quantity=quantity-'1',
lock_stock=lock_stock+'1',
sys_version=sys_version+1
WHERE id = '15608' AND
quantity >= '1' limit 1
事務(wù)2 給 sku表 id 15608記錄上 X 鎖
5 UPDATE sku
SET quantity=quantity-'1',
lock_stock=lock_stock+'1',
sys_version=sys_version+1 WHERE id = '15608' AND
quantity >= '1' limit 1
這里是關(guān)鍵骤公,事務(wù)1想給sku表 id 15608上X鎖,發(fā)現(xiàn)被別人(事務(wù)2)上鎖了扬跋,等待鎖釋放
6 UPDATE sku
SET quantity=quantity-'1',
lock_stock=lock_stock+'1',
sys_version=sys_version+1
WHERE id = '15504' AND
quantity >= '1' limit 1
事物2打算給sku表id為15504記錄上 X 排它鎖阶捆,發(fā)現(xiàn)被其他事務(wù)上了,而且此事務(wù)居然還在等他提交钦听,這時(shí)MYSQL立刻回滾事務(wù)2…(php發(fā)現(xiàn)MYSQL返回死鎖信息洒试,記錄該信息到錯(cuò)誤日志…發(fā)送回滾指令…mysql已經(jīng)“幫”他回滾了…)
7 執(zhí)行成功 事務(wù)1發(fā)現(xiàn)別人的鎖釋放了,獲得X鎖朴上,執(zhí)行成功
8 commit 事務(wù)1執(zhí)行成功垒棋,記錄binlog日志

解決方案

  • 減小事務(wù)中的語(yǔ)句數(shù)量
  • 在業(yè)務(wù)中調(diào)整語(yǔ)句的執(zhí)行順序,例如可以按照where條件中字段的大小進(jìn)行一下排序痪宰,按照排序后順序執(zhí)行叼架,讓死鎖變?yōu)殒i等待。

相關(guān)補(bǔ)充

  • innodb的行鎖衣撬,鎖的是查詢條件中的索引字段乖订,以及索引字段對(duì)應(yīng)的primary key字段
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市具练,隨后出現(xiàn)的幾起案子乍构,更是在濱河造成了極大的恐慌,老刑警劉巖靠粪,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜡吧,死亡現(xiàn)場(chǎng)離奇詭異毫蚓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)昔善,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門元潘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人君仆,你說我怎么就攤上這事翩概。” “怎么了返咱?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵钥庇,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我咖摹,道長(zhǎng)评姨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任萤晴,我火速辦了婚禮吐句,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘店读。我一直安慰自己嗦枢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布屯断。 她就那樣靜靜地躺著文虏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪殖演。 梳的紋絲不亂的頭發(fā)上氧秘,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音剃氧,去河邊找鬼敏储。 笑死,一個(gè)胖子當(dāng)著我的面吹牛朋鞍,可吹牛的內(nèi)容都是我干的已添。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼滥酥,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼更舞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起坎吻,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤缆蝉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體刊头,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡黍瞧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了原杂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片印颤。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖穿肄,靈堂內(nèi)的尸體忽然破棺而出年局,到底是詐尸還是另有隱情,我是刑警寧澤咸产,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布矢否,位于F島的核電站,受9級(jí)特大地震影響脑溢,放射性物質(zhì)發(fā)生泄漏僵朗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一焚志、第九天 我趴在偏房一處隱蔽的房頂上張望衣迷。 院中可真熱鬧,春花似錦酱酬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至让禀,卻和暖如春挑社,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巡揍。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工痛阻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腮敌。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓阱当,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親糜工。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弊添,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容