当前位置: 首页 > news >正文

数据库死锁分析与解决实战

数据库死锁分析与解决实战

一、死锁概述

死锁是指两个或多个事务在执行过程中,因互相等待对方持有的锁而陷入无限等待的状态。

1.1 死锁条件

条件说明
互斥资源只能被一个事务占用
请求与保持事务持有资源并请求新资源
不可剥夺资源不能被强制剥夺
循环等待事务形成循环等待链

1.2 死锁示例

事务A: BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; 事务B: BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 2; 事务A: UPDATE accounts SET balance = balance + 100 WHERE id = 2; -- 等待事务B 事务B: UPDATE accounts SET balance = balance + 100 WHERE id = 1; -- 等待事务A 结果:死锁!

二、死锁检测

2.1 MySQL死锁检测

-- 查看当前死锁 SHOW ENGINE INNODB STATUS\G -- 查看锁等待 SELECT * FROM performance_schema.data_locks; SELECT * FROM performance_schema.data_lock_waits; -- 查看事务 SELECT * FROM information_schema.INNODB_TRX;

2.2 死锁日志分析

------------------------ LATEST DETECTED DEADLOCK ------------------------ 2024-01-15 10:00:00 0x7f1234567890 *** (1) TRANSACTION: TRANSACTION 123456, ACTIVE 10 sec starting index read mysql tables in use 1, locked 1 LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s) MySQL thread id 100, OS thread handle 0x7f1234567890, query id 500 localhost user updating UPDATE accounts SET balance = balance + 100 WHERE id = 2 *** (2) TRANSACTION: TRANSACTION 123457, ACTIVE 10 sec starting index read mysql tables in use 1, locked 1 3 lock struct(s), heap size 1136, 1 row lock(s) MySQL thread id 101, OS thread handle 0x7f1234567891, query id 501 localhost user updating UPDATE accounts SET balance = balance + 100 WHERE id = 1 *** WE ROLL BACK TRANSACTION (1)

三、死锁预防

3.1 统一访问顺序

// 按主键顺序访问资源 public void transfer(Long fromId, Long toId, BigDecimal amount) { Long firstId = Math.min(fromId, toId); Long secondId = Math.max(fromId, toId); try (Connection conn = getConnection()) { conn.setAutoCommit(false); // 先更新ID较小的记录 String sql1 = "UPDATE accounts SET balance = balance - ? WHERE id = ?"; try (PreparedStatement pstmt = conn.prepareStatement(sql1)) { pstmt.setBigDecimal(1, amount); pstmt.setLong(2, firstId); pstmt.executeUpdate(); } // 再更新ID较大的记录 String sql2 = "UPDATE accounts SET balance = balance + ? WHERE id = ?"; try (PreparedStatement pstmt = conn.prepareStatement(sql2)) { pstmt.setBigDecimal(1, amount); pstmt.setLong(2, secondId); pstmt.executeUpdate(); } conn.commit(); } catch (SQLException e) { // 回滚处理 } }

3.2 缩短事务长度

