tencent cloud

TDSQL Boundless

产品动态
产品简介
产品概述
应用场景
产品架构
实例类型
兼容性说明
使用规范建议
自研内核
内核概述
内核版本更新动态
功能类特性
性能类特性
产品计费
计费概述
购买方式
价格详情
续费说明
欠费说明
退费说明
快速入门
创建实例
连接实例
用户指南
数据迁移
数据同步/订阅
实例管理
参数配置
账号管理
安全组
备份与恢复
数据库审计
标签管理
实践教程
Online DDL 的技术演进与使用实践
锁机制解析与问题排查实践
数据智能调度及相关性能优化实践
TDSQL Boundless 选型指南与实践教程
开发指南
开发指南(MySQL 兼容模式)
开发指南(HBase 兼容模式)
性能调优
性能调优概述
SQL 调优
DDL 调优
性能白皮书
性能概述
TPC-C 测试
Sysbench 测试
API 文档
History
Introduction
API Category
Making API Requests
Instance APIs
Security Group APIs
Task APIs
Backup APIs
Rollback APIs
Parameter APIs
Database APIs
Data Types
Error Codes
通用参考
系统原理
SQL 参考
数据库参数说明
TPC-H 基准测试数据模型参考
错误码信息
安全与合规
常见问题
服务协议
服务等级协议
服务条款
隐私政策
数据处理和安全协议
联系我们
词汇表

抢占式 DDL

PDF
聚焦模式
字号
最后更新时间: 2026-03-26 15:19:24

功能概述

TDSQL Boundless 提供抢占式 DDL 功能,用于解决分布式场景下, DDL 操作因其他节点上的长事务持有 MDL-S 锁而长时间等待甚至超时失败的问题。
开启抢占式 DDL 后,当 DDL 操作在目标节点等待 MDL-X 锁超过指定时间时,系统将主动终止阻塞 MDL-X 锁获取的会话,确保 DDL 操作能够顺利完成。

背景信息

TDSQL Boundless 分布式架构下的 DDL 锁协调

TDSQL Boundless 采用分布式架构,每个 SQLEngine 节点均具备独立的读写能力。当某个节点执行 DDL 操作时,需要在以下两个层面获取锁:
1. 本节点 MDL 锁: DDL 需要在发起节点获取目标表的 MDL-X 锁,与本节点上的活跃事务互斥。
2. 全局对象锁: DDL 需要通过元数据服务(TDMC)获取全局对象锁,确保同一时间只有一个节点能修改表结构,防止跨节点 DDL 冲突。

问题现象

在同一节点上,如果存在对目标表的长事务或大查询,这些会话会持有该表的 MDL-S 锁。DDL 操作需要获取 MDL-X 锁,两者互斥,导致 DDL 被阻塞。如果长事务在锁等待超时时间内未结束,DDL 将执行失败。
典型报错:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
在未开启抢占式 DDL 的情况下,处理此类问题通常需要 DBA 手动定位并终止持锁会话,操作流程繁琐且响应不及时。

抢占式 DDL 的解决思路

抢占式 DDL 提供了一种自动化的解决方案:当 DDL 等待 MDL 锁超过指定时间后,系统将自动终止阻塞 DDL 的会话,释放 MDL 锁资源,使 DDL 操作能够继续执行。相比手动干预,这种方式响应更快、操作更可靠。

注意事项

业务影响: 开启抢占式 DDL 后,阻塞 DDL 的会话将被系统强制终止,会话上未提交的事务将被回滚。请评估业务对事务中断的容忍度。
建议在低峰期使用: 尽管抢占式 DDL 能自动处理锁冲突,仍建议在业务低峰期执行 DDL 变更,以减少对正常业务的影响。

参数说明

通过以下参数控制抢占式 DDL 的行为,可在控制台的参数配置页面或通过 SQL 命令进行设置。
参数
级别
说明
取值范围
默认值
tdsql_ddl_block_mode
Session
控制普通线程(normal)DDL 锁获取行为,设置为 preemptive 时启用抢占式 DDL 逻辑
preemptive
nonblock
default
preemptive
tdsql_ddl_recovery_block_mode
Global
控制恢复线程(recovery)DDL 锁获取行为,设置为 preemptive 时启用抢占式 DDL 逻辑;仅 GLOBAL 级别设置生效,SESSION 级别设置无效
preemptive
nonblock
default
preemptive
tdsql_ddl_preempt_after_wait_seconds
Session
抢占式 DDL 等待 MDL‑X 锁的容忍时间,超过该时间后自动触发锁抢占流程。单位:秒
1 ~ 31536000
50

使用方法

1. 开启抢占式 DDL。
在执行 DDL 的会话中开启功能:
SET tdsql_ddl_block_mode = 'preemptive';
-- tdsql_ddl_block_mode参数的默认值即为 'preemptive'
2. (可选)调整抢占等待时间。
例如设置为5秒:
SET tdsql_ddl_preempt_after_wait_seconds = 5;
3. (可选)配置恢复线程抢占式 DDL。
SET GLOBAL tdsql_ddl_recovery_block_mode = 'preemptive';
4. 执行 DDL 操作。
ALTER TABLE orders ADD COLUMN remark VARCHAR(255);
如果当前节点上存在长事务阻塞了该表的 MDL 锁,系统将在等待指定时间后自动终止阻塞会话,DDL 继续执行直至完成。

使用示例

准备工作

创建测试表并插入数据:
CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(50));
INSERT INTO t1 VALUES (1, 'Alice'), (2, 'Bob');

未开启抢占式 DDL

会话1(模拟长事务):
BEGIN;
SELECT * FROM t1;
-- 事务未提交,持有 t1 的 MDL 共享读锁
会话2(执行 DDL):
ALTER TABLE t1 ADD COLUMN age INT;
-- 等待 MDL 排他锁...
-- 超时后报错:
-- ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
结果: DDL 执行失败,需要 DBA 手动通过 performance_schema.metadata_locks 定位持锁会话。

开启抢占式 DDL

会话1(模拟长事务):
BEGIN;
SELECT * FROM t1;
-- 事务未提交,持有 t1 的 MDL 共享读锁
会话2(开启抢占式 DDL 并执行):
SET tdsql_ddl_block_mode = 'preemptive';
SET tdsql_ddl_preempt_after_wait_seconds = 5;
ALTER TABLE t1 ADD COLUMN age INT;
-- 等待 5 秒后,系统自动触发抢占并终止阻塞会话
Query OK, 0 rows affected (5.067 sec)
Records: 0 Duplicates: 0 Warnings: 0
会话1的变化:
SELECT * FROM t1;
ERROR 2013 (HY000): Lost connection to MySQL server during query
结果: DDL 执行成功。会话1被终止,事务被回滚,后续操作需重新发起。

排查与诊断

当 DDL 操作遇到 MDL 锁阻塞时,您也可以通过以下方式手动排查,作为抢占式 DDL 的补充手段:
1. 查看 MDL 锁持有情况:
SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_NAME = 't1';
2. 定位持锁会话并参考 PROCESSLIST_ID 手动终止持锁会话:
SELECT
ml.OBJECT_NAME,
ml.LOCK_TYPE,
ml.LOCK_STATUS,
t.PROCESSLIST_ID,
t.PROCESSLIST_INFO
FROM performance_schema.metadata_locks ml
JOIN performance_schema.threads t
ON ml.OWNER_THREAD_ID = t.THREAD_ID
WHERE ml.OBJECT_NAME = 't1' AND ml.LOCK_STATUS = 'GRANTED';
说明:
在分布式场景下,如果 DDL 报错 ERROR 8542 ... Acquire object lock ... wait timeout,表明 DDL 被其他节点的 DDL 通过全局对象锁阻塞,此场景属于 DDL-DDL 冲突,需等待另一个 DDL 完成,抢占式 DDL 不适用于此场景。

相关文档

帮助和支持

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

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

文档反馈