-
两笔转账并发执行,一笔从 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
-
我在一个异步方法上用 .Result 同步等了一下结果,整个请求就这么永远卡死了,没有任何报错也没有超时,我对着 async 配 .Result 造成的死锁这个坑排查大半天的复盘
一个让我对 C# async/await 从会用到敬畏的经典坑,折磨在它不报错不抛异常不超时,只是静悄悄永远卡死在那,请求转圈到天荒地老、日志却干干净净。老项目里要在一个同步方法里调一个异步方法拿数据,图省事没把整条链改异步,直接在异步方法后加了 .Result 想同步等结果:return GetDataAsync().Result。这在控制台可能正常,但放到旧版 ASP.NET、WPF、WinF…- 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
-
我图省事在一个 async 方法上调了 .Result 想同步拿结果,本地控制台跑得好好的,一放进 Web 服务高并发下整个请求就永久卡死的深度复盘
我有个 async 方法,想在同步方法里同步拿到结果,图省事顺手调了 .Result。本地控制台测试秒出、毫无问题。可一放进经典 ASP.NET(带 SynchronizationContext)的 Web 服务、并发一上来,那个请求就永久卡死、再也不返回,线程被一个个耗尽、整个服务雪崩。深挖才懂这是经典的 sync-over-async 死锁:await 的续体默认要回到原 Synchroniz…- 0
- 0
-
服务器很闲却瘫了:.NET 异步死锁避坑复盘
一个跑了两年都好好的 .NET 接口,某天起在流量高一点的时段就大面积超时,请求像泥牛入海一样卡住不返回。我第一反应是哪儿慢了,可登上服务器一看更懵:CPU 占用才百分之十几,内存宽裕,数据库一点不慢,可就是请求堆积、响应不出来——一个不忙的服务器,却服务不了请求。抓内存 dump 看线程栈才发现真相:进程里堆积着大量工作线程,几乎全卡在同一行形如 GetDataAsync().Result 的调…- 2
- 0
-
转账偶发死锁:MySQL Deadlock 成因与根治避坑
有个转账功能逻辑很简单:从账户 A 扣钱给账户 B 加钱,两步包在一个事务里,平时跑得好好的。可一到大促并发一高,日志里就零星冒出 Deadlock found when trying to get lock; try restarting transaction——死锁,受影响的转账直接失败回滚。我一开始百思不得其解:就两条 update 怎么会死锁?顺着日志把并发的两笔转账摆在一起对比才看清真…- 2
- 0
-
一行 .Result 拖垮整个应用:C# 异步死锁避坑
一个平时跑得稳稳的 ASP.NET 老项目,我给某接口加了点新功能、调用了异步 HTTP 客户端取下游数据,本地测一切正常,压测时却出了鬼:并发一上来接口就大面积超时,不是慢,是彻底卡死永远不返回,而且会蔓延,最后整个应用线程池仿佛被冻住,连其它正常接口也没了响应,重启能缓解、一压又复现。我先怀疑下游慢、线程池太小,抓 dump 一看线程没在干活,而是齐刷刷阻塞在同一行我自以为无害的代码:var …- 0
- 0
-
C# async/await 死锁实战:一个 .Result 如何让接口集体卡死
一个 ASP.NET 服务在压力上来时会偶发性地卡死——不是崩溃,是卡住,请求全部超时,线程数飙到几百,CPU 却低得可怜,像是所有线程都在睡觉。我排查了整整两天,最后的修复只是删掉了一个单词:.Result。这篇就从这个经典死锁讲起,把 async/await 真正讲透:它到底是什么(剧透:它不是多线程)、.Result 死锁是怎么互相等待锁死的、ConfigureAwait(false) 在防…- 2
- 0
-
C# async/await 踩坑实战:同步阻塞死锁、async void 与线程池饥饿
事情是从一个看起来人畜无害的 PR 开始的:一位同事在 ASP.NET Core 控制器里图省事,把异步调用写成了 var data = GetDataAsync().Result;,能编译、本地点一下也出结果,评审就这么过了——结果一上生产,这个接口在并发上来后开始大面积超时,最后整个应用线程池被拖垮、几乎所有请求一起卡死,根因就是这一行同步阻塞异步。那次之后我把这些年在 C# 异步上踩过的坑系…- 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
-
MySQL 可重复读下 INSERT 间隙锁死锁的真实复盘:4 种修法 + 6 条铁律
订单接口在并发压测下死锁率高达 3%,排查到最后发现是 SELECT FOR UPDATE 加的间隙锁覆盖了多个用户范围,两个 INSERT 互相阻塞触发死锁。这篇把死锁的真实加锁机制、四种修法的取舍、定位死锁的标准流程、跨数据库对比、以及团队最终立的六条铁律,完整讲一遍。- 2
- 0
-
ConcurrentHashMap.computeIfAbsent 嵌套调用导致 CPU 100% 的真实事故复盘
线上 Java 服务 CPU 100% 全线程卡死,jstack 看全堆在 ConcurrentHashMap.computeIfAbsent。本文讲清楚桶级 synchronized 嵌套调用的活锁原理 + 最小复现 + 5 种修法 + JMH 性能对比 + 排查 checklist。结论:缓存层一律用 Caffeine。- 0
- 0
-
RR 隔离级别 + INSERT ON DUPLICATE KEY UPDATE:让我半夜爬起来的死锁实录
凌晨 2 点 47 分,告警群弹出 5 条 MySQL 死锁日志。本文复盘从 SHOW ENGINE INNODB STATUS 看到 gap lock 真相、3 次失败修复、到最终 RC 模式 + FOR UPDATE 解决的全过程,附完整 SQL、排查命令和压测对比。- 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:×
没有优惠劵可用!
















