mysql死锁的例子_GitHub - yxp199249/mysql-deadlocks: 收集一些常见的 MySQL 死锁案例
mysql-deadlocks
在工作過程中偶爾會遇到死鎖問題,雖然這種問題遇到的概率不大,但每次遇到的時候要想徹底弄懂其原理并找到解決方案卻并不容易。這個項目收集了一些常見的 MySQL 死鎖案例,大多數案例都來源于網絡,并對其進行分類匯總,試圖通過死鎖日志分析出每種死鎖的原因,還原出死鎖現場。
實際上,我們在定位死鎖問題時,不僅應該對死鎖日志進行分析,還應該結合具體的業務代碼,或者根據 binlog,理出每個事務執行的 SQL 語句。
我將這些死鎖按事務執行的語句和正在等待或已持有的鎖進行分類匯總:
事務一語句
事務二語句
事務一等待鎖
事務二等待鎖
事務二持有鎖
案例
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
表中的語句雖然大多數只列出了 delete 和 insert,但實際上絕大多數的 delete 語句和 update 或 select ... for update 加鎖機制是一樣的,所以為了避免重復,對于 update 語句就不在一起匯總了(當然也有例外,譬如使用 update 對索引進行更新時加鎖機制和 delete 是有區別的,這種情況我會單獨列出,如案例 11)。
對每一個死鎖場景,我都會定義一個死鎖名稱(實際上就是事務等待和持有的鎖),每一篇分析,我都分成了 死鎖特征、死鎖日志、表結構、重現步驟、分析和參考 這幾個部分。
對于這種分類方法我感覺并不是很好,但也想不出什么其他更好的方案,如果你有更好的建議,歡迎討論。另外,如果你有新的死鎖案例,或者對某個死鎖的解釋有異議,歡迎給我提 Issue 或 PR。
死鎖分析
之前寫過關于死鎖的一系列博客,供參考。
死鎖重現
docker 目錄下包含了各個死鎖重現的測試腳本,測試步驟如下:
創建數據庫和初始數據
# cd docker
# docker-compose up -d
確保機器上安裝了 docker 和 docker-compose,上面的命令會啟動一個 mysql:5.7 的容器,并創建一個名為 dldb 的數據庫,初始密碼為 123456,并通過 docker-entrypoint-initdb.d 初始化所有案例所需要的表和數據。
等待容器啟動結束
# docker logs -f dldb
使用 dockere logs 查看容器啟動日志,如果出現數據初始化完成的提示,如下所示,則進入下一步。
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.
進入容器執行測試腳本
首先進入容器:
# docker exec -it dldb bash
然后執行測試腳本,測試腳本在每一個案例對應的 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 工具并發執行兩個事務,每個事務執行 N 次(N = 100000),如果兩個事務會出現死鎖,則我們可以通過死鎖日志看到。
檢查是否出現死鎖日志
# tail -f /var/log/mysql/error.log
TODO
重現案例 1
重現案例 2
重現案例 3
重現案例 4
重現案例 5
重現案例 6
重現案例 7
重現案例 8
重現案例 9
重現案例 10
重現案例 11
重現案例 12
重現案例 13
重現案例 14
重現案例 15
重現案例 16
重現案例 17
重現案例 18
重現案例 19
重現案例 20
由于相同的測試腳本在并發的時候可能產生不同的死鎖,后續可以寫個腳本來解析 error.log 看看發生了多少次死鎖
使用 mysqlslap 測試不太方面,后續可以寫個腳本來模擬并發事務
總結
以上是生活随笔為你收集整理的mysql死锁的例子_GitHub - yxp199249/mysql-deadlocks: 收集一些常见的 MySQL 死锁案例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NB物联网之天翼物联(3)——初窥编解码
- 下一篇: NR PUCCH(一) PUCCH fo