锁
根据加锁的范围,MySQL里面的锁大致可以分为全局锁,表级锁和行级锁。
全局锁
- MySql提供了一个加全局锁的方法,Flush tables with read lock(FTWRL)
- 适用场景:全库逻辑备份
- 阻塞: 数据更新语句,数据定义语句,更新类事务提交语句
表级锁
- MySql中表级锁有两种:表锁 和 元数据锁
表锁
- 表锁语法是: lock tables … read/write
- 对于InnoDB这种支持行锁的引擎,一般不使用lock tables方式控制并发
元数据锁(matedata lock,MDL)
- MDL不需要显示使用,在访问一个表的时候会被自动加上。
- 作用:保证读写的正确性。
- 增删改查操作自动加MDL读锁,修改表结构的时候加MDL写锁
幻读
- 问题: 即使把所有的记录都加上锁,也还是阻止不了新插入的记录。
如何解决幻读问题
- 产生幻读的原因是:行锁只能锁住行,新插入记录这个动作,要更新的是记录之间的间隙。
- 解决办法: InnoDB引入了新的锁,间隙锁(Gap Lock)
- 与间隙锁冲突的操作:往这个间隙中插入一条记录
- 间隙锁和行锁合称:next-key lock
加锁总结
原则1:加锁的基本单位是next-key lock,是前开后闭区间。
原则2:查找过程中访问到的对象才会加锁。
优化1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。
优化2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock退化为间隙锁。
Bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。
锁是加在索引上的
用lock in share mode来给行加读锁避免数据被更新的话,必须要绕过覆盖索引优化,查询字段中加入索引中不存在的字段。
分析加锁规则的时候可以用next-key lock来进行分析,但是具体执行的时候,是要分成间隙锁和行锁两阶段来执行的。
- 源:<极客时间> MySQL实战45讲教程