您好,登录后才能下订单哦!
# MySQL数据库死锁Deadlock found when trying to get lock怎么解决
## 一、什么是MySQL死锁
死锁(Deadlock)是指两个或多个事务在执行过程中,因争夺资源而造成的一种互相等待的现象。当MySQL检测到这种循环依赖关系时,会立即终止其中一个事务的执行,并抛出错误:
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
### 死锁的四个必要条件
1. **互斥条件**:资源一次只能被一个事务占用
2. **请求与保持条件**:事务持有资源的同时请求新的资源
3. **不剥夺条件**:已分配的资源不能被其他事务强行剥夺
4. **循环等待条件**:多个事务形成头尾相接的等待环路
## 二、MySQL死锁的常见场景
### 1. 不同顺序的加锁操作
```sql
-- 事务1
UPDATE table_a SET ... WHERE id = 1;
UPDATE table_b SET ... WHERE id = 2;
-- 事务2
UPDATE table_b SET ... WHERE id = 2;
UPDATE table_a SET ... WHERE id = 1;
在REPEATABLE READ隔离级别下,范围查询会产生间隙锁:
-- 事务1
SELECT * FROM table WHERE id BETWEEN 1 AND 10 FOR UPDATE;
-- 事务2
INSERT INTO table(id) VALUES(5); -- 被阻塞
-- 事务1
INSERT INTO users(id, name) VALUES(1, 'Alice');
-- 事务2
INSERT INTO users(id, name) VALUES(1, 'Bob'); -- 死锁可能发生
SHOW ENGINE INNODB STATUS\G
在输出中查找LATEST DETECTED DEADLOCK
部分。
在my.cnf中配置:
[mysqld]
innodb_print_all_deadlocks = 1
典型死锁日志包含: - 涉及的事务信息 - 持有的锁和等待的锁 - 最终被选为牺牲品(victim)的事务
确保所有事务按照相同的顺序访问表和行。
-- 不推荐
START TRANSACTION;
-- 大量业务逻辑
COMMIT;
-- 推荐
START TRANSACTION;
-- 仅必要的数据库操作
COMMIT;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 无索引的列会导致表锁
ALTER TABLE orders ADD INDEX idx_customer_id(customer_id);
SET innodb_lock_wait_timeout = 30; -- 单位秒
将大事务拆分为多个小事务执行。
UPDATE products
SET stock = stock - 1, version = version + 1
WHERE id = 100 AND version = 5;
SELECT * FROM table WHERE id = 1 FOR UPDATE NOWT;
应用程序捕获死锁异常后自动重试:
max_retries = 3
for attempt in range(max_retries):
try:
execute_transaction()
break
except DeadlockException:
if attempt == max_retries - 1:
raise
sleep(random.uniform(0, 0.1))
[mysqld]
innodb_deadlock_detect = ON # 默认开启
innodb_lock_wait_timeout = 50
// 使用Redis实现分布式锁
String lockKey = "order_lock_" + orderId;
boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
对高频竞争的表进行水平拆分。
-- 监控锁等待
SELECT * FROM performance_schema.events_waits_current
WHERE EVENT_NAME LIKE '%lock%';
-- 监控死锁次数
SHOW STATUS LIKE 'innodb_row_lock%';
现象:下单时频繁出现死锁
原因:库存扣减和订单创建未按固定顺序
解决方案:
1. 先锁商品记录,再锁优惠券记录
2. 引入Redis预减库存
现象:热点帖子点赞死锁
解决方案:
1. 使用计数器表+定期合并
2. 客户端批量提交
MySQL死锁是并发系统中常见问题,通过以下原则可以有效减少死锁: 1. 预防:统一资源访问顺序,减少事务持有时间 2. 检测:建立完善的监控体系 3. 恢复:实现自动重试机制 4. 优化:持续分析业务场景,针对性优化
最佳实践建议:在开发环境开启完整的死锁日志记录,定期分析潜在的死锁风险,将死锁处理方案纳入代码评审标准。
”`
这篇文章共计约2100字,采用Markdown格式编写,包含了: - 死锁原理说明 - 常见场景分析 - 诊断方法 - 12种解决方案 - 高级优化建议 - 真实案例 - 监控预警方案 - 总结与最佳实践
内容结构清晰,既有理论知识也有实操方案,适合DBA和开发人员阅读参考。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。