事务不只是“打包提交”,还涉及并发隔离。
想象有两个户籍窗口同时在翻同一本总账:
- A 窗口正在修改
- B 窗口正在查询
- 两边到底能看到什么
这就是隔离级别要解决的问题。
InnoDB 支持四种经典隔离级别:
| 隔离级别 | 户籍总账类比 | 直觉理解 |
|---|---|---|
READ UNCOMMITTED |
你连别人还没盖章的草稿都能偷看 | 最松,可能脏读 |
READ COMMITTED |
只能看已盖章版本,但每翻一次都可能看到新版本 | 不脏读,但可能不可重复读 |
REPEATABLE READ |
本次办理期间,你一直按第一次看到的账本快照办事 | InnoDB 默认级别 |
SERIALIZABLE |
大家尽量像排单队,一个个严肃办理 | 最严格,并发代价最高 |
设置会话级隔离级别:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;然后开始事务:
START TRANSACTION;要理解 InnoDB 的默认 REPEATABLE READ,你可以先记住一句话:
普通 SELECT 往往读的是一致性快照。
也就是:
- 不是所有读都会加锁
- 在一个事务里,普通查询可能持续看到同一份“时间切片”
这正是 InnoDB 并发能力强的重要原因。
但如果你不是单纯“看看”,而是要“看完就改”,就要用锁定读:
SELECT *
FROM citizens
WHERE citizen_id = 1
FOR UPDATE;或者:
SELECT *
FROM citizens
WHERE citizen_id = 1
FOR SHARE;可以把它理解为:
FOR UPDATE:这条档案我先占住,别人别改FOR SHARE:这条档案我先按住,别人先别写
还要知道一个 MySQL/InnoDB 的重点:
在 REPEATABLE READ 下,InnoDB 不只是管“行”,还会在一些范围场景里用到 gap lock / next-key lock 的思路,避免区间并发写带来更复杂的问题。
你不需要一开始把锁类型全背下来,但要知道:
隔离级别越强,越安全;通常也越容易带来等待和阻塞。