日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

mysql len hex asc_线上频出MySQL死锁问题!分享一下自己教科书般的排查和分析过程!...

發(fā)布時(shí)間:2025/3/19 数据库 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql len hex asc_线上频出MySQL死锁问题!分享一下自己教科书般的排查和分析过程!... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文主要是講過程與思路,從手上的日志來(lái)反推故障現(xiàn)場(chǎng),最后模擬出事故現(xiàn)場(chǎng)。沒有過度講解理論的一些知識(shí),主要是偏分析。

文章參考的理論知識(shí)在最后,同時(shí)也將本次案例提交 ISSUE 給:https://github.com/aneasystone/mysql-deadlocks/issues/22?倉(cāng)庫(kù)。

項(xiàng)目源碼地址:https://github.com/LiWenGu/transaction_lock.git

1. 日志

1.1 業(yè)務(wù)日志

一直平穩(wěn)運(yùn)行大半年的代碼,突然在最近幾天頻出現(xiàn)死鎖異常,業(yè)務(wù)機(jī)器大概每一兩天在業(yè)務(wù)高峰期發(fā)生一次如下的業(yè)務(wù)日志:INFO 57553 ---?[ConsumerThread2] org.example.controller.TestController ???:?全局鏈路跟蹤id:2的日志:[TransactionReqVO(userId=4, money=4), TransactionReqVO(userId=2, money=2), TransactionReqVO(userId=5, money=5)]

INFO 57553 ---?[ConsumerThread1] org.example.controller.TestController ???:?全局鏈路跟蹤id:1的日志:[TransactionReqVO(userId=5, money=5), TransactionReqVO(userId=1, money=1), TransactionReqVO(userId=4, money=4)]

ERROR 57553 ---?[ConsumerThread2] org.example.controller.TestController ???:?全局鏈路跟蹤id:2的異常:

###?Error?updating?database.??Cause:?com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:?Deadlock?found?when?trying?to?get?lock;?try?restarting?transaction

###?The?error?may?exist?in?org/example/mapper/TestTableMapper.java?(best?guess)

###?The?error?may?involve?org.example.mapper.TestTableMapper.update-Inline

###?The?error?occurred?while?setting?parameters

###?SQL:?UPDATE?test_table?SET?money?=?money?+???WHERE?user_id?=??

###?Cause:?com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:?Deadlock?found?when?trying?to?get?lock;?try?restarting?transaction

;?Deadlock?found?when?trying?to?get?lock;?try?restarting?transaction;?nested?exception?is?com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:?Deadlock?found?when?trying?to?get?lock;?try?restarting?transaction

org.springframework.dao.DeadlockLoserDataAccessException:

###?Error?updating?database.??Cause:?com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:?Deadlock?found?when?trying?to?get?lock;?try?restarting?transaction

###?The?error?may?exist?in?org/example/mapper/TestTableMapper.java?(best?guess)

###?The?error?may?involve?org.example.mapper.TestTableMapper.update-Inline

###?The?error?occurred?while?setting?parameters

###?SQL:?UPDATE?test_table?SET?money?=?money?+???WHERE?user_id?=??

###?Cause:?com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:?Deadlock?found?when?trying?to?get?lock;?try?restarting?transaction

;?Deadlock?found?when?trying?to?get?lock;?try?restarting?transaction;?nested?exception?is?com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:?Deadlock?found?when?trying?to?get?lock;?try?restarting?transaction

at?org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:266)?~[spring-jdbc-5.0.13.RELEASE.jar:5.0.13.RELEASE]

at?org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)?~[spring-jdbc-5.0.13.RELEASE.jar:5.0.13.RELEASE]

at?org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)?~[mybatis-spring-2.0.1.jar:2.0.1]

at?org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)?~[mybatis-spring-2.0.1.jar:2.0.1]

at?com.sun.proxy.$Proxy59.update(Unknown?Source)?~[na:na]

at?org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:294)?~[mybatis-spring-2.0.1.jar:2.0.1]

at?org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:67)?~[mybatis-3.5.1.jar:3.5.1]

at?org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:58)?~[mybatis-3.5.1.jar:3.5.1]

at?com.sun.proxy.$Proxy62.update(Unknown?Source)?~[na:na]

at?org.example.service.impl.TestServiceImpl.update(TestServiceImpl.java:16)?~[classes/:na]

at?org.example.manager.impl.BizManagerImpl.transactionMoney(BizManagerImpl.java:25)?~[classes/:na]

at?org.example.manager.impl.BizManagerImpl$$FastClassBySpringCGLIB$$824241b9.invoke()?~[classes/:na]

Deadlock?非常顯眼,說(shuō)明業(yè)務(wù)上出現(xiàn)了死鎖,肯定是業(yè)務(wù)上有問題。但是該業(yè)務(wù)代碼一直運(yùn)行了大半年,查看 Git 記錄也發(fā)現(xiàn)最近沒人動(dòng)該業(yè)務(wù)相關(guān)代碼,說(shuō)明該業(yè)務(wù)之前就可能有問題,只是最近才達(dá)到了觸發(fā)這種異常的條件。

對(duì)該日志做個(gè)簡(jiǎn)單的總結(jié):

1.這是什么錯(cuò)誤日志?8行:### SQL: UPDATE test_table SET money = money + ? WHERE user_id = ?

9行:### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction

從第 8~9 行可以得知,該錯(cuò)誤是數(shù)據(jù)庫(kù)的錯(cuò)誤,是死鎖錯(cuò)誤異常而導(dǎo)致的回滾,關(guān)鍵 SQL 是:UPDATE test_table SET money = money + ? WHERE user_id = ?

2.核心錯(cuò)誤的調(diào)用方法是哪個(gè),即事務(wù)開始的方法是哪個(gè)?

30行:at org.example.manager.impl.BizManagerImpl.transactionMoney(BizManagerImpl.java:25) ~[classes/:na] 31行:at org.example.manager.impl.BizManagerImpl$$FastClassBySpringCGLIB$$824241b9.invoke() ~[classes/:na]

過濾了 jdk 類、spring 類、mybatis 類后,得到核心的業(yè)務(wù)錯(cuò)誤代碼(30~31 行),31 行為 Spring 的代理執(zhí)行,30 行才是真正最開始執(zhí)行業(yè)務(wù)代碼:BizManagerImpl.transactionMoney

1.2 數(shù)據(jù)庫(kù)死鎖日志

接著去查看該庫(kù)對(duì)應(yīng)的數(shù)據(jù)庫(kù)死鎖日志,使用命令:show innodb engine status,過濾掉非重要的日志后如下:------------------------

LATEST?DETECTED?DEADLOCK

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

2020-07-14?23:34:29?0x7f958f1d5700

***?(1)?TRANSACTION:

TRANSACTION?95146580,?ACTIVE?2?sec?starting?index?read

mysql?tables?in?use?1,?locked?1

LOCK?WAIT?4?lock?struct(s),?heap?size?1136,?5?row?lock(s),?undo?log?entries?2

MySQL?thread?id?6264489,?OS?thread?handle?140273305761536,?query?id?837446998?10.10.59.164?root?updating

UPDATE?test_table?SET?money?=?money?+?5?WHERE?user_id?=?5

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

RECORD?LOCKS?space?id?71816?page?no?4?n?bits?80?index?idx_user_id?of?table?`mall`.`test_table`?trx?id?95146580?lock_mode?X?locks?rec?but?not?gap?waiting

Record?lock,?heap?no?3?PHYSICAL?RECORD:?n_fields?2;?compact?format;?info?bits?0

0:?len?8;?hex?8000000000000005;?asc?????????;;

1:?len?8;?hex?8000000000000006;?asc?????????;;

***?(2)?TRANSACTION:

TRANSACTION?95146581,?ACTIVE?2?sec?starting?index?read

mysql?tables?in?use?1,?locked?1

4?lock?struct(s),?heap?size?1136,?5?row?lock(s),?undo?log?entries?2

MySQL?thread?id?6264490,?OS?thread?handle?140280327919360,?query?id?837446999?10.10.59.164?root?updating

UPDATE?test_table?SET?money?=?money?+?4?WHERE?user_id?=?4

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

RECORD?LOCKS?space?id?71816?page?no?4?n?bits?80?index?idx_user_id?of?table?`mall`.`test_table`?trx?id?95146581?lock_mode?X?locks?rec?but?not?gap

Record?lock,?heap?no?3?PHYSICAL?RECORD:?n_fields?2;?compact?format;?info?bits?0

0:?len?8;?hex?8000000000000005;?asc?????????;;

1:?len?8;?hex?8000000000000006;?asc?????????;;

Record?lock,?heap?no?5?PHYSICAL?RECORD:?n_fields?2;?compact?format;?info?bits?0

0:?len?8;?hex?8000000000000001;?asc?????????;;

1:?len?8;?hex?8000000000000002;?asc?????????;;

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

RECORD?LOCKS?space?id?71816?page?no?4?n?bits?80?index?idx_user_id?of?table?`mall`.`test_table`?trx?id?95146581?lock_mode?X?locks?rec?but?not?gap?waiting

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

0:?len?8;?hex?8000000000000004;?asc?????????;;

1:?len?8;?hex?8000000000000005;?asc?????????;;

***?WE?ROLL?BACK?TRANSACTION?(2)

關(guān)鍵點(diǎn)總結(jié)如下:

1.該庫(kù)中最近一次死鎖發(fā)生的時(shí)間是什么時(shí)候?4行:2020-07-14 23:34:29 0x7f958f1d5700

得知,最近一次死鎖發(fā)生在 2020-07-14 23:34:29

2.該次死鎖導(dǎo)致的兩個(gè)事務(wù)的重要信息?12行:RECORD LOCKS space id 71816 page no 4 n bits 80 index idx_user_id of table?mall.test_table?trx id 95146580 lock_mode X locks rec but not gap waiting

得知,事務(wù) 1 等待的鎖為:lock_mode X locks rec but not gap waiting24行:RECORD LOCKS space id 71816 page no 4 n bits 80 index idx_user_id of table?mall.test_table?trx id 95146581 lock_mode X locks rec but not gap

得知,事務(wù) 2 持有的鎖為:lock_mode X locks rec but not gap34行:RECORD LOCKS space id 71816 page no 4 n bits 80 index idx_user_id of table?mall.test_table?trx id 95146581 lock_mode X locks rec but not gap waiting

得知,事務(wù) 2 等待的鎖為:lock_mode X locks rec but not gap waiting39行:*** WE ROLL BACK TRANSACTION (2)

得知,最后回滾的是事務(wù) 1從 12、24、34 行:index idx_user_id of table?mall.test_table

得知:導(dǎo)致該次死鎖的索引為:idx_user_id

3.能知道導(dǎo)致死鎖的兩個(gè)具體 SQL 嗎?不能,產(chǎn)生死鎖的情況各式各樣,事務(wù)中的 SQL 可能不止有兩個(gè) SQL,單從死鎖日志是沒法知道具體原因的,必須要結(jié)合業(yè)務(wù)代碼查看事務(wù)上下文查看

2. 理論知識(shí)

排查過程中發(fā)現(xiàn)有個(gè)特點(diǎn),影響的都是是線上的大用戶。由于當(dāng)時(shí)我很久沒看死鎖相關(guān)的理論知識(shí),因此先去了解下相關(guān)死鎖的基本知識(shí)。

2.1 死鎖的條件互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用。

占有且等待:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí),對(duì)已獲得的資源保持不放。

不可強(qiáng)行占有:進(jìn)程已獲得的資源,在末使用完之前,不能強(qiáng)行剝奪。

循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。

