媒体文件自动摄取、归档与镜像同步:一套可落地的Linux方案
2026/10/2 18:17:29
通过本节学习,你将掌握:
学完本节后,你将能够:
问题描述:某电商平台在双11促销期间,大量用户同时抢购热门商品。系统频繁出现死锁错误,导致部分订单处理失败。通过监控发现,死锁主要发生在库存扣减操作中。
你的任务:如何快速定位死锁原因,并设计解决方案避免死锁?
问题描述:某金融系统的转账功能,当多个用户同时进行转账操作时,偶尔会出现死锁。虽然MySQL会自动回滚其中一个事务,但用户体验受到影响。
你的任务:如何分析死锁日志,并优化业务逻辑避免死锁?
死锁是数据库系统中最棘手的问题之一,特别是在高并发的业务场景中。当多个事务相互等待对方持有的资源锁时,就会形成死锁,导致事务无法继续执行。深入理解死锁的成因、排查方法和预防策略,对保障数据库稳定运行至关重要。本节将为你提供一套完整的死锁排查和解决方案。
死锁是指两个或多个事务在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
这是最常见的死锁场景:
-- 会话1执行BEGIN;UPDATEemployeesSETsalary=55000WHEREemp_no=10001;-- 等待一会再执行下一步-- 会话2执行BEGIN;UPDATEemployeesSETsalary=60000WHEREemp_no=10002;UPDATEemployeesSETsalary=56000WHEREemp_no=10001;-- 此时会阻塞-- 回到会话1执行UPDATEemployeesSETsalary=61000WHEREemp_no=10002;-- 死锁发生!-- 假设表有两个索引:PRIMARY(emp_no) 和 idx_dept_no(dept_no)-- 会话1BEGIN;UPDATEemployeesSETdept_no='d002'WHEREemp_no=10001;-- 等待一会再执行下一步-- 会话2BEGIN;UPDATEemployeesSETdept_no='d001'WHEREemp_no=10002;UPDATEemployeesSETdept_no='d002'WHEREemp_no=10003;-- 可能阻塞-- 回到会话1UPDATEemployeesSETdept_no='d001'WHEREemp_no=10002;-- 死锁可能发生在可重复读隔离级别下,范围查询会产生间隙锁:
-- 表中emp_no数据: 10001, 10002, 10005, 10008-- 会话1BEGIN;SELECT*FROMemployeesWHEREemp_noBETWEEN10003AND10006FORUPDATE;-- 锁住了(10002, 10005]区间-- 会话2BEGIN;SELECT*FROMemployeesWHEREemp_noBETWEEN10004AND10007FORUPDATE;-- 锁住了(10002, 10005]和(10005, 10008]区间-- 会话1INSERTINTOemployeesVALUES(10007,'1990-01-01','John','Doe','M','2020-01-01');-- 可能发生死锁MySQL的InnoDB存储引擎内置了死锁检测机制。
InnoDB使用等待图(waits-for graph)来检测死锁: