1、MySQL锁机制
1.1、MySQL为什么要有锁机制的存在?
MySQL 中锁机制的存在是为了保证数据库操作的并发安全性和数据的一致性,特别是在多个用户同时访问和操作数据库时,锁能够防止数据不一致、丢失、或数据冲突问题的发生。
1.2、MySQL锁的定义
MySQL 中的锁是指控制多个事务并发访问同一数据资源的一种机制,目的是保证数据的一致性、完整性以及并发访问时的安全性。锁机制通过限制其他事务对某些数据的读写权限,防止在并发操作中出现数据冲突、数据丢失和不一致的情况。
从不同维度划分,锁的叫法不同,使用场景不同。
1.3、从性能上分
乐观锁: 用版本对比或CAS机制,适合读多的场景。如果在写多的场景使用乐观锁,会因比对次数过多,影响性能。
悲观锁: 适合写多的场景,读锁和写锁都属于悲观锁。
1.4、从对数据操作粒度分
表锁: 每次操作锁住整张表,开销小,加锁快;不会出现死锁。锁定粒度大,发生锁冲突的概率最高,并发度最低。使用场景:一般在整表数据迁移时。
页锁: 只有BDB存储引擎支持,锁定粒度介于表锁和行锁之间,并发度一般。会出现死锁。
行锁: 每次操作锁住一行数据,开销大,加锁慢,会出现死锁。锁定粒度最小,发生锁冲突的概率最低,并发度最高。RR级别会升级表锁,RC级别不会升级为表锁。
1.5、从对数据操作类型分
读锁(共享锁,S锁(Shared)): 针对同一份数据,多个读操作可以同时进行,不会互相影响。
写锁(排它锁,X锁(eXclusive)): 当前写操作没有完成前,它会阻断其他写锁和读锁。数据修改操作都会加写锁,查询也可以通过for update加写锁。
意向锁(Intention Lock,I锁): 针对表锁,主要是为了提高加表锁的效率,是mysql数据库自己加的。可以再细分为两类:
意向共享锁,IS锁: 对整个表加共享锁之前,需要先获取到意向共享锁。
意向排他锁,IX锁: 对整个表加排他锁之前,需要先获取到意向排他锁。
表级锁类型兼容性总结如下表:
X | IX | S | IS | |
---|---|---|---|---|
X | 冲突 | 冲突 | 冲突 | 冲突 |
IX | 冲突 | 兼容 | 冲突 | 兼容 |
S | 冲突 | 冲突 | 兼容 | 兼容 |
IS | 冲突 | 兼容 | 兼容 | 兼容 |
1.6、从锁定机制或策略分
间隙锁(Gap Lock): 锁定两个索引记录之间的“间隙”,不包括索引记录本身,锁定的范围是在两个索引键值之间的区域。目的是防止幻读,通过锁定间隙,阻止其他事务在该间隙中插入新的记录,避免当前事务在后续查询中出现幻影行(即幻读现象)。
使用场景是范围查询(Range Search),使用非唯一索引时,会使用间隙锁。RR隔离级别时,当执行范围查询并需要锁定满足条件的记录范围,防止其他事务插入间隙中的新记录。
临键锁(Next-key Locks): 行锁 和 间隙锁 的组合,锁定一个索引记录以及其前面的间隙,锁定的范围包括锁定索引记录及其前面的间隙。目的是防止幻读和保证数据一致性,前者通过锁定索引记录及其前面的间隙,防止其他事务插入或修改锁定范围内的数据;后者防止其他事务修改或删除已锁定的记录。
使用场景是精确匹配查询,使用唯一索引时,会使用临键锁。RR隔离级别,对唯一索引进行等值查询并加锁时,使用临键锁。
2、锁优化小Tips
- 尽可能让所有数据检索都通过索引完成,避免无索引行锁升级为表锁。
- 合理设计索引,尽量缩小锁的范围。
- 尽可能减少检索条件范围,避免间隙锁。
- 尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量放在事务最后执行。
- 尽可能用低的事务隔离级别。
3、我的公众号
敬请关注我的公众号:大象只为你,持续更新技术知识…