mysql死锁的例子_GitHub - yxp199249/mysql-deadlocks: 收集一些常见的 MySQL 死锁案例
mysql-deadlocks
在工作過程中偶爾會遇到死鎖問題,雖然這種問題遇到的概率不大,但每次遇到的時候要想徹底弄懂其原理并找到解決方案卻并不容易。這個項目收集了一些常見的 MySQL 死鎖案例,大多數(shù)案例都來源于網(wǎng)絡,并對其進行分類匯總,試圖通過死鎖日志分析出每種死鎖的原因,還原出死鎖現(xiàn)場。
實際上,我們在定位死鎖問題時,不僅應該對死鎖日志進行分析,還應該結(jié)合具體的業(yè)務代碼,或者根據(jù) binlog,理出每個事務執(zhí)行的 SQL 語句。
我將這些死鎖按事務執(zhí)行的語句和正在等待或已持有的鎖進行分類匯總:
事務一語句
事務二語句
事務一等待鎖
事務二等待鎖
事務二持有鎖
案例
insert
insert
lock_mode X insert intention
lock_mode X insert intention
lock_mode X
insert
insert
lock_mode X locks gap before rec insert intention
lock_mode X locks gap before rec insert intention
lock_mode X locks gap before rec
insert
insert
lock_mode X insert intention
lock_mode X insert intention
lock_mode S
insert
insert
lock mode S
lock_mode X locks gap before rec insert intention
lock_mode X locks rec but not gap
delete
insert
lock_mode X locks rec but not gap
lock mode S
lock_mode X locks rec but not gap
delete
delete
lock_mode X
lock mode S
lock_mode X locks rec but not gap
delete
delete
lock_mode X
lock mode X
lock_mode X locks rec but not gap
delete
delete
lock_mode X locks rec but not gap
lock_mode X
lock_mode X
delete
delete
lock_mode X locks rec but not gap
lock mode X
lock_mode X locks rec but not gap
delete
delete
lock_mode X locks rec but not gap
lock_mode X locks rec but not gap
lock_mode X locks rec but not gap
delete
insert
lock_mode X
lock_mode X locks gap before rec insert intention
lock_mode X locks rec but not gap
delete
insert
lock_mode X
lock_mode X locks gap before rec insert intention
lock_mode S
delete
insert
lock_mode X
lock_mode X locks gap before rec insert intention
lock_mode X
delete
insert
lock_mode X
lock mode S
lock_mode X locks rec but not gap
update
update
lock_mode X locks rec but not gap
lock mode S
lock_mode X locks rec but not gap
update
update
lock_mode X
lock_mode X locks gap before rec insert intention
lock_mode X locks rec but not gap
update
update
lock_mode X locks gap before rec insert intention
lock_mode X locks gap before rec insert intention
lock_mode X
update
delete
lock_mode X locks rec but not gap
lock_mode X
lock mode S
update
update
lock_mode X locks rec but not gap waiting
lock_mode X locks rec but not gap waiting
lock_mode X locks rec but not gap
表中的語句雖然大多數(shù)只列出了 delete 和 insert,但實際上絕大多數(shù)的 delete 語句和 update 或 select ... for update 加鎖機制是一樣的,所以為了避免重復,對于 update 語句就不在一起匯總了(當然也有例外,譬如使用 update 對索引進行更新時加鎖機制和 delete 是有區(qū)別的,這種情況我會單獨列出,如案例 11)。
對每一個死鎖場景,我都會定義一個死鎖名稱(實際上就是事務等待和持有的鎖),每一篇分析,我都分成了 死鎖特征、死鎖日志、表結(jié)構(gòu)、重現(xiàn)步驟、分析和參考 這幾個部分。
對于這種分類方法我感覺并不是很好,但也想不出什么其他更好的方案,如果你有更好的建議,歡迎討論。另外,如果你有新的死鎖案例,或者對某個死鎖的解釋有異議,歡迎給我提 Issue 或 PR。
死鎖分析
之前寫過關于死鎖的一系列博客,供參考。
死鎖重現(xiàn)
docker 目錄下包含了各個死鎖重現(xiàn)的測試腳本,測試步驟如下:
創(chuàng)建數(shù)據(jù)庫和初始數(shù)據(jù)
# cd docker
# docker-compose up -d
確保機器上安裝了 docker 和 docker-compose,上面的命令會啟動一個 mysql:5.7 的容器,并創(chuàng)建一個名為 dldb 的數(shù)據(jù)庫,初始密碼為 123456,并通過 docker-entrypoint-initdb.d 初始化所有案例所需要的表和數(shù)據(jù)。
等待容器啟動結(jié)束
# docker logs -f dldb
使用 dockere logs 查看容器啟動日志,如果出現(xiàn)數(shù)據(jù)初始化完成的提示,如下所示,則進入下一步。
MySQL init process in progress...
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
/usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/t16.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
/usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/t18.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
/usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/t8.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
MySQL init process done. Ready for start up.
進入容器執(zhí)行測試腳本
首先進入容器:
# docker exec -it dldb bash
然后執(zhí)行測試腳本,測試腳本在每一個案例對應的 SQL 文件中,比如案例 18 對應的測試腳本如下:
# mysqlslap --create-schema dldb -q "begin; delete from t18 where id = 4; insert into t18 (id) values (4); rollback;" --number-of-queries=100000 -uroot -p123456 &
# mysqlslap --create-schema dldb -q "begin; delete from t18 where id = 4; rollback;" --number-of-queries=100000 -uroot -p123456 &
測試腳本通過 mysqlslap 工具并發(fā)執(zhí)行兩個事務,每個事務執(zhí)行 N 次(N = 100000),如果兩個事務會出現(xiàn)死鎖,則我們可以通過死鎖日志看到。
檢查是否出現(xiàn)死鎖日志
# tail -f /var/log/mysql/error.log
TODO
重現(xiàn)案例 1
重現(xiàn)案例 2
重現(xiàn)案例 3
重現(xiàn)案例 4
重現(xiàn)案例 5
重現(xiàn)案例 6
重現(xiàn)案例 7
重現(xiàn)案例 8
重現(xiàn)案例 9
重現(xiàn)案例 10
重現(xiàn)案例 11
重現(xiàn)案例 12
重現(xiàn)案例 13
重現(xiàn)案例 14
重現(xiàn)案例 15
重現(xiàn)案例 16
重現(xiàn)案例 17
重現(xiàn)案例 18
重現(xiàn)案例 19
重現(xiàn)案例 20
由于相同的測試腳本在并發(fā)的時候可能產(chǎn)生不同的死鎖,后續(xù)可以寫個腳本來解析 error.log 看看發(fā)生了多少次死鎖
使用 mysqlslap 測試不太方面,后續(xù)可以寫個腳本來模擬并發(fā)事務
總結(jié)
以上是生活随笔為你收集整理的mysql死锁的例子_GitHub - yxp199249/mysql-deadlocks: 收集一些常见的 MySQL 死锁案例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NB物联网之天翼物联(3)——初窥编解码
- 下一篇: Oracle数据库语句大全