All Projects → aneasystone → Mysql Deadlocks

aneasystone / Mysql Deadlocks

收集一些常见的 MySQL 死锁案例

Labels

Projects that are alternatives of or similar to Mysql Deadlocks

Meguca
anonymous realtime imageboard focused on high performance and transparent moderation
Stars: ✭ 286 (-63.19%)
Mutual labels:  plpgsql
Practical Sql
Code and Data for the book "Practical SQL" by Anthony DeBarros, published by No Starch Press (2018).
Stars: ✭ 392 (-49.55%)
Mutual labels:  plpgsql
Pgtap
PostgreSQL Unit Testing Suite
Stars: ✭ 631 (-18.79%)
Mutual labels:  plpgsql
Postgres Json Schema
JSON Schema validation for PostgreSQL
Stars: ✭ 319 (-58.94%)
Mutual labels:  plpgsql
100daysofiac
100 Days of IaC in Azure
Stars: ✭ 347 (-55.34%)
Mutual labels:  plpgsql
Vector Datasource
Tilezen vector tile service - OpenStreetMap data in several formats
Stars: ✭ 427 (-45.05%)
Mutual labels:  plpgsql
Groupdate.sql
The simplest way to group temporal data
Stars: ✭ 260 (-66.54%)
Mutual labels:  plpgsql
Demo
“Happy Lager” Craft CMS demo site.
Stars: ✭ 730 (-6.05%)
Mutual labels:  plpgsql
103976
103976个英语单词库(sql版,csv版,Excel版)包含英文单词,中文翻译,单词的词性及多种词义,执行SQL语句就可以生成表,支持SQL Server,MySQL等多种数据库
Stars: ✭ 361 (-53.54%)
Mutual labels:  plpgsql
Node Sqlite3
Asynchronous, non-blocking SQLite3 bindings for Node.js
Stars: ✭ 5,083 (+554.18%)
Mutual labels:  plpgsql
Cgasm
We're insanely passionate about command line asm documentation in the cloud, and we're crushing it!
Stars: ✭ 321 (-58.69%)
Mutual labels:  plpgsql
Hioshop Server
海风小店,开源商城,微信小程序商城服务器端
Stars: ✭ 331 (-57.4%)
Mutual labels:  plpgsql
Mixerp
Open Source ERP, HRM, MRP, MPS
Stars: ✭ 472 (-39.25%)
Mutual labels:  plpgsql
Pointcloud
A PostgreSQL extension for storing point cloud (LIDAR) data.
Stars: ✭ 289 (-62.81%)
Mutual labels:  plpgsql
Postgrest Starter Kit
Starter Kit and tooling for authoring REST API backends with PostgREST
Stars: ✭ 657 (-15.44%)
Mutual labels:  plpgsql
Sqlite Parser
JavaScript implentation of SQLite 3 query parser
Stars: ✭ 279 (-64.09%)
Mutual labels:  plpgsql
Pg Shortkey
YouTube-like Short IDs as Postgres Primary Keys
Stars: ✭ 402 (-48.26%)
Mutual labels:  plpgsql
Mysql Sys
The MySQL sys schema
Stars: ✭ 758 (-2.45%)
Mutual labels:  plpgsql
Blog
Everything about database,business.(Most for PostgreSQL).
Stars: ✭ 6,330 (+714.67%)
Mutual labels:  plpgsql
Audit Trigger
Simple, easily customised trigger-based auditing for PostgreSQL (Postgres). See also pgaudit.
Stars: ✭ 493 (-36.55%)
Mutual labels:  plpgsql

mysql-deadlocks

在工作过程中偶尔会遇到死锁问题,虽然这种问题遇到的概率不大,但每次遇到的时候要想彻底弄懂其原理并找到解决方案却并不容易。这个项目收集了一些常见的 MySQL 死锁案例,大多数案例都来源于网络,并对其进行分类汇总,试图通过死锁日志分析出每种死锁的原因,还原出死锁现场。

实际上,我们在定位死锁问题时,不仅应该对死锁日志进行分析,还应该结合具体的业务代码,或者根据 binlog,理出每个事务执行的 SQL 语句。

我将这些死锁按事务执行的语句和正在等待或已持有的锁进行分类汇总:

