【计算机基础速成】第五课:锁、MVCC 与数据库并发控制
1. 这节课的目标
前一课我们讲了事务、ACID 和隔离级别。这一课要回答一个很自然的问题:
数据库到底是怎么在并发场景下控制数据问题的?
这节课的核心就是:
- 锁
- MVCC
面试官常见问法包括:
- 什么是数据库锁?
- 行锁和表锁有什么区别?
- 共享锁和排他锁是什么?
- 乐观锁和悲观锁有什么区别?
- 什么是 MVCC?
- MVCC 和锁有什么关系?
这节课学完后,你至少要做到:
- 能说清数据库为什么需要锁
- 能分清表锁、行锁、共享锁、排他锁
- 能分清乐观锁和悲观锁
- 能说出 MVCC 的核心作用
- 能回答“事务隔离不只是靠锁,还可能靠 MVCC”
2. 为什么数据库需要锁
一句话理解
因为多个事务并发操作同一份数据时,可能会互相冲突,所以需要锁来协调访问。
举个例子
假设商品库存是 10。
事务 A 在扣减库存。 事务 B 也在扣减库存。
如果没有任何控制,两个事务可能同时读取到库存 10,然后都去减 1,最后结果可能不对。
所以数据库需要某种机制,保证并发时数据尽量正确。
这个机制里最直观的一种,就是:
锁
3. 什么是锁
一句话理解
锁就是数据库在并发访问数据时使用的一种控制机制。
面试标准答法
锁是数据库用于控制并发访问的一种机制,当多个事务同时操作同一份数据时,数据库可以通过加锁来保证数据的一致性和隔离性,避免并发冲突。
关键词
- 控制并发访问
- 保证一致性
- 保证隔离性
- 避免冲突
4. 锁的常见分类
你现在最需要掌握的主要有三组分类:
- 表锁和行锁
- 共享锁和排他锁
- 乐观锁和悲观锁
5. 表锁和行锁
5.1 表锁
一句话理解
锁住整张表。
特点
- 加锁范围大
- 冲突概率高
- 并发能力差
- 实现相对简单
面试答法
表锁是对整张表加锁,当事务对表加锁后,其他事务对这张表的访问会受到较大限制。它的粒度较大,并发性能相对较差。
5.2 行锁
一句话理解
锁住某一行或某几行数据。
特点
- 加锁范围小
- 冲突概率低
- 并发能力更强
- 实现更复杂
面试答法
行锁是对具体的数据行加锁,相比表锁,它的锁粒度更细,可以让不同事务并发操作不同数据行,因此并发性能通常更好。
5.3 表锁和行锁怎么比较
| 类型 | 锁范围 | 并发能力 | 开销 |
|---|---|---|---|
| 表锁 | 整张表 | 较低 | 较小 |
| 行锁 | 某一行或某几行 | 较高 | 较大 |
面试标准答法
表锁锁定整张表,粒度较大,实现简单但并发能力差;行锁锁定具体行,粒度更细,并发能力更强,但锁管理成本也更高。
6. 共享锁和排他锁
这两个概念主要是从“读写权限”角度看锁。
6.1 共享锁
一句话理解
多个事务都可以读,但不能随便写。
面试答法
共享锁也叫读锁,事务获取共享锁后可以读取数据,多个事务之间通常可以同时持有共享锁,但其他事务如果想修改这条数据,通常需要等待。
6.2 排他锁
一句话理解
一个事务拿到后,别的事务不能再对这份数据做冲突操作。
面试答法
排他锁也叫写锁,事务获取排他锁后,其他事务通常不能再对这条数据加共享锁或排他锁,因此它主要用于保护写操作。
6.3 怎么记
- 共享锁:偏读
- 排他锁:偏写
一个非常粗略但够用的理解是:
- 读读可以共享
- 写通常需要更强控制
7. 乐观锁和悲观锁
这组概念在后端面试里非常高频,而且不只数据库会问,项目里也常问。
7.1 悲观锁
一句话理解
先假设冲突很容易发生,所以先锁住再操作。
面试答法
悲观锁的思想是,认为并发冲突很可能发生,所以在操作数据之前先加锁,确保操作期间其他事务不能产生冲突。
特点
- 更保守
- 更安全
- 并发性能可能较差
7.2 乐观锁
一句话理解
先假设冲突不容易发生,提交时再检查。
面试答法
乐观锁的思想是,认为并发冲突不一定经常发生,因此通常不会一开始就加数据库锁,而是在更新时通过版本号或时间戳等方式检查数据是否被其他事务修改过。
常见实现
- 版本号
- 时间戳
一个典型例子
假设一条数据有字段:
idstockversion
更新时带上版本条件:
update product
set stock = stock - 1, version = version + 1
where id = 1 and version = 3;如果更新成功,说明期间没人改过。 如果更新失败,说明版本已经变了,需要重试或报错。
7.3 乐观锁和悲观锁的区别
| 类型 | 思想 | 常见方式 | 特点 |
|---|---|---|---|
| 悲观锁 | 先假设会冲突 | 先加锁再操作 | 安全但并发可能差 |
| 乐观锁 | 先假设不易冲突 | 提交时校验版本 | 并发较好但可能重试 |
面试标准答法
悲观锁认为并发冲突很容易发生,所以通常会先加锁再操作;乐观锁认为冲突不一定频繁发生,通常在更新时通过版本号等方式做校验。前者更保守,后者并发性能通常更好。
8. 什么是 MVCC
这是数据库并发控制里最常见、也最容易被追问的概念之一。
你先不要被名字吓住。
MVCC 全称是:
Multi-Version Concurrency Control
中文常叫:
多版本并发控制
8.1 一句话理解
MVCC 通过为数据保留多个版本,让读操作和写操作尽量不互相阻塞。
8.2 为什么需要 MVCC
如果数据库只靠锁来解决并发问题,那么读写之间、甚至读读之间可能会更容易互相等待,影响并发性能。
MVCC 的核心价值就在于:
在保证一定一致性的前提下,提升并发性能。
8.3 更容易理解的说法
你可以把 MVCC 理解成:
- 写操作不会直接把过去的“可见状态”立刻完全抹掉
- 读操作可以根据自己的事务视角,去读某个合适版本的数据
这样就能减少很多不必要的锁冲突。
8.4 面试标准答法
MVCC 是多版本并发控制机制,它通过保存数据的多个版本,使得事务在读取数据时不一定需要加锁读取当前最新值,而是可以读取对自己可见的版本,从而减少读写冲突,提升并发性能。
9. MVCC 解决了什么问题
核心作用
- 减少读写冲突
- 提高并发性能
- 帮助实现更好的事务隔离效果
面试答法
MVCC 的核心作用是在并发场景下减少锁竞争,特别是让读操作和写操作尽量不互相阻塞,从而提升数据库的整体并发性能。
10. MVCC 和锁是什么关系
这是很重要的一道题。
很多初学者会误以为:
数据库解决并发问题只靠锁
其实不是。
正确理解
- 锁是一种并发控制手段
- MVCC 也是一种并发控制手段
- 它们常常会配合使用
面试标准答法
数据库的并发控制并不只依赖锁,MVCC 也是非常重要的机制。锁更适合处理写写冲突或需要强控制的场景,而 MVCC 更擅长优化读写并发,它们在数据库中通常会配合使用。
11. 为什么说事务隔离不只靠锁
你上一课学了隔离级别,这一课就要把它串起来。
可以这样理解
为了实现事务隔离,数据库可能会:
- 使用锁限制并发访问
- 使用 MVCC 让读操作读取合适版本
所以事务隔离不是“只有锁”,而是:
锁 + MVCC 等机制共同完成
12. 一套可直接背的完整答法
如果面试官问:
你说一下数据库并发控制。
你可以这样答:
数据库在并发场景下,为了保证数据一致性和隔离性,通常会使用锁和 MVCC 等机制进行并发控制。
锁本质上是控制多个事务对同一份数据访问的一种方式,
常见有表锁和行锁、共享锁和排他锁。
另外从思想上还可以分为乐观锁和悲观锁,
悲观锁更偏向先加锁再操作,乐观锁通常会在更新时通过版本号等方式做校验。
MVCC 是多版本并发控制,它通过保存数据的多个版本,让读操作能够读取对自己可见的版本,
从而减少读写冲突,提高并发性能。
所以数据库的事务隔离并不只是靠锁实现的,很多情况下还会结合 MVCC 一起工作。13. 本课高频面试题
13.1 什么是数据库锁
标准回答
锁是数据库用于控制并发访问的一种机制,当多个事务同时操作同一份数据时,数据库可以通过加锁来保证数据的一致性和隔离性,避免并发冲突。
13.2 行锁和表锁有什么区别
标准回答
表锁锁定整张表,粒度较大,并发能力相对较差;行锁锁定具体数据行,粒度更细,并发能力更强,但管理成本也更高。
13.3 共享锁和排他锁是什么
标准回答
共享锁通常也叫读锁,允许多个事务读取同一份数据;排他锁通常也叫写锁,事务持有排他锁后,其他事务通常不能再对该数据进行冲突操作。
13.4 乐观锁和悲观锁有什么区别
标准回答
悲观锁认为并发冲突很容易发生,所以通常会先加锁再操作;乐观锁认为冲突不一定频繁发生,通常在更新时通过版本号或时间戳等方式进行校验。前者更保守,后者并发性能通常更好。
13.5 什么是 MVCC
标准回答
MVCC 是多版本并发控制机制,它通过保存数据的多个版本,使事务读取时可以读取对自己可见的数据版本,从而减少读写冲突,提升并发性能。
13.6 MVCC 有什么作用
标准回答
MVCC 的核心作用是减少锁竞争,尽量让读写操作不互相阻塞,从而提升数据库在并发场景下的性能。
13.7 MVCC 和锁有什么关系
标准回答
锁和 MVCC 都是数据库并发控制的重要手段。锁更适合强控制场景,MVCC 更适合优化读写并发,它们通常会结合使用,而不是互相替代。
14. 本课最小记忆卡片
卡片 1
- 锁:控制并发访问,保证一致性和隔离性
卡片 2
- 表锁:锁整张表,粒度大,并发低
- 行锁:锁具体行,粒度小,并发高
卡片 3
- 共享锁:偏读
- 排他锁:偏写
卡片 4
- 悲观锁:先假设会冲突,先加锁
- 乐观锁:先假设不冲突,提交时校验
卡片 5
- MVCC:多版本并发控制
- 作用:减少读写冲突,提高并发性能
卡片 6
- 并发控制不只靠锁,也靠 MVCC
15. 课后练习
15.1 口头复述题
请你尝试不看讲义回答:
- 为什么数据库需要锁?
- 什么是表锁和行锁?
- 什么是共享锁和排他锁?
- 什么是乐观锁和悲观锁?
- 什么是 MVCC?
- MVCC 有什么作用?
- MVCC 和锁有什么关系?
15.2 场景思考题
- 如果一个系统读很多、写相对少,你觉得更希望数据库尽量依赖锁还是尽量减少锁冲突?
- 为什么乐观锁经常和版本号一起出现?
- 为什么说数据库事务隔离不是只靠锁?
15.3 今日最低完成标准
如果你今天时间不多,至少完成下面任务:
- 背会本课 6 张最小记忆卡片
- 能口头回答 7 道高频题
- 能完整说出“锁和 MVCC 是怎么做并发控制的”
16. 数据库阶段小结
到这里,你数据库面试最核心的五块内容已经基本连起来了:
- MySQL 和 SQL 基础
- SQL 进阶查询与
join - 索引
- 事务与隔离级别
- 锁与 MVCC
如果你能把这五部分都说顺,后端实习数据库八股已经有比较像样的底子了。
17. 下一课预告
第六课:计算机网络入门与 TCP/IP 分层