破壞死鎖也很簡(jiǎn)單,四個(gè)條件破一個(gè)即可。(本案例是破壞的 4)

2.2 數(shù)據(jù)庫(kù)的鎖類型

數(shù)據(jù)庫(kù)的死鎖比較復(fù)雜,主要是由 Insert、Update(其實(shí)在開發(fā)中 Delete 或 For Update 是不怎么不考慮的,因?yàn)樵趯?shí)際業(yè)務(wù)代碼中我們一般不會(huì)有 Delete 或 For Update 的操作,刪除都是物理刪除,for update 建議少用,除非你知道非用不可)。

InnoDB 的鎖:共享鎖與獨(dú)占鎖(S、X)

意向鎖

記錄鎖(Record Locks)

間隙鎖(Gap Locks)

Next-Key Locks

插入意向鎖

自增鎖

空間索引斷言鎖

這里參考了官網(wǎng)的 Innodb 鎖分類,從死鎖日志的?lock_mode X locks rec but not gap?,大致能知道,這里可能涉及了 X 鎖、記錄鎖、間隙鎖(但是有個(gè) not,說(shuō)明不涉及)。

3. ?從死鎖日志分析

分析之前先得到該表的建表語(yǔ)句:show create table test_table;:CREATE?TABLE?`test_table`?(

`id`?bigint(20)?NOT?NULL?AUTO_INCREMENT,

`money`?bigint(20)?NOT?NULL,

`user_id`?bigint(20)?NOT?NULL,

PRIMARY?KEY?(`id`),

KEY?`idx_user_id`?(`user_id`)

)?ENGINE=InnoDB?AUTO_INCREMENT=5?DEFAULT?CHARSET=utf8

接著結(jié)合死鎖日志、鎖的種類、建表語(yǔ)句得出以下模糊的結(jié)論:

1.從死鎖日志的 10、12 行結(jié)合建表索引得知10行:UPDATE test_table SET money = money + 5 WHERE user_id = 5

12行:RECORD LOCKS space id 71816 page no 4 n bits 80 index idx_user_id of table?mall.test_table?trx id 95146580

事務(wù)1的?UPDATE test_table SET money = money + 5 WHERE user_id = 5? 語(yǔ)句在等待鎖:它通過普通索引 idx_user_id 更新,先獲取了 user_id=5 的 X 鎖,接著去申請(qǐng)對(duì)應(yīng)行的主鍵(Record Lock)的行鎖但是被阻塞(waiting),并不包括間隙鎖(not gap)。具體是哪個(gè)主鍵我們并不清楚。

2.從死鎖日志的 22、24 行結(jié)合建表索引得知22行:UPDATE test_table SET money = money + 4 WHERE user_id = 4

24行:Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0

事務(wù)2的?UPDATE test_table SET money = money + 4 WHERE user_id = 4? 語(yǔ)句在持有鎖:它通過普通索引 idx_user_id 更新,先獲取了 user_id=4 的 X 鎖,接著去申請(qǐng)對(duì)應(yīng)行的主鍵(Record Lock)的行鎖成功了,并不包括間隙鎖(not gap)。具體是成功的哪個(gè)主鍵我們并不清楚。

3.從死鎖日志的 22、34 行結(jié)合建表索引得知22行:UPDATE test_table SET money = money + 4 WHERE user_id = 4

34行:RECORD LOCKS space id 71816 page no 4 n bits 80 index idx_user_id of table?mall.test_table?trx id 95146581 lock_mode X locks rec but not gap waiting

事務(wù)2的?UPDATE test_table SET money = money + 4 WHERE user_id = 4? 語(yǔ)句在等待鎖:它通過普通索引 idx_user_id 更新,先獲取了 user_id=4 的 X 鎖,接著去申請(qǐng)對(duì)應(yīng)行的主鍵(Record Lock)的行鎖但是被阻塞(waiting),并不包括間隙鎖(not gap)。具體是哪個(gè)主鍵我們并不清楚。

