1. session1 执行 delete  会在唯一索引 c2 的 c2 = 15 这一记录上加 X lock(也就是在MySQL 内部观测到的:X Lock but not gap);

2. session2 和 session3 在执行 insert 的时候,由于唯一约束检测发生唯一冲突,会加 S Next-Key Lock,即对 (1,15] 这个区间加锁包括间隙,并且被 seesion1 的 X Lock 阻塞,进入等待;

3. session1 在执行 commit 后,会释放 X Lock,session2 和 session3 都获得 S Next-Key Lock;

4. session2 和 session3 继续执行插入操作,这个时候 INSERT INTENTION LOCK(插入意向锁)出现了,并且由于插入意向锁会被 gap 锁阻塞,所以 session2 和 session3 互相等待,造成死锁。

死锁日志如下:

INSERT INTENTION LOCK

在之前的死锁分析第四点,如果不分析插入意向锁,也是会造成死锁的,因为插入最终还是要对记录加 X Lock 的,session2 和 session3 还是会互相阻塞互相等待。

但是插入意向锁是客观存在的,我们可以在官方手册中查到,不可忽略:

Prior to inserting the row, a type of gap lock called an insert intention gap lock is set. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap.

插入意向锁其实是一种特殊的 gap lock,但是它不会阻塞其他锁。假设存在值为 4 和 7 的索引记录,尝试插入值 5 和 6 的两个事务在获取插入行上的排它锁之前使用插入意向锁锁定间隙,即在(4,7)上加 gap lock,但是这两个事务不会互相冲突等待。

当插入一条记录时,会去检查当前插入位置的下一条记录上是否存在锁对象,如果下一条记录上存在锁对象,就需要判断该锁对象是否锁住了 gap。如果 gap 被锁住了,则插入意向锁与之冲突,进入等待状态(插入意向锁之间并不互斥)。总结一下这把锁的属性:

1. 它不会阻塞其他任何锁;

2. 它本身仅会被 gap lock 阻塞。

在学习 MySQL 过程中,一般只有在它被阻塞的时候才能观察到,所以这也是它常常被忽略的原因吧...

GAP LOCK

在此例中,另外一个重要的点就是 gap lock,通常情况下我们说到 gap lock 都只会联想到 REPEATABLE-READ 隔离级别利用其解决幻读。但实际上在 READ-COMMITTED 隔离级别,也会存在 gap lock ,只发生在:唯一约束检查到有唯一冲突的时候,会加 S Next-key Lock,即对记录以及与和上一条记录之间的间隙加共享锁。

通过下面这个例子就能验证:

这里 session1 插入数据遇到唯一冲突,虽然报错,但是对 (15,20] 加的 S Next-Key Lock 并不会马上释放,所以 session2 被阻塞。另外一种情况就是本文开始的例子,当 session2 插入遇到唯一冲突但是因为被 X Lock 阻塞,并不会立刻报错 “Duplicate key”,但是依然要等待获取 S Next-Key Lock 。

有个困惑很久的疑问:出现唯一冲突需要加 S Next-Key Lock 是事实,但是加锁的意义是什么?还是说是通过 S Next-Key Lock 来实现的唯一约束检查,但是这样意味着在插入没有遇到唯一冲突的时候,这个锁会立刻释放,这不符合二阶段锁原则。这点希望能与大家一起讨论得到好的解释。

如果是在 REPEATABLE-READ,除以上所说的唯一约束冲突外,gap lock 的存在是这样的:

普通索引(非唯一索引)的S/X Lock,都带 gap 属性,会锁住记录以及前1条记录到后1条记录的左闭右开区间,比如有[4,6,8]记录,delete 6,则会锁住[4,8)整个区间。

对于 gap lock,相信 DBA 们的心情是一样一样的,所以我的建议是:

1. 在绝大部分的业务场景下,都可以把 MySQL 的隔离界别设置为 READ-COMMITTED;

2. 在业务方便控制字段值唯一的情况下,尽量减少表中唯一索引的数量。

锁冲突矩阵

前面我们说的 GAP LOCK 其实是锁的属性,另外我们知道 InnoDB 常规锁模式有:S 和 X,即共享锁和排他锁。锁模式和锁属性是可以随意组合的,组合之后的冲突矩阵如下,这对我们分析死锁很有帮助。

mysql死锁如何释放_mysql 死锁:如何解决mysql死锁相关推荐

  1. mysql 57授权失败_MYSQL教程完美解决mysql客户端授权后连接失败的问题

    <MYSQL教程完美解决mysql客户端授权后连接失败的问题>要点: 本文介绍了MYSQL教程完美解决mysql客户端授权后连接失败的问题,希望对您有用.如果有疑问,可以联系我们. MYS ...

  2. 【Mysql】太可怕了,跟踪及解决Mysql死锁原来可以这么简单

    文章目录 1.存储引擎 2.锁粒度 3.不同粒度锁的比较 4.行锁 5.表锁 6.事务 事务的ACID 事务的隔离级别 事务并发存在问题 使用四种隔离级别来解决事务并发 设置Mysql数据的隔离级别 ...

  3. mysql数据库连接数释放_MySQL数据库连接数问题及处理

    一.MySQL连接数超标原因分析 MySQL的默认最大连接数为100(N),实际给普通用户使用只有N-1个,保留一个连接是留给超级管理员使用的,防止连接占满了不会把管理员也踢出来.很多网站在运行的时候 ...

  4. mysql -u 报错_MySQL报错解决!

    大家好:我是小狼,最近工作一直瞎忙,没时间写东西,终于有点时间了,现在我正在搭建extmail服务器,文档是参考这里:http://www.extmail.org/forum/thread-7002- ...

  5. mysql binary 查询_MYSQL的binary解决mysql数据大小写敏感问题 《转载》

    BINARY不是函数,是类型转换运算符,它用来强制它后面的字符串为一个二进制字符串,可以理解为在字符串比较的时候区分大小写 如下: mysql> select binary 'ABCD'='ab ...

  6. mysql一直拒绝登录_mysql 拒绝登录解决

    一大早打开Navicat Lite for MySQL客户端,提示1045 access denied for user 'root'@'localhost' using password yes,太 ...

  7. mysql 备注 部分乱码_mysql备注乱码解决之道

    首先还是要修改一下my.ini里面的client和server的编码,要改两处..代码如下: [client] port=3306 [mysql] default-character-set=utf8 ...

  8. mysql导入数据表越来越慢,快速解决mysql导数据时,格式不对、导入慢、丢数据的问题...

    快速解决mysql导数据时,格式不对.导入慢.丢数据的问题 如果希望一劳永逸的解决慢的问题,不妨把你的mysql升级到mysql8.0吧,mysql8.0默认的字符集已经从latin1改为utf8mb ...

  9. mysql数据库localhost已断开_完美解决MySQL通过localhost无法连接数据库的问题

    问题:一台服务器的PHP程序通过localhost地址无法连接数据库,但是如果设置为127.0.0.1则可以正常连接,连接其他数据库服务器也正常.MySQL的权限设置正确,且通过mysql命令行客户端 ...

  10. linux下安装Mysql(干货!!!)解决mysql 1130问题,远程登录问题

    转载自:http://www.cnblogs.com/xxoome/p/5864912.html linux版本:CentOS7 64位     1.下载安装包"mysql-5.6.33-l ...

最新文章

  1. 希尔伯特著名的第六问题 – 原来麦克斯韦早就有解?
  2. CNN模型复杂度(FLOPs、MAC)、参数量与运行速度
  3. finalshell连接超时怎么解决_电脑无线网络连接不上怎么回事 电脑连不上无线网络的解决方法...
  4. LeetCode:104_Maximum Depth of Binary Tree | 二叉树的最大深度 | Easy
  5. 固态+机械(uefi类型的bios),用easybcd安装win10+ubuntu16.04双系统
  6. vue对象拼接_vue 俩个数组对象合并成一个
  7. 雷军1994年写的老代码曝光,被称像诗一样优雅
  8. Java 在指定目录下查找文件
  9. 互联网晚报 | 3月22日 星期二 |​ ​工作人员标注mu5735残骸并展开调查;万门大学疑似解散VIP群跑路...
  10. Modern UI for WPF 开源项目(5):定义logo
  11. Hammer.js分析(三)——input.js
  12. 结构体与共用体05 - 零基础入门学习C语言57
  13. 51nod1113-----矩阵快速幂
  14. mysql --force 无效_【技能库】--mysql 索引失效 force index也失效-- 原因解决方案(256)...
  15. linux多进程子进程继承,Linux-fork调用后,父进程的线程是否会被子进程继承?
  16. mmap库:Python内存映射文件操作
  17. 火狐扩展教程_4个值得一试的Firefox扩展
  18. 模拟CMOS集成电路设计基础 第一章 第二章开头
  19. datagrid的deleteRow使用
  20. 作业1丨创建问答式简历程序

热门文章

  1. php函数substr、mb_substr、mb_strcut截取中文比较
  2. Mysql中提取某列信息的一些函数方法
  3. java 不换行输出_java的输入输出
  4. docker批量重启容器服务
  5. 如何学会读论文?三轮阅读法,滑铁卢大学S. Keshav
  6. 程序员拿到结婚证以后说的第一句话
  7. 编程人生,软件开发教给我的7大生活哲理
  8. 前端学习——Css-基础
  9. 小米手机使用应用沙盒动态修改电池信息
  10. centos7用Java搭建网站,CentOS7 使用java建站程序publiccms建站教程之--Redhat系环境搭建篇...