帮你快速理解、总结文档立即下载

应用死锁

最近更新时间:2026-08-18 19:12:03
我的收藏

现象描述

TDSQL Boundless 实例在运行过程中,业务侧出现死锁报错,可能伴随以下现象:
应用程序日志中出现死锁错误,错误码为 1213ER_LOCK_DEADLOCK)。
应用程序日志中出现锁等待超时错误,错误码为 1205ER_LOCK_WAIT_TIMEOUT)。
实例监控中 SQL 失败数指标升高,死锁次数不为零。
高并发场景下,部分事务被自动回滚并提示 Deadlock found when trying to get lock。
您可通过以下方式发现和确认死锁:
在 TDSQL Boundless 控制台的实例详情 > 监控告警 > 指标监控页面查看 SQL 失败数、汇总活跃线程数、死锁次数、行锁等待次数等指标,判断死锁发生频率和时间点。
数据库智能管家 DBbrain诊断优化 > 异常诊断页面查看死锁诊断事件,获取现场描述、智能分析和优化建议。

可能原因

死锁通常由多个事务相互持有对方需要的锁资源,形成等待环导致。可能原因如下:
序号
可能原因
1
多个事务以不同顺序访问相同的表或行,形成锁等待环。
2
事务中执行时间过长,持有锁的时间过长,增加死锁概率。
3
并发量突增,锁竞争加剧,短时间内大量事务争抢同一批资源。
4
死锁检测未开启或锁等待超时设置不合理,导致死锁无法被及时检测和解除。

解决思路

针对不同原因,解决思路如下:
可能原因
解决思路
事务访问顺序不一致
统一事务中表的访问顺序,确保并发事务按相同顺序加锁。
事务执行时间过长
拆分大事务为小事务,减少单事务持锁时间;优化事务内 SQL 执行效率。
并发量突增
业务侧进行限流或错峰执行,降低并发争抢强度。
死锁检测未开启
通过控制台开启死锁检测,并合理设置锁等待超时时间。

处理步骤

步骤1:查看监控指标

1. 登录 TDSQL Boundless 控制台,在实例列表中单击目标实例 ID,进入实例详情页。
2. 选择监控告警 > 指标监控页签,查看以下指标的变化趋势:
监控指标
说明
关注点
SQL 失败数
每秒失败的 SQL 数量
死锁发生时,失败数会突增
汇总活跃线程数
当前活跃线程数
并发量是否突增
慢查询数
每秒慢查询数量
锁等待是否导致查询变慢
CPU 利用率
实例 CPU 使用率
锁竞争是否导致 CPU 升高
死锁次数
每秒死锁发生次数,直接反映死锁频率
死锁次数是否持续不为零
行锁等待次数
每秒行锁等待次数,反映锁竞争强度
锁等待次数是否突增
行锁等待超时次数
每秒行锁等待超时次数,反映锁超时是否频繁
锁超时是否频繁出现
平均行锁等待时间
行锁平均等待耗时(毫秒),反映锁等待是否过长
等待时间是否持续偏高
当前长事务个数
当前长事务数量,是否存在持有锁时间过长的事务
长事务是否长时间持有锁
跨节点事务 TPS
每秒跨节点事务数,跨分片事务更易引发死锁
跨节点事务是否频繁
重点关注 SQL 失败数突增的时间点,与业务并发高峰或批量任务执行时间是否吻合。同时关注死锁次数行锁等待次数是否同步上升,若死锁次数持续不为零,说明存在频繁死锁;若当前长事务个数偏高,可能存在事务持有锁时间过长导致死锁。
3. 如需进行多指标关联分析,可登录 DBbrain 控制台,进入诊断优化 > 性能趋势页面,使用图表联动功能查看 CPU、内存、磁盘、QPS、慢查询等关键性能指标的时间序列曲线。若 CPU 利用率飙升但 QPS 未明显增长,且慢查询数同步上升,可能是锁竞争导致事务空转等待锁资源。详细操作请参见 性能趋势

步骤2:查看死锁信息

