-
我为了保证原子性把几万条记录的批量处理塞进了一个数据库事务,结果这个事务跑了好几分钟,期间长时间持锁阻塞了其他业务、占满了连接池、还把回滚段撑得老大、主从延迟飙升:一次大事务拖垮整个库的深度复盘
我有个批量任务要更新几万条记录,想着这些操作得保证原子性、要么全成功要么全回滚,就放进一个事务里:开启事务→循环几万次逐条 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
-
我的两个事务互相等着对方手里的锁、谁也不肯松手,最后数据库直接报了死锁、强行回滚了一个,我盯着这个高并发下偶发的报错查了好几天的深度复盘
我的转账业务在一个事务里更新两条记录(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
-
后台改 40 万条数据把前台下单也搞挂了:一次 MySQL 大事务与锁等待的复盘
运营要把一批已发货超过 7 天的历史订单状态统一改成已完成约 40 万条,我图省事写了一条 UPDATE 把这 40 万行一次性更新,脚本跑约 40 秒,这 40 秒里整个电商的下单支付接口大面积超时,我改的是历史老订单和正在下单的新用户毫不相干凭什么把前台也搞挂。排查梳理:应用日志超时报的是 Lock wait timeout exceeded 关键词是等锁不是 DB 慢,SHOW PROCES…- 0
- 0
-
InnoDB 锁机制完全指南:Next-Key Lock、间隙锁与死锁排查
"为什么我的 UPDATE 把整张表锁了?""死锁日志里的 Next-Key Lock 是什么?""间隙锁怎么避免?" —— InnoDB 锁机制是 MySQL DBA 的入门必考题。这篇文章把 InnoDB 各种锁讲透:行锁、间隙锁、Next-Key Lock、意向锁、记录锁,以及它们在不同 SQL 下的实际行为。所有结论都配可复现的 …- 16
- 0
锁
幸运之星正在降临...
点击领取今天的签到奖励!
恭喜!您今天获得了{{mission.data.mission.credit}}积分
我的优惠劵
-
¥优惠劵使用时效:无法使用使用时效:
之前
使用时效:永久有效优惠劵ID:×
没有优惠劵可用!








