You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

生产环境MySQL死锁本地复现失败,求排查思路

MySQL死锁根源排查思路求助

错误场景

遇到的死锁错误信息:

SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction (SQL: update `pre_txns_2403` set `status` = SUCCESS, `response_code` = 0, `response_msg` = SUCCESS, `ipay_error` = TXN, `ipay_desc` = Transaction Successful, `sp_transid` = 407508316340, `opr_id` = 407508316340, `res_dt` = 2024-03-15 08:00:14, `optional1` = 607264, `optional2` = 9935558558, `optional3` = CENTRAL BANK OF INDIA, `optional4` = 5044.00, `optional5` = e46944ca4251477b92842311c55f5e1e, `optional6` = , `optional7` = , `optional8` = , `optional9` = , `remarks1` = 316340, `remarks2` = , `remarks3` = , `remarks4` = YWY3OTAzYzNlM2ExZTJlOdjuLnfS78RXTDsN1fnMZcU=, `remarks5` = 3991805, `remarks6` = 431501, `remarks7` = 64a43d40-642e-4fa1-84d1-3f7034aa34c2, `remarks8` = , `remarks9` = , `remarks10` = , `remarks11` = , `remarks12` = , `remarks13` = , `remarks14` = , `remarks15` = LARAVEL where `ipay_id` = P240315080011LZNVJ)

触发代码逻辑

try {
    DB::connection($db . '__write')->beginTransaction();

    $transaction = DB::connection($db . '__write')->table($table)->where('ipay_id', $validatedData['ipayId']);
    $transaction->update($data);

    DB::connection($db . '__write')->commit();
} catch (\Exception $e) {
    return \Ipay::response([
        'statusCode' => 'ISE',
        'internalCode' => $e->getMessage(),
        'internalCodeAppend' => '#UTU1',
    ]);
}

现有困惑

本地环境完整复现操作,甚至1秒内执行10次脚本都未出现死锁,但生产环境触发该错误。目前仅能拿到上述错误信息,无法确定死锁是由该更新查询导致,还是存在其他关联操作影响。

求助需求

需要死锁根源追踪、排查的实用思路与方法,以及分析死锁发生前相关查询序列的有效手段。可提供脚本执行的所有查询序列作为补充上下文。


排查思路参考

  • 提取生产环境死锁日志
    执行SHOW ENGINE INNODB STATUS;,查看输出中LATEST DETECTED DEADLOCK部分,这里会明确死锁涉及的事务、锁类型、关联行与索引信息,是定位核心依据。若生产开启了通用日志或慢查询日志,可筛选死锁时间点前后的SQL,排查是否有其他事务在操作同一张表的相关数据。
  • 检查索引与锁范围
    确认pre_txns_2403表的ipay_id字段是否有有效索引:无索引会导致UPDATE触发全表扫描,加大量行锁甚至表锁,大幅提升死锁概率;有索引的话,用EXPLAIN分析该UPDATE语句,确认索引是否被正确使用。同时排查是否有其他事务操作该表时,因索引使用问题导致锁范围扩大引发冲突。
  • 模拟生产级并发场景
    本地复现失败大概率是并发量、数据库配置(如事务隔离级别、innodb_lock_wait_timeout)与生产不一致:调整本地数据库配置匹配生产,用并发测试工具(如JMeter、自定义多线程脚本)模拟更高并发量,同时加入生产中可能存在的关联操作(如同一表的其他更新、关联表的读写),尝试复现死锁。
  • 梳理完整事务执行链路
    整理生产中该业务的全流程事务序列,排查是否存在交叉锁等待场景:比如事务A先通过SELECT ... FOR UPDATE锁定目标行,再执行其他耗时操作;事务B同时发起UPDATE请求等待锁,若此时事务A又尝试获取其他资源锁,就可能形成死锁。

内容的提问来源于stack exchange,提问作者Rohannn Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 11:02:46