serializable 隔离级别不是更安全,而是主动制造串行冲突:postgresql 用谓词锁检测读写依赖并报错,mysql 则将所有 select 升级为临键锁导致死锁;二者均非异常而是设计行为,性能代价高,应优先优化访问模式而非盲目升级隔离级别。

Serializable 隔离级别不是“更安全”,而是主动制造串行冲突
在 PostgreSQL 或 MySQL 中启用 SERIALIZABLE,不是给事务加了一层“保险”,而是告诉数据库:“请模拟串行执行,并在检测到任何可能破坏串行等价性的读写依赖时,直接报错或死锁”。这不是异常,是设计行为。
- PostgreSQL 报
ERROR: could not serialize access due to read/write dependencies among transactions—— 这是它主动放弃而非失败 - MySQL(InnoDB)报
Deadlock found when trying to get lock—— 它用临键锁把 SELECT 范围也锁死,两个事务只要扫描重叠索引区间(比如都查WHERE status = 'pending'),就大概率互相等待超时 - 压测初期不显问题?因为低并发下锁等待被掩盖;一旦 QPS 上去,TPS 断崖下跌、慢查询里满屏
Lock wait timeout exceeded
谓词锁(Predicate Lock)在 PostgreSQL 中怎么“模拟串行”
PostgreSQL 不靠锁住物理行或间隙,而是记录事务“关心什么条件”——比如事务 A 执行了 SELECT * FROM orders WHERE user_id = 123 AND status = 'unpaid',系统就会记下这个谓词:(user_id=123 ∧ status='unpaid')。后续任何修改该谓词覆盖范围的写操作(如 UPDATE orders SET status = 'paid' WHERE user_id = 123),都会触发序列化检查。
- 它不阻塞读,但会拦截“可能影响该谓词结果”的写 —— 即便那行数据当前根本不在结果集中
- 没有索引支撑的谓词(如
WHERE JSON_CONTAINS(meta, '"vip": true'))会导致全表谓词注册,开销剧增 -
EXPLAIN (ANALYZE, BUFFERS)看不到谓词锁,但pg_stat_activity的state字段可能出现active+wait_event_type = 'Lock'+wait_event = 'PredicateLock'
MySQL 的 SERIALIZABLE 实际等于“所有 SELECT 都自动加 LOCK IN SHARE MODE”
MySQL 并不实现标准谓词锁,而是降级为“所有读都升级成临键锁”。这意味着哪怕你只写 SELECT id FROM users WHERE id = 100,它也会对 (99, 101) 这个间隙加锁;如果没走索引,就是全表加锁。
- 配置差异:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE在 MySQL 中全局生效于当前 session 的所有 SELECT,无法局部关闭 - 常见误用:在分页场景用
SELECT ... LIMIT 10 OFFSET 1000+ SERIALIZABLE → 锁住前 1010 行的间隙,极易被其他 INSERT 阻塞 - 性能影响:TPS 下降 50%+ 是常态;监控上表现为
Innodb_row_lock_time_avg方差极大,且innodb_lock_wait_timeout触发频率陡升
真正能绕过死锁的,从来不是换隔离级别,而是改访问模式
想防幻读或避免并发更新冲突,硬切 SERIALIZABLE 是最重、最慢、最容易崩的路。现实工程中更有效的做法,是让数据库少猜、少拦、快进快出。
- 把判断逻辑提到事务外:比如“扣库存前先查是否足够”,改成应用层缓存 + 原子计数器(Redis INCRBY),只在最终落库时用
UPDATE t SET stock = stock - 1 WHERE id = ? AND stock >= 1 - 用
SELECT ... FOR UPDATE显式锁住确定要改的行,比隐式谓词锁/临键锁范围小得多;但注意:WHERE 条件必须命中唯一索引,否则照样锁范围 - 乐观锁不是 SERIALIZABLE 的替代品:它不防止并发读取后各自提交,只保证“最后提交者胜出”。用
version字段时,必须处理UPDATE ... WHERE version = ?返回 0 行的重试逻辑,否则用户点一次下单没反应,再点一次就重复下单
SERIALIZABLE 只适合那种运行时间










