LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

数据库死锁场景如何复现和解决?

freeflydom
2025年3月17日 10:32 本文热度 17

需了解死锁先看这一篇

死锁是如何被发现和解决的?这篇文章告诉你

一、死锁的产生原因

  • 死锁发生在两个或多个事务相互等待对方释放锁,导致它们都无法继续执行的情况,形成死锁。
  • 这种情况在并发高的系统中比较常见,尤其是在多个事务同时操作相同的数据时。

常见场景包括:

  1. 不同顺序访问资源:事务A先操作表1再操作表2,事务B先操作表2再操作表1。
  2. 索引缺失:全表扫描导致锁范围扩大,增加冲突概率。
  3. 长事务:事务长时间未提交,导致锁持有时间过长。

二、死锁场景复现(以MySQL为例)

  • 复现死锁可以帮助理解问题发生的条件,从而更好地预防和解决。
1. 准备测试表和数据
CREATE TABLE account (
    id INT PRIMARY KEY,
    balance DECIMAL(10,2)
);
INSERT INTO account VALUES (1, 1000.00), (2, 2000.00);
2. 模拟两个事务交叉更新
  • 事务A:先更新id=1,再更新id=2。

    BEGIN;
    UPDATE account SET balance = balance - 100 WHERE id = 1;
    -- 等待事务B执行后再继续
    UPDATE account SET balance = balance + 100 WHERE id = 2;
    COMMIT;
    
  • 事务B:先更新id=2,再更新id=1。

    BEGIN;
    UPDATE account SET balance = balance - 200 WHERE id = 2;
    -- 等待事务A执行后再继续
    UPDATE account SET balance = balance + 200 WHERE id = 1;
    COMMIT;
    
3. 观察死锁
  1. 按顺序执行事务A和事务B的UPDATE语句。
  2. 事务A尝试更新id=2时,因事务B持有锁而等待。
  3. 事务B尝试更新id=1时,因事务A持有锁而等待。
  4. 数据库检测到死锁,自动回滚其中一个事务:
    1205 - Lock wait timeout exceeded; try restarting transaction
    


三、解决死锁的核心方法

  • 常见的解决策略包括设置合理的事务隔离级别、优化事务逻辑、使用超时机制、以及数据库自动检测和处理死锁
1. 数据库自动处理
  • 死锁检测:数据库自动检测死锁并回滚代价较小的事务(如MySQL默认开启)。
  • 查看死锁日志(MySQL):
    SHOW ENGINE INNODB STATUS;  -- 查看LATEST DETECTED DEADLOCK部分
    
2. 代码层优化
  • 统一资源访问顺序:所有事务按相同顺序操作表或记录。
    -- 所有事务先更新id=1,再更新id=2
    UPDATE account SET ... WHERE id = 1;
    UPDATE account SET ... WHERE id = 2;
    
  • 减少事务粒度:避免长事务,尽快提交或回滚。
    // 示例:使用Spring的@Transactional设置超时
    @Transactional(timeout = 5)  // 事务5秒未完成则回滚
    public void transfer() { ... }
    
  • 使用乐观锁:通过版本号避免行锁竞争。
    UPDATE account 
    SET balance = 900, version = version + 1 
    WHERE id = 1 AND version = 1;
    
3. 数据库配置调优
  • 降低隔离级别:从REPEATABLE READ改为READ COMMITTED,减少锁冲突。
    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
    
  • 索引优化:为WHERE条件字段添加索引,缩小锁范围。
    ALTER TABLE account ADD INDEX idx_id (id);
    
4. 重试机制
  • 捕获死锁异常:代码中捕获DeadlockException并重试。
    int retryCount = 0;
    while (retryCount < 3) {
        try {
            executeTransaction();
            break;
        } catch (DeadlockException e) {
            retryCount++;
            Thread.sleep(100); // 等待后重试
        }
    }
    

四、死锁分析工具

  1. MySQL死锁日志

    • 查看SHOW ENGINE INNODB STATUS输出,分析TRANSACTIONWAITING FOR THIS LOCK部分。
  2. pt-deadlock-logger(Percona工具):
    实时监控死锁事件并记录。

    pt-deadlock-logger --user=root --password=123456 --run-time=10
    
  3. 性能模式(Performance Schema)
    MySQL 5.6+开启性能模式,监控锁等待事件。

    SELECT * FROM performance_schema.events_transactions_current;
    


五、预防死锁

  1. 事务设计原则
    • 短事务优先,及时提交。
    • 避免交叉更新多张表。
  2. 统一操作顺序
    所有业务逻辑按固定顺序访问资源(如按主键升序操作)。
  3. 监控与报警
    配置Prometheus监控死锁次数,超过阈值触发告警。
  4. 压力测试
    使用JMeter模拟并发事务,验证死锁概率。

六、总结

  • 复现死锁:通过交叉更新不同顺序的资源,观察数据库自动回滚。
  • 解决方案
    • 统一资源访问顺序,减少锁竞争。
    • 优化索引和事务设计,降低死锁概率。
    • 结合重试机制和数据库自动处理,提升系统容错性。
  • 关键工具:数据库日志、性能分析工具、压力测试框架。

转自https://juejin.cn/post/7481837718718644274


该文章在 2025/3/17 10:33:31 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved