tencent cloud

TDSQL Boundless

应用死锁

Download
聚焦模式
字号
最后更新时间: 2026-07-17 16:33:34

现象描述

TDSQL Boundless 实例在运行过程中,业务侧出现死锁报错,可能伴随以下现象:
应用程序日志中出现死锁错误,错误码为 1213ER_LOCK_DEADLOCK)。
应用程序日志中出现锁等待超时错误,错误码为 1205ER_LOCK_WAIT_TIMEOUT)。
实例监控中 SQL 失败数指标升高。
高并发场景下,部分事务被自动回滚并提示 Deadlock found when trying to get lock。
您可在 TDSQL Boundless 控制台的实例详情 > 监控告警 > 指标监控页面查看 SQL 失败数、活跃线程数等指标,判断死锁发生频率和时间点。

可能原因

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

解决思路

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

处理步骤

步骤1:查看监控指标

1. 登录 TDSQL Boundless 控制台,在实例列表中单击目标实例 ID,进入实例详情页。
2. 选择监控告警 > 指标监控页签,查看以下指标的变化趋势:
监控指标
说明
关注点
SQL 失败数
每秒失败的 SQL 数量
死锁发生时,失败数会突增
活跃线程数
当前活跃线程数
并发量是否突增
慢查询数
每秒慢查询数量
锁等待是否导致查询变慢
CPU 利用率
实例 CPU 使用率
锁竞争是否导致 CPU 升高
重点关注 SQL 失败数突增的时间点,与业务并发高峰或批量任务执行时间是否吻合。

步骤2:查看死锁信息

通过系统视图查看死锁记录,分析死锁发生的事务和锁等待关系。
1. 连接数据库实例,执行以下 SQL 查看死锁记录。
SELECT
rollback_trans_id,
cycle_transactions,
occurred_at
FROM information_schema.TDSTORE_PESSIMISTIC_DEADLOCK_INFO
ORDER BY occurred_at DESC
LIMIT 20;
该视图展示最近发生的死锁信息,字段说明如下:
rollback_trans_id:被回滚的事务 ID。
cycle_transactions:构成死锁环的事务列表。
occurred_at:死锁发生时间。
2. 如需查看死锁详情,执行以下 SQL 查看死锁的锁等待详情。
SELECT
rollback_trans_id,
requesting_node,
requesting_trans_id,
blocking_trans_id,
req_lock_range,
blk_lock_range,
occurred_at,
requesting_sql
FROM information_schema.TDSTORE_PESSIMISTIC_DEADLOCK_DETAIL_INFO
ORDER BY occurred_at DESC
LIMIT 20
该视图展示死锁发生时的锁等待关系,帮助您定位冲突的具体资源和事务。

步骤3:查看当前锁等待会话

若死锁正在发生或存在长时间锁等待,查看当前会话的锁等待情况。
1. 执行以下 SQL 查看当前正在执行的会话,重点关注 TIME 值较大的会话,这些会话可能正在等待锁资源。
SELECT
ID,
USER,
HOST,
DB,
COMMAND,
TIME,
STATE,
INFO
FROM information_schema.PROCESSLIST
WHERE COMMAND != 'Sleep'
ORDER BY TIME DESC
LIMIT 20
2. 若发现长时间锁等待的会话,可使用 KILL 命令终止该会话以释放锁资源。
KILL <会话ID>;
警告:
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:优化 SQL 语句

锁竞争往往与低效 SQL 有关,优化 SQL 可以减少锁持有时间。
1. 对涉及锁竞争的 SQL 执行 EXPLAIN 查看执行计划。
EXPLAIN UPDATE table_name SET ... WHERE ...;
2. 重点关注以下信息:
type 列为 ALL 表示全表扫描,会锁定大量行,需要添加索引。
rows 列值过大说明扫描行数过多,锁定的行也越多。
3. 优化建议:
WHERE 条件列添加索引,减少扫描和锁定行数。
避免在没有索引的列上执行 UPDATEDELETE
使用 LIMIT 限制单次操作影响的行数。

预防措施

为避免死锁问题反复发生,建议采取以下预防措施:
开启死锁检测:确保 tdstore_deadlock_detect 参数设置为 ON,使系统自动检测并解除死锁。
配置告警策略:在控制台为 SQL 失败数指标配置告警,及时发现死锁问题。
规范事务设计:制定事务开发规范,统一表访问顺序,控制事务大小和持锁时间。
定期巡检慢 SQL:通过 DBbrain 智能诊断定期检查慢 SQL,优化低效查询以减少锁持有时间。
监控 SQL 失败数:定期关注控制台监控面板中的 SQL 失败数指标,若出现突增,及时排查是否存在死锁或锁等待问题。

帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