通过数据库智能管家 DBbrain 的异常诊断功能查看死锁事件详情,获取死锁快照、锁等待关系和智能分析建议,详细操作请参见 异常诊断
1. 登录 DBbrain 控制台,在左侧导航栏选择诊断优化
2. 在页面顶部选择数据库类型为 TDSQL Boundless,并选择目标实例 ID
3. 单击异常诊断页签,在页面右侧选择查看实时历史诊断信息。
4. 在诊断提示列表中,单击对应事件行进入详情。
死锁诊断事件的风险等级固定为致命。事件详情包含以下四个模块:
模块
排查要点
事件详情
确认风险等级为"致命",记录起止时间,用于后续与监控指标关联分析。
现场描述
被回滚的事务 ID:系统自动选择回滚的事务,通常是写数据量较少或较晚开启的事务。
requesting_sql:触发死锁的具体 SQL 语句,是定位问题根因的关键。
req_lock_range / blk_lock_range:等待方和阻塞方分别持有或等待的锁范围,帮助判断锁冲突的具体资源。
智能分析
系统对死锁根因和影响范围的分析,确认是访问顺序不一致、长事务还是并发突增导致。
优化建议
针对死锁场景给出的处理建议,据此确定后续处理方向(Kill 会话、调参数、优化 SQL)。

5. 切换到智能分析页签,根据系统给出的分析结论和建议,确定后续处理方向。

步骤3:查看锁等待会话

若死锁频繁发生且存在持续锁等待,可通过 DBbrain 的实时会话功能查看当前锁等待情况并终止异常会话,详细操作请参见 实时会话
1. 在 DBbrain 控制台的诊断优化页面,单击实时会话页签。
2. 活跃会话列表中,查看当前活跃会话的来源、执行时间和状态,重点关注以下信息:
STATE 字段为 Locked 的会话:该会话正处于锁等待状态,是锁竞争的直接表现。
TIME 值较大的会话:可能正在等待锁资源,导致其他事务被阻塞。
INFO 字段:会话正在执行的 SQL 语句,帮助定位是哪个业务操作引发的锁等待。
USER 和 HOST 字段:帮助定位是哪个业务或客户端发起的会话。
3. 若发现长时间锁等待的异常会话,按以下步骤终止该会话以释放锁资源:
3.1 在活跃会话列表中,勾选待终止的会话。
3.2 单击列表右上方的 Kill 会话
3.3 在弹出的确认对话框中,单击确定
注意:
Kill 会话会立即终止目标会话正在执行的 SQL 与事务,未提交的事务将回滚,可能导致业务侧请求报错。请仅在确认目标会话确为异常会话后再执行该操作。终止会话需要当前账号具备实例的会话管理权限
4. 终止会话后,可在列表上方单击 Kill 历史记录,查看已终止的会话记录。

步骤4:开启死锁检测

若死锁检测未开启,建议通过控制台开启,使系统自动检测并解除死锁。
1. 登录 TDSQL Boundless 控制台,在实例列表中单击目标实例 ID,进入实例详情页。
2. 选择参数设置 > 数据库参数页签,查找以下参数:
参数名
说明
默认值
tdstore_deadlock_detect
是否开启死锁检测。开启后系统会自动检测死锁环并回滚其中一个事务。
OFF
tdstore_deadlock_victim
死锁发生时选择牺牲事务的策略。WRITE_LEAST 优先回滚写数据量较少的事务;START_LATEST 优先回滚较晚开启的事务。
WRITE_LEAST
3. tdstore_deadlock_detect 的值修改为 ON,开启死锁检测。
4. 根据业务场景设置 tdstore_deadlock_victim 的值:
WRITE_LEAST:优先保护写数据量大的事务,适合以数据写入为主的场景。
START_LATEST:优先保护先开启的事务,适合事务执行顺序明确的场景。
5. 在目标参数所在行的参数当前值列,单击修改参数值,单击保存,在确认对话框中单击确定
注意:
开启死锁检测会带来少量的性能开销,但在死锁频发的场景下,开启检测可以避免事务长时间阻塞,整体收益大于开销。

步骤5:调整锁等待超时时间