事务一语句 事务二语句 事务一等待锁 事务二等待锁 事务二持有锁 案例
insert insert lock_mode X insert intention lock_mode X insert intention lock_mode X 1
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 14
insert insert lock_mode X insert intention lock_mode X insert intention lock_mode S 2
insert insert lock mode S lock_mode X locks gap before rec insert intention lock_mode X locks rec but not gap 15
delete insert lock_mode X locks rec but not gap lock mode S lock_mode X locks rec but not gap 18
delete delete lock_mode X lock mode S lock_mode X locks rec but not gap 4
delete delete lock_mode X lock mode X lock_mode X locks rec but not gap 6
delete delete lock_mode X locks rec but not gap lock_mode X lock_mode X 3
delete delete lock_mode X locks rec but not gap lock mode X lock_mode X locks rec but not gap 7
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 8,9
delete insert lock_mode X lock_mode X locks gap before rec insert intention lock_mode X locks rec but not gap 5
delete insert lock_mode X lock_mode X locks gap before rec insert intention lock_mode S 10
delete insert lock_mode X lock_mode X locks gap before rec insert intention lock_mode X 12
delete insert lock_mode X lock mode S lock_mode X locks rec but not gap 13
update update lock_mode X locks rec but not gap lock mode S lock_mode X locks rec but not gap 11
update update lock_mode X lock_mode X locks gap before rec insert intention lock_mode X locks rec but not gap 16
update update lock_mode X locks gap before rec insert intention lock_mode X locks gap before rec insert intention lock_mode X 17
update delete lock_mode X locks rec but not gap lock_mode X lock mode S 19
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 20

表中的语句虽然大多数只列出了 delete 和 insert,但实际上绝大多数的 delete 语句和 update 或 select ... for update 加锁机制是一样的,所以为了避免重复,对于 update 语句就不在一起汇总了(当然也有例外,譬如使用 update 对索引进行更新时加锁机制和 delete 是有区别的,这种情况我会单独列出,如案例 11)。

对每一个死锁场景,我都会定义一个死锁名称(实际上就是事务等待和持有的锁),每一篇分析,我都分成了 死锁特征、死锁日志、表结构、重现步骤、分析和参考 这几个部分。

对于这种分类方法我感觉并不是很好,但也想不出什么其他更好的方案,如果你有更好的建议,欢迎讨论。另外,如果你有新的死锁案例,或者对某个死锁的解释有异议,欢迎给我提 Issue 或 PR。

死锁分析

之前写过关于死锁的一系列博客,供参考。

死锁重现

docker 目录下包含了各个死锁重现的测试脚本,测试步骤如下:

  1. 创建数据库和初始数据
# cd docker
# docker-compose up -d

确保机器上安装了 docker 和 docker-compose,上面的命令会启动一个 mysql:5.7 的容器,并创建一个名为 dldb 的数据库,初始密码为 123456,并通过 docker-entrypoint-initdb.d 初始化所有案例所需要的表和数据。

  1. 等待容器启动结束
# 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.
  1. 进入容器执行测试脚本

首先进入容器:

# 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),如果两个事务会出现死锁,则我们可以通过死锁日志看到。

  1. 检查是否出现死锁日志
# tail -f /var/log/mysql/error.log

TODO

  • [ ] 重现案例 1
  • [ ] 重现案例 2
  • [ ] 重现案例 3
  • [ ] 重现案例 4
  • [ ] 重现案例 5
  • [ ] 重现案例 6
  • [ ] 重现案例 7
  • [x] 重现案例 8
  • [ ] 重现案例 9
  • [ ] 重现案例 10
  • [ ] 重现案例 11
  • [ ] 重现案例 12
  • [ ] 重现案例 13
  • [ ] 重现案例 14
  • [ ] 重现案例 15
  • [x] 重现案例 16
  • [ ] 重现案例 17
  • [x] 重现案例 18
  • [ ] 重现案例 19
  • [ ] 重现案例 20
  • [ ] 由于相同的测试脚本在并发的时候可能产生不同的死锁,后续可以写个脚本来解析 error.log 看看发生了多少次死锁
  • [ ] 使用 mysqlslap 测试不太方面,后续可以写个脚本来模拟并发事务
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].