场景:如下代码,获取数据库连接,删除权限的时候,会造成数据库死锁.
代码
日志:
数据库:
SHOW OPEN TABLES where In_use > 0;
问题分析:测试环境Centos7操作系统,Mysql5.7.40版本程序运行正常,开发环境Windows操作系统,Mysql5.7.40一旦执行这段代码就会造成数据库死锁,对比两个环境数据库配置文件,发现差别很大,经过尝试,发现是数据库事务隔离级别配置造成的,开发环境my.ini配置文件中没有事务隔离级别相关的配置。
事务隔离级别查询:
SHOW VARIABLES LIKE 'tx_isolation';
添加事务隔离级别配置:
transaction_isolation=READ-COMMITTED
查询事务隔离级别:
修改Mysql事务隔离级别之后,SQL执行正常。
经过分析(baidu.com),是由于间隙锁(Gap Lock)造成的。
MySQL InnoDB支持三种行锁定方式:
- 行锁(Record Lock):锁直接加在索引记录上面。
- 间隙锁(Gap Lock):锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间。
- Next-Key Lock:行锁与间隙锁组合起来用就叫做Next-Key Lock。
间隙锁概念
- 当我们用范围条件(between)而不是相等条件(=)检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;
- 对于键值在条件范围内但不存在的记录,叫做 “间隙(GAP)”,InnoDB也会对这个"间隙"加锁,这种锁机制就是所谓的间隙锁(NEXT-KEY)锁。
间隙锁作用
- 防止幻读
- 防止数据误删/误改
间隙锁隐患
- 事务会锁住了需要插入数据的区域,一直在进行数据处理,导致插入数据一直在等待,对插入的性能就有很大影响了,必须等到事务结束才能进行插入,性能会降低。