serializable会彻底阻塞并发写入,因其强制事务串行执行,所有select隐式加共享锁,update/insert等操作均需等待,导致qps断崖下跌、锁等待超时频发。

串行化隔离级别会彻底阻塞并发写入
串行化(SERIALIZABLE)不是“加更严的锁”,而是让事务在逻辑上变成单线程执行——只要两个事务操作的数据有重叠(哪怕只是同一张表的任意行),后发起的事务就会被挂起,直到前一个事务提交或回滚。这意味着:UPDATE、INSERT、SELECT ... FOR UPDATE 都可能触发等待,普通 SELECT 也会被隐式加上共享锁(InnoDB 默认行为),不再是无锁快照读。
常见错误现象:应用日志里频繁出现 Lock wait timeout exceeded,或者监控显示事务平均响应时间陡增、TPS 断崖下跌;开发查问题时发现“明明只改一行,为什么整个表都卡住了?”——大概率是误开了 SERIALIZABLE。
- 它不区分 DML 类型:即使是只读查询,只要落在同一张表,也可能被排队
- InnoDB 在该级别下基本弃用 MVCC 的一致性快照机制,转而依赖锁调度
- 和
REPEATABLE READ不同,SERIALIZABLE对范围查询(如WHERE status = 'pending')会加间隙锁(gap lock)甚至临键锁(next-key lock),防止幻读的同时也大幅扩大锁粒度
银行核心账务核销必须用串行化
不是“建议用”,而是监管合规硬性要求。比如某银行日终批处理中执行“总分核对+差额冲正”:需原子性地读取全部子账户余额、计算总和、比对总账、生成冲正凭证、更新总账余额——这整套流程必须确保中间无任何其他事务插入、修改或删除子账户记录,否则会出现“漏算一笔”或“重复冲正”。此时 SERIALIZABLE 是唯一能 100% 拦住幻读和不可重复读的选项。
典型使用场景:
- 金融类:跨机构资金划拨确认、监管报送数据封账、会计科目结转
- 政务类:选民资格最终锁定(禁止新增/删除)、不动产登记终审归档
- 工业控制:PLC 设备指令下发校验(不允许指令被并发覆盖)
注意:这些都不是在线交易接口,而是定时批处理任务,执行窗口固定、频次低(日/小时级),能承受排队延迟。
电商秒杀库存扣减不能靠串行化扛压
有人误以为“防止超卖就该上 SERIALIZABLE”,这是典型认知偏差。秒杀场景本质是高并发、低延迟、短事务,而 SERIALIZABLE 会让所有扣减请求串行排队,QPS 可能从 5000+ 掉到 200 以下,且极易因锁等待超时导致大量失败请求。
真正有效的方案是:
- 用
REPEATABLE READ+SELECT ... FOR UPDATE锁住具体库存行(非全表) - 前置 Redis 原子计数器做第一层削峰
- 库存扣减 SQL 必须带明确主键条件(如
WHERE sku_id = ? AND stock > 0),避免间隙锁放大
串行化在这里不仅没解决问题,反而把系统拖垮——它解决的是“绝对一致”,不是“高并发下的正确一致”。
串行化配置容易被忽略的细节
MySQL 默认隔离级别是 REPEATABLE READ,要启用 SERIALIZABLE 必须显式设置,但很多人只在会话级改,忘了应用连接池可能复用连接,导致部分请求意外继承旧级别。
- 全局生效:
SET GLOBAL transaction_isolation = 'SERIALIZABLE';(需重启连接才生效) - 会话级生效:
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;(仅当前连接) - JDBC 连接字符串里加
sessionVariables=transaction_isolation=SERIALIZABLE才能保证每次新建连接都带上
最危险的是混合使用:主库设为 SERIALIZABLE,从库仍是 REPEATABLE READ,会导致主从间 binlog 复制语义不一致,出现数据偏差。生产环境若真要用,必须主从同配,且提前压测锁排队模型。