模糊結(jié)論肯定是有問題的,最大的問題在于導(dǎo)致的 SQL 語(yǔ)句不正確,即:死鎖的原因是真實(shí)的,但是具體是因?yàn)槟男?SQL 導(dǎo)致的死鎖是不清楚的。接著我們整理得到了以下可能有問題的表格:

事務(wù)1事務(wù)2某些 SQL某些 SQL

某個(gè) SQL 的 user_id = 5 行更新操作被阻塞了某個(gè) SQL 的 user_id = 4 獲得了鎖但是又阻塞了

某些 SQL某些 SQL

可以得知,其實(shí)單從死鎖日志分析是比較片面的,因?yàn)?user_id 為 4、5 這兩個(gè) update 操作是不會(huì)有互相阻塞的問題,肯定是有別的 SQL 影響,我們需要額外從業(yè)務(wù)日志分析才能還原完整的現(xiàn)場(chǎng)。

4. 從業(yè)務(wù)日志分析

從死鎖日志是不能完全知道導(dǎo)致的關(guān)鍵 SQL 和故障現(xiàn)場(chǎng)的整體流程,因此我們要借助業(yè)務(wù)日志來(lái)完成最后對(duì)故障現(xiàn)場(chǎng)的分析:

通過前面對(duì)業(yè)務(wù)日志的分析,我們知道最關(guān)鍵的調(diào)用方法是?BizManagerImpl.transactionMoney,查看對(duì)應(yīng)源碼:@Override

@Transactional

public?boolean?transactionMoney(List?transactionReqVOList)?throws?Exception{

for?(TransactionReqVO?transactionReqVO?:?transactionReqVOList)?{

//?模擬業(yè)務(wù)操作

Thread.sleep(1000);

int?updateCount?=?testTableService.update(transactionReqVO.getUserId(),?transactionReqVO.getMoney());

if?(updateCount?==?0)?{

log.error("轉(zhuǎn)賬異常:"?+?transactionReqVO);

}

}

return?true;

}

可以知道,應(yīng)該是 for 循環(huán)事務(wù)的問題,但是具體是哪些 user_id 是不清楚的,接著我們查看業(yè)務(wù)日志的上下文,通過全鏈路 traceId(模擬) 做搜索,得到以下的日志:[ConsumerThread2] org.example.controller.TestController ? ?: 全局鏈路跟蹤id:2的日志:[TransactionReqVO(userId=4, money=4), TransactionReqVO(userId=2, money=2), TransactionReqVO(userId=5, money=5)]

[ConsumerThread1] org.example.controller.TestController ? ?: 全局鏈路跟蹤id:1的日志:[TransactionReqVO(userId=5, money=5), TransactionReqVO(userId=1, money=1), TransactionReqVO(userId=4, money=4)]

分析到這一步,我們已經(jīng)可以還原死鎖場(chǎng)景了,事務(wù)流程圖如下:

事務(wù)1事務(wù)2UPDATE test_table SET money = money + 4 WHERE user_id = 4UPDATE test_table SET money = money + 5 WHERE user_id = 5

UPDATE test_table SET money = money + 2 WHERE user_id = 2UPDATE test_table SET money = money + 1 WHERE user_id = 1

UPDATE test_table SET money = money + 5 WHERE user_id = 5UPDATE test_table SET money = money + 4 WHERE user_id = 4

5. 業(yè)務(wù)日志、死鎖日志結(jié)合分析

將死鎖日志分析得出的不正確表格加上業(yè)務(wù)日志分析得出正確表格,我們得出最終帶有理解的最終正確的事務(wù)表格:

事務(wù)1事務(wù)2UPDATE test_table SET money = money + 4 WHERE user_id = 4 持有 user_id 為 4 的行鎖UPDATE test_table SET money = money + 5 WHERE user_id = 5 持有 user_id 為 5 的行鎖

UPDATE test_table SET money = money + 2 WHERE user_id = 2?持有 user_id 為 2 的行鎖UPDATE test_table SET money = money + 1 WHERE user_id = 1?持有 user_id 為 1 的行鎖

