FOR UPDATE 读到了新值,下一条 SELECT 却又读回旧值
RR 下,B 的快照里 k = 1,之后 C 提交把 k 改成 5:
-- B
SELECT k FROM t WHERE id = 1 FOR UPDATE; -- 5
SELECT k FROM t WHERE id = 1; -- 1FOR UPDATE / FOR SHARE 是当前读:读最新已提交的版本并加锁。但它们不产生新版本,快照也不会刷新,所以紧跟着的普通 SELECT 照旧按快照读到 1。
加锁只是挡住别人再改,不改变可见性。想在事务里一直拿最新值,后续读也要加 FOR UPDATE。
两种锁定读的区别:
| 别人 FOR SHARE | 别人 FOR UPDATE / 改行 | 别人普通 SELECT | |
|---|---|---|---|
| 我 FOR SHARE | 可以 | 要等 | 可以 |
| 我 FOR UPDATE | 要等 | 要等 | 可以 |