概述

之前接触到的数据库死锁,很多都是批量更新时加锁顺序不一致而导致的死锁,但是上周却遇到了一个很难理解的死锁。借着这个机会又重新学习了一下mysql的死锁知识以及常见的死锁场景。今天不介绍死锁的基本知识和mysql的加锁原理,主要是用实验来帮助大家理解下死锁。


环境

环境:采用的是5.7版本的mysql数据库,事务隔离级别是默认的RR(Repeatable-Read),采用innodb引擎。


环境演示

CREATE TABLE `test` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `a` int(11) unsigned DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `a` (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8;

表的结构很简单,一个主键id,另一个唯一索引a。表里的数据如下:

insert into test values(1,1);
insert into test values(2,2);
insert into test values(4,4);
commit;
select * from test;

出现死锁的操作如下:

然后通过SHOW ENGINE INNODB STATUS \G;来查看死锁日志:

分析

遇到死锁,第一步就是阅读死锁日志。死锁日志通常分为两部分,上半部分说明了事务1在等待什么锁:

---TRANSACTION 35493153, ACTIVE 53 sec
1 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 372, OS thread handle 139691463722752, query id 524209 61.140.171.46 root cleaning up
---TRANSACTION 35493047, ACTIVE 82 sec
3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 371, OS thread handle 139691465004800, query id 524167 61.140.171.46 root cleaning up

从日志里我们可以看到事务1(MySQL thread id 372)和事务2(MySQL thread id 371)产生了死锁。

查看thread

查看死锁

 select trx_id,trx_state,trx_mysql_thread_id,trx_isolation_level from information_schema.INNODB_TRX;

该锁是通过事务2在步骤2执行的delete语句申请的。由于是RR隔离模式下的基于唯一索引的等值查询(Where a = 2),所以会申请一个记录锁,而非next-key锁。

而且事务2正在申请S锁,也就是共享锁。该锁是insert into test (id,a) values (10,2)语句申请的。insert语句在普通情况下是会申请排他锁,也就是X锁,但是这里出现了S锁。这是因为a字段是一个唯一索引,所以insert语句会在插入前进行一次duplicate key的检查,为了使这次检查成功,需要申请S锁防止其他事务对a字段进行修改。

那么为什么该S锁会失败呢?这是对同一个字段的锁的申请是需要排队的。S锁前面还有一个未申请成功的X锁,所以S锁必须等待,所以形成了循环等待,死锁出现了。


死锁形成流程图

这里通过表格的形式阐述死锁形成的流程:


后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下!

思考

1,查看死锁日志

SHOW ENGINE INNODB STATUS

记一次mysql数据库死锁实验相关推荐

  1. go mysql slave_【Golang+mysql】记一次mysql数据库迁移(一)

    # [记一次mysql数据库迁移(一)](https://github.com/stayfoo/stayfoo-hub/blob/master/docs/mysql/blog/%E8%AE%B0%E4 ...

  2. mysql勒索_记一次mysql数据库被勒索(下)

    背景: nextcloud的mysql数据库被黑,删库勒索.参考:记一次mysql数据库被勒索(上) mysql数据库恢复成功,nextcloud还是无法连接.参考:记一次mysql数据库被勒索(中) ...

  3. 记一次mysql数据库转储sql文件到另外一台电脑运行失败的解决办法

    记一次mysql数据库转储sql文件到另外一台电脑运行失败的解决办法 将转储的sql文件中创建触发器相关的语句剪切复制到另外的一份文本,保存重新运行sql文件,成功后在把之前剪切的语句复制过来在运行一 ...

  4. mysql数据库死锁几种情况

    mysql数据库死锁的产生原因及解决办法 数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会 ...

  5. 记一次 MySQL 数据库遭比特币病毒处理方法

    记一次 MySQL 数据库遭比特币病毒处理方法 经过 某日上午,发现公司的某个项目的测试服务器上的项目数据库突然消失,当时并没有找到消失,随后开启了MySQL-binlog日志记录数据库的所有操作. ...

  6. mysql数据库死锁的产生原因及解决办法

    该文章为转载,如有侵权请及时联系 这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下 数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据 ...

  7. mysql数据库死锁检测_数据库死锁检测和解决方式

    做性能测试或者线上环境并发量比较大的时候经常出现数据库死锁的情况,下面介绍几种数据库死锁的检测方式和解决方式.都是采用sql命令实现的.如果不用命令行也可以通过查看数据库服务器的日志信息进行死锁检测, ...

  8. mysql数据库死锁重启后无效_mysql数据库死锁解决办法

    Date: 2016.04.30 数据库死锁的问题,还是挺让人讨厌的. 这里提供两个解决数据库死锁的方法: 1)重启数据库(谁用谁知道) 2)杀掉抢资源的进程: 先查哪些进程在抢资源:SELECT * ...

  9. mysql 数据库 死锁_Mysql数据库出现死锁的情况(一)

    在临近上线之前,我们系统做了一次压力测试,发现有一个接口在高并发情况下会出现一个死锁的情况..首先申明-不是我写的,我只是帮忙排查下. 随着对Mysql锁的深入了解,于是就准备写几篇文章来记录下Mys ...

最新文章

  1. Python 什么时候会被取代?
  2. CVPR 2020论文开源项目一页看尽,附代码论文
  3. 【NLP】探索NLP模型可解释性的7种姿势
  4. 自适应/响应式网页设计
  5. 请举例说明如何在Spring 中注入一个Java 集合?
  6. 前端学习(2015)vue之电商管理系统电商系统之实现图片的预览效果
  7. Educational Codeforces Round 103 (Rated for Div. 2)A~E解题报告
  8. mysql面试吗hi提_面试必备的10道MySQL题
  9. win10的一些命令,记一记
  10. 爬虫 --- 08. 全站爬取(CrawlSpider), 分布式, 增量式爬虫
  11. 谷歌学术搜索 2019
  12. geany的安装与使用
  13. 服务器系统和操作系统的区别
  14. SolidWorks弹簧扣与弹簧扣凹槽使用技巧
  15. 企业级计算机储存容量,家用NAS与企业级NAS功能大比拼
  16. 亚马逊美国账号怎么注册?有什么条件?
  17. 微服务(四) 【手摸手带你搭建Spring Cloud】 Hystrix 熔断器 什么是熔断器? 什么是Hystrix?为什么要熔断器 Hystrix用来做什么? 作用是什么?
  18. 08.第九章.人力资源管理
  19. GEE:北运河流域土地利用的重分类
  20. 软件测试效果怎么提高?

热门文章

  1. ubuntu解压缩分卷压缩文件(同时解压多个文件)
  2. Peer Effects Report(博弈论+机制设计)
  3. 人工智能创业的“风口”和“泡沫”
  4. 基于C++的吃豆人小游戏的设计与实现
  5. web html做菜单,Web元素设计之导航菜单
  6. c#模拟看板控件_ComponentOne for Winform
  7. 中国区块链从业者至少要读三遍的白皮书
  8. Gym - 101194G Pandaria (并查集+倍增+线段树合并)
  9. 操作mysql的dbms_数据库学习之(5)详解DBMS
  10. 小程序数据回传,刷新父界面数据