UPDATE test_table SET money = money + 5 WHERE user_id = 5

阻塞中...等待持有 user_id 為 5 的行鎖解鎖UPDATE test_table SET money = money + 4 WHERE user_id = 4

阻塞中...user_id等待持有 user_id 為 4 的行鎖解鎖

回滾

提交

可以知道,其實(shí)死鎖日志的 SQL 是模糊的,但是原因是正確的,至于具體是哪些 SQL 導(dǎo)致的死鎖,是需要從業(yè)務(wù)日志來(lái)判定。

6. 善后

模擬出了事務(wù)2的場(chǎng)景,我們就可以對(duì)回滾的 SQL 執(zhí)行,來(lái)人工修復(fù)受到影響的用戶數(shù)據(jù)(客戶第一)。

也可以知道其實(shí)?transactionMoney()??方法不應(yīng)該加事務(wù),因?yàn)樵摌I(yè)務(wù)場(chǎng)景每個(gè)用戶的更新是獨(dú)立的不應(yīng)該互相受到影響,但是當(dāng)某條更新失敗時(shí),我們也要打印對(duì)應(yīng)的日志。

這里我們就知道為什么之前大半年都沒問題,最近才頻發(fā)這種異常,因?yàn)橹挥挟?dāng)兩個(gè)事務(wù)同時(shí)執(zhí)行,并且兩個(gè)事務(wù)中包含了相同的兩個(gè)或兩個(gè)以上的 user_id 才會(huì)可能觸發(fā)該異常。而這種 user_id 都是所謂的大用戶,像該示例中的 user_id 為 1、2 是小用戶,雖然它們也受到了影響,但是頻率是沒有 user_id 為 4、5 這種大用戶高的。

在實(shí)際的業(yè)務(wù)場(chǎng)景也證實(shí)了這點(diǎn),不僅是發(fā)生故障的時(shí)間是集中在高峰期,而且發(fā)生故障的用戶也經(jīng)常有那幾個(gè)熟面孔,經(jīng)過后面復(fù)盤,這幾個(gè)熟面孔用戶也就是我們所說(shuō)的”大用戶“(業(yè)務(wù)操作頻率高的用戶)。

7. 模擬項(xiàng)目源碼

為了模擬真實(shí)場(chǎng)景中的方法調(diào)用(消息接收調(diào)用執(zhí)行),使用了線程來(lái)模擬。

并且使用線程睡眠來(lái)保證每個(gè)事務(wù)執(zhí)行夠長(zhǎng),來(lái)讓每次模擬執(zhí)行都必現(xiàn)異常。

項(xiàng)目結(jié)構(gòu)比較簡(jiǎn)單, Controller -> Manager -> Service -> Mapper -> DB,執(zhí)行?curl 'localhost:8080/test/consumer'?后,查看命令行輸出即可看到業(yè)務(wù)異常日志。

對(duì)應(yīng)的死鎖日志需要到對(duì)應(yīng)的數(shù)據(jù)庫(kù)執(zhí)行:show engine innodb status?后可看到。

8. 最后

中間查閱了很多資料,發(fā)現(xiàn)有個(gè)項(xiàng)目總結(jié)了所有的死鎖日志對(duì)應(yīng)的可能 SQL:https://github.com/aneasystone/mysql-deadlocks,里面也講解了加鎖的各個(gè)細(xì)節(jié)過程,是非常值得一看的。

以下為該項(xiàng)目的部分截圖:

當(dāng)遇到復(fù)雜的業(yè)務(wù)場(chǎng)景,尤其是不熟悉的時(shí)候,這個(gè)是一個(gè)很好的參考資料。業(yè)務(wù)日志記錄、全鏈路跟蹤是非常非常重要的

總結(jié)

以上是生活随笔為你收集整理的mysql len hex asc_线上频出MySQL死锁问题!分享一下自己教科书般的排查和分析过程!...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。