@Transactional public void processOrder(Order order) { // 1. 验证订单 validateOrder(order); // 2. 更新库存(使用独立事务或延迟更新) updateInventoryAsync(order); // 3. 创建订单记录 orderRepository.save(order); // 4. 发送通知(异步处理) notificationService.sendAsync(order); }

3.3 使用乐观锁

@Transactional public boolean updateWithOptimisticLock(Long id, BigDecimal amount) { Account account = accountRepository.findById(id).orElseThrow(); if (account.getVersion() != expectedVersion) { throw new OptimisticLockingFailureException("Data has been modified"); } account.setBalance(account.getBalance().add(amount)); account.setVersion(account.getVersion() + 1); accountRepository.save(account); return true; }

四、死锁解决

4.1 超时机制

public void executeWithTimeout(Supplier<Void> operation, long timeoutMs) { ExecutorService executor = Executors.newSingleThreadExecutor(); Future<Void> future = executor.submit(() -> { operation.get(); return null; }); try { future.get(timeoutMs, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { future.cancel(true); throw new RuntimeException("Operation timed out"); } catch (Exception e) { throw new RuntimeException("Operation failed", e); } finally { executor.shutdown(); } }

4.2 重试机制

@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 100, multiplier = 2)) @Transactional public void transferWithRetry(Long fromId, Long toId, BigDecimal amount) { // 转账逻辑 accountRepository.debit(fromId, amount); accountRepository.credit(toId, amount); }

4.3 死锁检测与回滚

public void executeWithDeadlockRetry(Runnable operation) { int attempts = 0; int maxAttempts = 3; long backoffMs = 100; while (attempts < maxAttempts) { try { operation.run(); return; } catch (SQLException e) { if (isDeadlockError(e) && attempts < maxAttempts - 1) { attempts++; try { Thread.sleep(backoffMs * attempts); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); throw new RuntimeException(ie); } } else { throw e; } } } }

五、最佳实践

5.1 索引优化

-- 确保WHERE条件有索引 CREATE INDEX idx_accounts_id ON accounts(id); -- 复合索引优化 CREATE INDEX idx_orders_user_status ON orders(user_id, status); -- 避免全表扫描 EXPLAIN SELECT * FROM orders WHERE status = 'PENDING';

5.2 隔离级别选择

// 使用合适的隔离级别 @Transactional(isolation = Isolation.READ_COMMITTED) public void processTransaction() { // 业务逻辑 }
隔离级别说明死锁风险
READ_UNCOMMITTED最低级别
READ_COMMITTED读已提交
REPEATABLE_READ可重复读
SERIALIZABLE串行化最高

5.3 监控告警

# Prometheus告警规则 groups: - name: database.rules rules: - alert: DeadlockDetected expr: rate(innodb_deadlocks_total[5m]) > 0 for: 1m labels: severity: warning annotations: summary: "Deadlock detected in database" description: "{{ $value }} deadlocks detected in the last 5 minutes"

六、总结

死锁预防和解决策略:

  1. 统一访问顺序:按固定顺序访问资源
  2. 缩短事务:减少事务持有锁的时间
  3. 使用乐观锁:避免悲观锁竞争
  4. 超时重试:自动处理死锁场景
  5. 监控告警:及时发现死锁问题

通过合理的设计和优化,可以有效减少数据库死锁的发生。

http://www.cnnetsun.cn/news/2589587.html

相关文章:

  • 避开坐标转换的坑:手把手教你用OpenCV和PyProj实现UTM与局部坐标的精准对齐
  • IntelliJ IDEA里写Javadoc注释的偷懒技巧:Live Templates与@param自动补全
  • 用Python和蒙特卡洛树搜索(MCTS)从零实现一个会自我对弈的五子棋AI
  • 大型机与 JCL:那些现代云原生程序员完全无法理解的“黑魔法”
  • 零碳园区管理系统“云-边-端”架构协同的关键技术有哪些
  • 居家养老安全响应系统技术拆解:8分钟完成“跌倒-报警-救援”闭环的架构设计
  • Unity 2020.1 新手必看:用Sprite Editor快速搞定天天酷跑同款角色动画(附Demo工程)
  • 使用Koopman理论识别机器人动力学的非线性系统(Matlab代码实现)
  • 【单变量输入多步预测】基于BiLSTM的风电功率预测研究(Matlab代码实现)
  • 无人机光电吊舱稳定瞄准:坐标变换与卡尔曼滤波融合算法解析
  • 避坑指南:Win10/Win11系统下Origin2018安装失败与闪退问题全解决
  • 知识图谱与BERT融合:基于深度Inception网络的网页分类实践
  • Docker安装常见数据库命令汇总(2026)
  • 5分钟上手H5P交互式视频:让普通视频变身互动学习平台的完整指南
  • 机器学习与数字孪生如何革新光网络故障管理
  • C语言goto语句的正确使用与替代方案
  • 网文书名设计的技术分析:3秒决策心理与用户行为数据
  • 为什么你的咨询工具留不住用户?Lovable框架中隐藏的3层情感化设计机制大揭秘
  • 抓准应试诀窍!2026浙大MEM高分上岸实战备考心得分享~
  • 别再死记硬背了!用Python(NumPy/SciPy)可视化理解离散与连续概率分布
  • 湖南好课优选《Python软件开发》教材正式出版 | 匠心筑教,赋能未来 !
  • 金装裁决(传世元神版)| 正版复古传世,元神合击热血归来
  • 规范驱动开发:从OpenAPI到契约测试的API设计实战
  • 工厂老板如何从0开始做短视频获客?2026年制造业实战全流程指南
  • 别再傻傻等Git clone --recursive了!手把手教你用kgithub镜像源秒下带子模块的大项目
  • 别再只盯着AUC了!用Python手把手教你计算gAUC,搞定搜索推荐中的排序评估难题
  • Lovable客服系统搭建最后窗口期!政策合规升级倒计时30天,GDPR+等保2.0双认证预检清单首次公开
  • NanoController v2:为超低功耗控制任务定制指令集的微架构设计
  • 2026最新 |《曼达洛人与格罗古》:星战新篇全解析,这些细节你绝对不能错过
  • CLI-Chatbot实现多轮对话以及history