-
我在一个数据库事务里先改了几张表的数据、又顺手执行了一条建临时表的 DDL,本以为整段都在事务保护下出错能一起回滚,结果后面一步失败我 rollback 时,前面改的数据竟然怎么都退不回去、已经实实在在落库了,排查很久才知道那条 DDL 早就把我的事务偷偷提交掉了的深度复盘
我有个操作需要在一个事务里完成好几步:先更新 A 表几行、再更新 B 表几行,中间为做点临时计算顺手 CREATE TEMPORARY TABLE 建了张临时表,最后再写 C 表。我用 START TRANSACTION 开了事务,心想万一哪步出错 ROLLBACK 一下所有改动就都干净撤销了。结果写 C 表那步因约束冲突失败,我老老实实 ROLLBACK,可回头一查 A 表 B 表的改动还在一行…- 0
- 0
-
我为了保证原子性把几万条记录的批量处理塞进了一个数据库事务,结果这个事务跑了好几分钟,期间长时间持锁阻塞了其他业务、占满了连接池、还把回滚段撑得老大、主从延迟飙升:一次大事务拖垮整个库的深度复盘
我有个批量任务要更新几万条记录,想着这些操作得保证原子性、要么全成功要么全回滚,就放进一个事务里:开启事务→循环几万次逐条 update→提交。功能没问题,可一上线跑,整个数据库就开始抖:其他业务大面积报锁等待超时、连接池被占满、主从延迟从毫秒飙到几十秒、DBA 告警 undo 暴涨。复盘才理解大事务的危害:一个事务在开始到提交的整个期间会持有它改过的行的锁、占用一个连接、在 undo log 里…- 0
- 0
-
两笔转账并发执行,一笔从 A 转 B、一笔从 B 转 A,数据库突然报 Deadlock found 把其中一笔回滚了:一次数据库死锁、加锁顺序不一致循环等待的深度复盘
我的转账逻辑一个事务里更新两个账户(扣转出方、加转入方),平时好好的,可线上偶发数据库报 Deadlock found、其中一笔被回滚。把两笔并发转账的加锁顺序画出来才看明白:事务 T1 从 A 转 B 先锁 A 再要锁 B,事务 T2 从 B 转 A 先锁 B 再要锁 A——T1 锁住 A 等 B、T2 锁住 B 等 A,互相等对方释放、循环等待、谁也动不了,数据库检测到死锁就挑一个回滚。根因是…- 0
- 0
-
两个并发事务因为以不同的顺序去更新两条记录,互相等着对方手里的锁,撞成了死锁、被 MySQL 强行回滚了一个:一次数据库死锁的深度复盘
转账接口高并发时偶发 Deadlock found,部分请求失败。根因是一个事务要更新两条记录,而不同请求加锁顺序不同:A→B 的请求先锁 A 再锁 B、B→A 的先锁 B 再锁 A,并发时事务1持有A等B、事务2持有B等A,互相等待形成循环等待的环、谁也走不了,MySQL 检测到死锁就回滚其中一个。本文讲透死锁怎么形成和它的四个必要条件,给出固定加锁顺序(破坏循环等待,最有效)、缩小事务/缩短持…- 0
- 0
-
我的转账接口在高峰期偶尔会报 Deadlock found、事务莫名其妙被回滚,我对着这个时有时无的数据库死锁排查了大半天才搞懂加锁顺序的复盘
我的转账接口在一个事务里扣 A 加 B,平时没事,一到高峰并发大就偶发 Deadlock found、事务被强行回滚,时有时无、并发越高越频繁。把并发事务的加锁顺序画在纸上一对照才懂:这是死锁,根源是加锁顺序不一致——A 转 B 的事务先锁 A 再锁 B,而同时 B 转 A 的事务先锁 B 再锁 A,于是事务1锁住A等B、事务2锁住B等A,各自持有对方想要的锁、互相死等,形成循环等待;InnoDB…- 0
- 0
-
我的两个事务互相等着对方手里的锁、谁也不肯松手,最后数据库直接报了死锁、强行回滚了一个,我盯着这个高并发下偶发的报错查了好几天的深度复盘
我的转账业务在一个事务里更新两条记录(A 扣钱、B 加钱),本地一切正常,可一上高并发就偶发报 Deadlock found、还被强行回滚一个事务。复盘并发的事务才懂:有的请求是 A 转 B(先锁 A 再锁 B)、有的是 B 转 A(先锁 B 再锁 A),加锁顺序相反;恰好交错时,T1 锁 A 等 B、T2 锁 B 等 A,互相死等成环,这就是死锁。InnoDB 检测到循环等待就回滚代价小的那个。…- 0
- 0
-
转账偶发死锁:MySQL Deadlock 成因与根治避坑
有个转账功能逻辑很简单:从账户 A 扣钱给账户 B 加钱,两步包在一个事务里,平时跑得好好的。可一到大促并发一高,日志里就零星冒出 Deadlock found when trying to get lock; try restarting transaction——死锁,受影响的转账直接失败回滚。我一开始百思不得其解:就两条 update 怎么会死锁?顺着日志把并发的两笔转账摆在一起对比才看清真…- 2
- 0
-
从粗放 MySQL 交易库 @Transactional 包住整个大方法连远程支付调用都裹进事务里行锁被慢接口绑架数秒高峰锁等待瀑布堆积连接池占满雪崩 + 压根不懂隔离级别用默认或乱设脏读不可重复读幻读分不清还把快照读和 FOR UPDATE 当前读混用读出灵异结果 + 凡是更新就无脑 select for update 悲观锁把读多写少场景的并行更新硬串行化 + 加锁顺序五花八门死锁频发只能靠重启清场 + 更新条件不走索引 InnoDB 行锁退化成扫描路径锁住一大片甚至全表把无关更新全阻塞 + 热点大商家账户单行被每秒上万笔成交更新行锁让请求排成长龙吞吐卡死 + 库存扣减用裸 read-modify-write 并发下丢失更新导致严重超卖发不出货 + 大事务循环更新几万行跑几分钟持锁堆 undo 拖慢全库还有僵尸事务赖着不走 + 锁等待死锁长事务全是黑盒出事才 SSH 上去 show processlist 肉眼抓瞎 → 2026 现代高并发数据库工程 短事务只包必须原子的 DB 写远程调用挪到事务外 + 理解四个隔离级别权衡默认 RR 分清 MVCC 快照读当前读 + 读多写少用乐观锁版本号 CAS + 统一按主键升序加锁加死锁监控加自动重试 + 写条件必走索引 EXPLAIN 确认行锁精准只锁命中行 + 热点账户余额分桶拆成多行分散并发读时 SUM 合并 + 原子 UPDATE x=x±? 加 stock>=1 条件根治丢失更新和超卖 + 批量拆成分批小事务加长事务监控告警 + performance_schema 持续度量锁等待和长事务做大盘告警 87 天战役复盘:47 套工程修法 + 7 个 P0 复盘 + 6 条工程哲学
8 人的数据库与交易平台团队 87 天把一套跑了五年、日订单量从每天几十万笔涨到上千万笔、大促高峰每秒上万笔并发写入后种种粗放并发写法集中爆雷的核心交易数据库——@Transactional 习惯性地甩在最外层大方法上把查库改库远程支付调用发消息发短信统统圈进同一个事务里一次慢支付就让账户行锁被绑架数秒高峰期锁等待瀑布式堆积连接池被长事务占满整个交易服务超时雪崩、压根不懂事务隔离级别要么手欠调到串…- 5
- 0
-
从应用层手写字符串拼接 SQL 有注入风险 + 每次请求新建连接不复用 + 几乎不建索引查询全表扫描 + 循环里逐条查的 N+1 灾难 + 大事务长时间持锁 + 单库单表硬扛全部读写 + 没有慢查询监控不看执行计划凭感觉优化 古老数据库使用体系 → 2026 参数化预编译彻底防注入 + HikariCP 连接池化复用 + 合理索引与覆盖索引 + 批量查询消灭 N+1 + 清晰事务边界与乐观锁 + 读写分离与分库分表水平扩展 + 慢查询日志加 EXPLAIN 执行计划分析 + Redis 旁路缓存与穿透击穿雪崩防护 现代数据库工程体系 87 天战役复盘:47 套工程修法 + 7 个 P0 复盘 + 6 条工程哲学
12 位 DBA 与后端工程师 87 天把一套跑了七年的粗放数据库使用体系——应用层手写字符串拼接 SQL 随时可能被注入脱库、每次请求新建连接不复用、几乎不建索引查询全表扫描、ORM 在循环里逐条查的 N+1 灾难、一个大事务包住一大堆操作长时间持锁让热点行排队、单库单表硬扛全部读写流量一大主库就 CPU 打满、没有慢查询监控不看执行计划全凭感觉瞎调——用在线 DDL 加双写灰度的稳健方式重构到…- 0
- 0
-
Spring @Transactional 失效的 7 种典型场景:从扣款不回滚事故说起 + code review 检查清单
扣款接口失败时没回滚,代码里明明写了 @Transactional,事务怎么就没生效?这是 Spring 老手都不一定能一次答对的问题。这篇把团队踩过的七种典型失效场景全部整理出来 — 类内自调用、非 public 方法、checked exception、异常被吞、传播行为配错、多数据源、@Async 跨线程,每种给最小复现、根因、修法,以及一套能在 code review 阶段就拦住的 Arc…- 2
- 0
-
MySQL 可重复读下 INSERT 间隙锁死锁的真实复盘:4 种修法 + 6 条铁律
订单接口在并发压测下死锁率高达 3%,排查到最后发现是 SELECT FOR UPDATE 加的间隙锁覆盖了多个用户范围,两个 INSERT 互相阻塞触发死锁。这篇把死锁的真实加锁机制、四种修法的取舍、定位死锁的标准流程、跨数据库对比、以及团队最终立的六条铁律,完整讲一遍。- 2
- 0
-
数据库死锁完全指南:从一次"两条没问题的 SQL 放一起却死锁"看懂为什么加锁顺序才是根因
2022 年我做一个电商的下单功能用户下单要做两件互相关联的事扣掉商品的库存在用户账户上记一笔消费这两件事必须一起成功或一起失败我自然用一个数据库事务把它们包起来第一版我做得很顺手事务开始 UPDATE 商品表扣库存 UPDATE 用户表记消费提交本地一测下单流畅库存和账户都对得上我心里很笃定事务嘛把要一起成功的几步包进 BEGIN COMMIT 数据库自己保证它们要么全成要么全败这下单稳了可等真…- 0
- 0
-
数据库死锁完全指南:从一次"大促下单成片失败、库存还被扣两次"看懂死锁的根治
2022 年我做一个电商的下单系统下单时要在一个事务里挨个扣减购物车里每个商品的库存。第一版我做得很省事拿到购物车的商品列表就按列表里的顺序一个个 UPDATE 过去。本地我下了几十单测了测真不错库存扣得准订单也对得上。我心里很踏实事务嘛把要改的几行包进一个 BEGIN COMMIT 数据库自己会保证一致。可等这个系统真正上线扛起大促的并发下单一串问题冒了出来。第一种最先把我打懵后台日志里时不时蹦…- 43
- 0
-
后台改 40 万条数据把前台下单也搞挂了:一次 MySQL 大事务与锁等待的复盘
运营要把一批已发货超过 7 天的历史订单状态统一改成已完成约 40 万条,我图省事写了一条 UPDATE 把这 40 万行一次性更新,脚本跑约 40 秒,这 40 秒里整个电商的下单支付接口大面积超时,我改的是历史老订单和正在下单的新用户毫不相干凭什么把前台也搞挂。排查梳理:应用日志超时报的是 Lock wait timeout exceeded 关键词是等锁不是 DB 慢,SHOW PROCES…- 0
- 0
-
加了 @Transactional 却不回滚:一次 Spring 事务失效的复盘
下单接口订单写成功了,扣库存那步抛异常,事务却没回滚 —— 订单留下了,库存没扣。方法上明明写着 @Transactional。排查发现是类内部自调用绕过了 AOP 代理。几天事务专项治理:理解代理机制、修自调用、异常处理与 rollbackFor、方法可见性、多线程与事务传播行为、事务自检与监控。- 3
- 0
-
Spring @Transactional 失效的 7 种真实场景 + 修法
标了 @Transactional 测试也好好的,生产却出现部分写入。本文 7 种事务失效场景:同类内部调用 / 非 public / 异常被吞 / checked exception / MyISAM / 多数据源 / Propagation 配错。每个附复现代码 + 3 种修法。- 0
- 0
-
MVCC 完全指南:从 ReadView 到 InnoDB 多版本并发控制
MVCC(Multi-Version Concurrency Control,多版本并发控制)是现代数据库实现"读不阻塞写,写不阻塞读"的关键技术。MySQL InnoDB、PostgreSQL、Oracle 全用它。但大多数人对 MVCC 的理解停留在"有多个版本",问起 ReadView 怎么算、四个隔离级别下具体怎么工作、为什么 RR 隔离级别能解决幻…- 0
- 0
事务
幸运之星正在降临...
点击领取今天的签到奖励!
恭喜!您今天获得了{{mission.data.mission.credit}}积分
我的优惠劵
-
¥优惠劵使用时效:无法使用使用时效:
之前
使用时效:永久有效优惠劵ID:×
没有优惠劵可用!

















