前言
分享一下我在我学习mysql的时候跟着我强哥学习的知识点~
MySQL 锁机制是数据库管理系统中用于协调多个用户同时访问和修改数据的方式,以确保数据的一致性和完整性。MySQL 锁机制主要包括以下三种类型:记录锁、间隙锁和临键锁。
MySQL有三种类型的行锁:
记录锁(Record Locks):
即对某条记录加锁。
id=1的用户加锁 update user set age=age 1 where id=1;
间隙锁(Gap Locks):
即对某个范围加锁,但是不包含范围的临界数据。
id大于1并且小于10的用户加锁 update user set age=age 1 where id>1 and id<10; SQL上面SQL的加锁范围是(1,10)。
临键锁(Next-Key Locks):
由记录锁和间隙锁组成,既包含记录本身又包含范围,左开右闭区间。
对id大于1并且小于等于10的用户加锁 update user set age=age 1 where id>1 and id<=10;
假如表中只有这样两条数据的话:
id | name | age |
---|---|---|
1 | 张三 | 1 |
10 | 李四 | 10 |
针对age索引,很产生这样三个索引范围:
(-∞,1),(1,10),(10, ∞)
刚才的这条SQL:
update user set name='杨不易呀' where age=5;
由于表中不存在age=5的记录,并且age=5刚好落在 (1,10) 的区间范围内,所以会对 (1,10) 的范围加锁。
当我们执行update语句的时候,age=2和age=8的数据范围都被加锁了。
问: 如果已经存在age=5的数据,刚才的那条update语句会对哪些数据加锁?
我: 假如表中数据是这样的。
id | name | age |
---|---|---|
1 | 张三666 | 1 |
5 | 杨不易呀架构 | 5 |
10 | 李四351 | 10 |
针对age索引,很产生这样四个索引范围:
(-∞,1),(1,5),(5,10),(10, ∞)
刚才的这条SQL:
update user set name='杨不易呀' where age=5;
age=5的数据落在 (1,5) 的区间范围内,所以会对 (1,5) 的范围加锁。
你以为这就完了吗?MySQL锁为了保证数据的安全性,还会向右遍历到不满足条件为止,还会再加一个间隙锁,也就是 (5,10) 的范围。
所以,这条SQL的加锁返回是 (1,5) 和 (5,10) 。
跟刚才age=5不存在的加锁范围 (1,10) 是一样的。不信可以再用刚才的测试用例跑一遍。
问: 如果我把SQL中where条件换成主键ID,加锁范围是什么样的?
update user set name='杨不易呀' where id=5;
我: 由于锁是加在索引上面的。
如果不存在id=5的数据,加锁范围跟上条SQL是一样的, (1,10) 。
如果存在id=5的数据,MySQL的 Next-Key Locks 会退化成 Record Locks ,也就是只在id=5的这一行记录上加锁。
总结:
- MySQL锁是加在索引记录上面的。
- 如果是非唯一性索引,不论表中是否存在该记录,除了会对该记录所在范围加锁,还会向右遍历到不满足条件的范围进行加锁。
- 如果是唯一索引,如果表中存在该记录,只对该行记录加锁。如果表中不存在该记录,除了会对该记录所在范围加锁,还会向右遍历到不满足条件的范围进行加锁。
最后
本期结束咱们下次再见