事务隔离级别需按场景精准选择:REPEATABLE READ防不住库存扣减中的幻读,SERIALIZABLE性能差,READ COMMITTED仍可能触发间隙锁;应优先用SELECT ... FOR UPDATE显式加锁,并配合唯一约束+重试处理幻读。事务隔离级别选错,脏读幻读不是bug是配置MySQL 默认的 REPEATABLE READ 看似稳妥,但对"库存扣减+下单"这类强一致性场景,它防不住幻读------比如两个事务同时查到库存 10,都通过校验,然后都执行 UPDATE inventory SET stock = stock - 1,结果变成 8 而非预期的 9。这不是代码写错了,是隔离级别没压住并发语义。真正起作用的不是"设得高",而是"设得准":READ UNCOMMITTED 基本不用,连未提交变更都能读,业务逻辑大概率崩READ COMMITTED 能防脏读,适合日志归档、报表统计等允许"读到中间态"的场景;但在库存类操作中,两次 SELECT 可能返回不同结果,导致校验失效REPEATABLE READ 是 InnoDB 默认,可重复读,但幻读靠间隙锁(gap lock)模拟,一不小心就锁表或死锁SERIALIZABLE 最严,所有 SELECT 隐式加共享锁,写操作阻塞读,吞吐暴跌,仅适合极低频关键核对(如财务对账)用 SELECT ... FOR UPDATE 而不是单纯调高隔离级别很多人以为把隔离级别提到 SERIALIZABLE 就万事大吉,其实更可靠、更轻量的做法是在关键路径显式加锁。比如扣库存前,用 SELECT stock FROM inventory WHERE id = 123 FOR UPDATE,这条语句会在索引记录上加行锁(如果条件走索引),后续同 key 的更新必须等待。注意几个实际坑点:没走索引?FOR UPDATE 会升级为表锁,整个表卡住WHERE 条件含函数或隐式转换(如 WHERE sku_id = '123' 但字段是 INT),索引失效,照样锁全表事务里先 SELECT ... FOR UPDATE,再做其他无关查询,可能延长锁持有时间,增加冲突概率应用层没捕获 Lock wait timeout exceeded 错误,直接报 500,用户感知就是"下单失败",而非重试幻读真实发生时,别硬扛,换唯一约束+重试比如"防止重复下单",用 SELECT ... FOR UPDATE 查订单是否存在,再插入,看似闭环,但两个事务查完都没单,都去插,唯一索引冲突后一个失败------这就是幻读在作祟。这时靠隔离级别解决成本高(SERIALIZABLE 太重),靠锁又难覆盖所有路径。 Murf AI AI文本转语音生成工具
相关推荐
xlxxy_11 分钟前
外部系统调用SAP接口遇到的一些报错八角.。14 分钟前
方法参数与Debug按键麦聪聊数据25 分钟前
连锁零售全域数据管控(下):API 化服务输出,释放全域数据业务价值奇树谦44 分钟前
NAS + 对象存储 + LMDB/HDF5:海量小文件存储最佳实践卷无止境1 小时前
拯救乱码方块:pandas 绘图中文字体的一揽子解决方案李昊哲小课1 小时前
fastapi sse websocket 智能家居实时控制台观远数据1 小时前
决策闭环的第三公里:从洞察到行动之间,AI能补上什么杰佛史彦明 本王是暴君1 小时前
PyTorch KernelAgent 源码解读 ---(2)--- 总体流程Zane19941 小时前
别再手写 try/finally 了:一文讲透 with 语句背后的上下文管理器协议满昕欢喜2 小时前
2.4 本地服务器组和中央管理服务器