若锁等待超时时间设置不合理(过长或过短),可通过控制台调整 tdsql_lock_wait_timeout 参数。
1. 参数设置 > 数据库参数页签,查找 tdsql_lock_wait_timeout 参数。
2. 根据业务场景调整参数值:
默认值为10秒。若业务事务执行时间较长,可适当调大,避免正常事务因锁等待被误杀。
若希望死锁和锁等待尽快被解除,可适当调小,减少业务阻塞时间。
3. 在目标参数所在行的参数当前值列,单击修改参数值,单击保存,在确认对话框中单击确定

步骤6:优化业务事务

从业务层面优化事务设计,从根本上减少死锁发生概率。
1. 统一访问顺序:确保所有并发事务以相同的顺序访问表和行。例如,事务 A 和事务 B 都先更新表1再更新表2,避免交叉等待。
2. 缩短事务范围
将大事务拆分为多个小事务,减少单事务持锁时间。
事务中避免包含耗时操作(如远程调用、文件 IO),尽快提交事务。
使用 SELECT ... FOR UPDATE 时,尽量只锁定需要的行,避免锁定过多资源。
3. 降低并发强度
对高并发写入场景进行限流,控制同时执行的事务数量。
批量操作分批执行,避免单批次操作锁定大量资源。
将非核心业务的写入操作错峰执行。
4. 使用合适的索引
确保更新和删除操作使用索引定位行,避免全表扫描加锁。
无索引的更新操作会锁定大量行,大幅增加死锁概率。

步骤7:通过 DBbrain 分析慢 SQL

锁竞争往往与低效 SQL 有关,优化 SQL 可以减少锁持有时间。推荐使用 DBbrain 的慢 SQL 分析功能定位锁等待热点 SQL 并进行优化。
1. 在 DBbrain 控制台的诊断优化页面,单击慢 SQL 分析页签。
2. 选择时间范围,在 SQL 列表中单击最大锁等待时间列,按降序排列,优先找到锁等待最严重的 SQL 模板。也可按总耗时平均执行时间降序排列,综合判断低效 SQL。
3. 单击某条聚合的慢 SQL,在右侧弹出的面板中查看执行计划、优化建议和执行耗时分布,详细操作请参见 慢 SQL 分析
4. 重点关注以下信息:
最大锁等待时间平均锁等待时间:锁等待时间较长的 SQL 是锁竞争的热点,优先优化。
最大扫描行数:扫描行数过多说明 SQL 未走索引或索引不合适,会锁定大量行,需添加索引。
执行计划中 type 列为 ALL 表示全表扫描,需添加索引;rows 列值过大说明扫描行数过多,锁定的行也越多。
5. 根据执行计划和优化建议,进行以下优化:
WHERE 条件列添加索引,减少扫描和锁定行数。
避免在没有索引的列上执行 UPDATEDELETE
使用 LIMIT 限制单次操作影响的行数。
6. 优化后回到慢 SQL 分析页面,对比优化前后的最大锁等待时间总耗时变化,验证优化效果。

预防措施

为避免死锁问题反复发生,建议采取以下预防措施:
开启死锁检测:确保 tdstore_deadlock_detect 参数设置为 ON,使系统自动检测并解除死锁。
配置告警策略:在控制台为 SQL 失败数、死锁次数、行锁等待次数等指标配置告警,及时发现死锁问题。
关注 DBbrain 异常诊断:定期查看 DBbrain 异常诊断页面的死锁诊断事件,根据智能分析和优化建议及时处理潜在风险。
定期巡检慢 SQL:通过 DBbrain 慢 SQL 分析页面定期检查慢 SQL 模板,重点关注最大锁等待时间较高的 SQL,优化低效查询以减少锁持有时间。
监控实时会话锁等待:在业务高峰期通过 DBbrain 实时会话页面关注 STATE 为 Locked 的会话数量,若锁等待会话持续增多,及时排查是否存在事务持有锁时间过长。
规范事务设计:制定事务开发规范,统一表访问顺序,控制事务大小和持锁时间。
监控 SQL 失败数:定期关注控制台监控面板中的 SQL 失败数指标,若出现突增,及时排查是否存在死锁或锁等待问题。

相关文档

您还可以通过 information_schema.PROCESSLIST 查看当前会话锁等待情况。