当然,其实如果我们执行的查询刚好是id>=2且id<=5,那么就算只锁住了(1,5],同样能避免幻读问题,只是我们要考虑到查询范围的最大值没有命中记录的情况,而锁住了下一个区间,可以确保不论是哪种范围查询,都可以避免幻读的产生 。
在我们使用锁的时候,有一个问题是需要注意和避免的,我们知道,排它锁有互斥的特性 。一个事务持有锁的时候,会阻止其他的事务获取锁,这个时候会造成阻塞等待,那么假如事务一直等待下去,就会一直占用CPU资源,所以,锁等待会有一个超时时间,在InnoDB引擎中,可以通过参数:innodb_lock_wait_timeout查询:
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';
默认超时时间是50s,超时后会自动释放锁回滚事务 。但是我们想一下,假如事务A在等待事务B释放锁,而事务B又在等待事务A释放锁,这时候就会产生一个等待环路了,而这种情况是无论等待多久都不可能会获取锁成功的,所以是没有必要去等50s的,这种形成等待环路的现象又叫做死锁 。
死锁(Dead Lock)什么是死锁死锁是指的两个或者两个以上的事务在执行过程中,因为争夺锁资源而造成的一种互相等待的现象 。
文章插图
文章插图
我们可以看到,发生死锁之后就会立刻回滚,而不会漫无目的的去等待50s之后超时再回滚事务,那么MySQL是如何知道产生了死锁的,是如何检测死锁的发生呢?
死锁的检测目前数据库大部分采用wait-for graph(等待图)的方式来进行死锁检测,InnoDB引擎也是采用这种方式来检测死锁 。数据库中会记录两种信息:
- 锁的信息链表
- 事务的等待链表
wait-for graph 算法会根据这两个信息构建一张图,当图中存在回路,则证明存在死锁:如下图中,t1和t2之间存在回路,这就证明t1和t2事务之间存在死锁
文章插图
死锁的避免
- 尽量将长事务拆分成多个小事务
- 查询时避免没有where条件语句查询,并尽可能使用索引查询
- 可以的话尽量使用等值查询
INNODB_TRX记录了当前在InnoDB中执行的每个事务的信息,包括事务是否在等待锁、事务何时启动以及事务正在执行的SQL语句(如果有的话) 。
文章插图
INNODB_LOCKS记录了事务请求锁但未获得的每个锁的信息和一个事务持有锁但正在阻塞另一个事务的每个锁的信息 。
文章插图
INNODB_LOCK_WAITS记录了锁等待的信息 。每个被阻塞的InnoDB事务包含一个或多个行,表示它所请求的锁以及正在阻塞该请求的任何锁 。
文章插图
作者:双子孤狼
原文链接:https://blog.csdn.net/zwx900102/article/details/106544634
【深入分析解读MySQL锁,解决幻读问题】
推荐阅读
- 怎么判断你的MySQL到底是读多还是写多
- 故障分析 | MySQL 无法启动,提示 missing……
- MySQL 网络延时参数设置建议
- 解读中西方茶文化,2013贵州茶业经济发展报告出版
- 解读中国茶禅味,茶禅味
- MySQL服务端读取客户端文件漏洞的复现
- UUID 及其在 MySQL 中的使用
- 解读壹方天第楼盘信息
- SQL、MySQL的区别是什么?这是我看过最好的回答
- Mysql ProxyAtlas生产环境使用心得