author:魏静崎
2025年8月9日
MySQL-锁 学习
MVCC-多版本并发控制
因为没有用锁,因此是乐观锁的思想
隐藏列
该数据当前值对应的事务id和老版本数据的指针,以及当没有主键id时维护一个raw_id。
所有的历史数据存储在undolog
ReadView
如果是读已提交的隔离级别,每次查询都会创建一个readview。
readview存储了当前事务id,未提交事务ids(包含当前事务id),和未开始事务id
因为是读已提交,因此当前事务能读取到的就是undolog中最新的但是id小于未提交事务ids的已提交的数据
如果是可重复读的隔离级别,一个事务中同样的查询只会创建一个readview,保证独到的数据相同
锁
当前读和快照读
快照读
和MVCC相关,无任何锁的东西,一般的select就是快照读
当前读
共享读锁性质:
select … from … lock i share mode
独占写锁性质:
select … from … for update
insert …
update …
delete …
读锁和写锁的兼容性
读锁允许别的线程来读,写锁不允许其他线程读写
全局锁
锁定数据库中的所有表,一般用于数据备份
表级锁
表锁
锁住整张表,粒度较大
lock tables table_name read/write
元数据锁
防止DML和DDL冲突,隐式加的锁,无需显式使用
意向锁
避免加锁时一行一行去查看行锁的加锁情况,解决上述低效而引入的,隐式加的锁
比如当使用update自动加上了行锁,同时也会为整张表加上表锁,由此就不会被后来的表锁加锁。
同时意向锁和行锁性质相同,同为共享锁或同为排他锁
行级锁
行锁
对单个记录加锁,根据锁的兼容性判断是否能加锁成功,RC和RR 都支持。
间隙锁
锁的是记录间间隙。RR才有
临键锁
锁的是当前记录+记录前间隙,约等于间隙锁+行锁。RR才有
临键锁和间隙锁都是为了解决幻读
如何解决: 假设数据id有 1 2 3 4 8, select where id >=4
则应当选取4和8,为以防在4-8之间或8之后插入数据
因此会给4加行级锁,给8加临键锁,8-无穷加间隙锁
根据性质,上面的锁又划分为共享读锁和独占写锁
- 本文作者: 魏静崎
- 本文链接: https://slightwjq.github.io/2025/08/09/MySQL-锁和MVCC/
- 版权声明: 该文章来源及最终解释权归作者所有