mysql-repeatableread 隔离级别下 deadlock分析
在repeatableread隔离级别下,其使用了相对轻量级的锁机制,采用的行锁(排他性,当存在一个事务获取到的当前行的所有权,其他事务如需要竞争相同行的所有权,需要阻塞等待锁释放(对于当前加锁应该是非公平锁竞争机制(ps 个人猜测未查找官方文档认证)))
两阶段锁协议
在执行数据写入或更新操作时,事务开启但并未立即执行加锁操作,innodb 会在定位到指定行数据时 才会执行行锁加锁操作,但锁的释放并非在执行结束后就立即释放,而是需要等待事务完成后才会释放锁
因此对于在并发事务情况, 对于其可能存在的锁冲突情况,尽量将 冲突加锁的操作延后,避免锁的时间过长;
在并发事务情况下,由于更新/写入操作 锁的排他性, 当存在锁时间过长则会导致死锁的发生, 对于死锁的处理策略 存在两种
- 设置默认锁等待时间,当等待超时后,被阻塞的事务自动回滚; 对于设置锁等待时间,其存在的缺点为如果设置时间过短,会存在误判的情况,但如果设置时间过长,则会导致业务系统整体响应时间变长(主要体现在出现事务回滚情况)
- 死锁主动检测,如果判断当前事务有可能和其他事务出现循环等待问题,如果判定认为存在,则回滚当前事务; 关于死锁主动检测其原理实际就是判断自身事务加入是否会导致其他事务出现deadLock的情况,时间复杂度为O(n),但其会随着事务的增加其整体的时间复杂度会变为 O(n^2),导致性能浪费
幻读
由于对于update操作中行锁只锁定了事务开启时扫描到的行,行锁并不能直接阻止新增操作,因此 引入 了 间隙锁(gap lock)
gap 的定义: https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_gap
gap_lock 的定义 : https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_gap_lock
next-key lock 的定义 : https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_next_key_lock
https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-gap-locks
间隙锁的相关概念
间隙锁是针对索引(主键索引或二级索引)数据之间的间隙进行加锁的操作,gap lock 只针对 在 repeatable read 隔离级别下 update 或 select for update 操作;
读锁和读锁之间是不会互斥,读锁和写锁之间会互斥,写锁之间互斥
而对于间隙锁的规则, 间隙锁会对将要对间隙执行插入操作的互斥
间隙锁的范围区间为 开区间;
间隙锁的目的是为了解决 phantom 问题,由于间隙锁和插入操作的写锁互斥, 因此避免了幻读的发生,但也导致了额外的问题点
由于间隙锁的范围不太可控,增加了间隙锁和插入时要求的行锁的冲突几率,从而导致 死锁的发生;
对于只有二级索引才会引发间隙锁或死锁的误解在于
在使用二级索引时,因为其扫描行数的增加导致间隙锁范围的增加,从而导致锁冲突的概率增加; 即使是使用主键索引也会存在间隙锁,但使用主键索引的好处在于其查找效率高效,降低了长事务的发生概率,从而降低了死锁发生的概率

浙公网安备 33010602011771号