RDS MySQL支持非阻塞DDL(Non blocking DDL)功能,规避了DDL执行过程中因MDL锁长时间获取不成功导致的会话阻塞和连接堆积,提升DDL过程中实例的稳定性和可用性。
功能说明
背景:在MySQL中,DDL操作需要获取目标表的MDL-X锁,以确保元数据一致性。然而,当表上存在未提交事务或长查询时,DDL线程会因无法立即获取锁而进入等待状态(pending)。由于MDL-X锁具有最高优先级,pending状态下的MDL-X锁会阻塞目标表后续的所有访问,引发会话阻塞、连接堆积和响应延迟等问题,严重时可能导致整个业务系统不可用。
简介:RDS MySQL的非阻塞DDL通过修改DDL线程获取和等待MDL锁的策略,将“一次性长等待”改为“间歇性短等待”。在等待间歇中,DDL线程会释放对MDL-X的请求,新会话允许访问目标表,避免了DDL线程长时间阻塞其他会话对目标表的访问。
适用范围
数据库版本需满足以下要求才能开启非阻塞DDL功能,当版本不符合要求时,可以升级升级内核小版本或数据库大版本:
MySQL 8.4
MySQL 8.0且内核小版本大于等于20250531
使用非阻塞DDL功能时,有以下限制:
当前仅支持
ALTER TABLE、CREATE INDEX和DROP INDEX操作。OPTIMIZE TABLE操作可以使用ALTER TABLE ... ENGINE = InnoDB代替。主节点同步至备节点或只读实例时,备节点或只读实例上本功能不生效。
开启本功能会降低DDL的优先级,因此无法获取MDL锁导致DDL失败的概率会增大。
参数管理
参数说明
您可以通过loose_rds_nonblock_ddl_retry_interval和loose_rds_nonblock_ddl_lock_wait_timeout参数来控制和调整非阻塞DDL功能。开启非阻塞DDL功能后,DDL线程会间歇性多次尝试获取MDL锁,获取失败则释放MDL请求并陷入等待。
参数名称 | 说明 |
|
|
|
|
修改参数
访问RDS实例列表,在上方选择地域,然后单击目标实例ID。
在左侧导航栏中单击参数设置。
在可修改参数页签内搜索待修改参数,并配置参数值。
单击确定,然后单击提交参数,并在弹出的窗口中选择生效的时间段。
功能效果
测试方法
本文采用sysbench工具模拟数据库实例上的数据访问,对比开启与关闭非阻塞DDL功能时,执行DDL对业务的影响。具体测试步骤如下:
使用sysbench构建表并插入数据。
sysbench oltp_read_write --db-ps-mode=auto --percentile=95 --mysql-host=$HOST --mysql-port=$PORT --mysql-user=$USER --mysql-db=$DB --tables=1 --table-size=50 --threads=16 prepare
启动sysbench压力测试模拟在线业务。
sysbench oltp_read_write --db-ps-mode=auto --percentile=95 --mysql-host=$HOST --mysql-port=$PORT --mysql-user=$USER --mysql-db=$DB --tables=1 --table-size=50 --threads=16 --report-interval=1 --time=100 run
启动一个会话,在待执行的目标表上开启长事务,以阻塞后续的 DDL 操作。
SELECT SLEEP(60) FROM sbtest1 LIMIT 1;
启动另一个会话,在关闭非阻塞DDL功能的情况下执行如下DDL操作,观察TPS变化。
ALTER TABLE sbtest1 ENGINE = InnoDB; -- 预期:该DDL线程由于无法获取MDL锁被阻塞。
开启非阻塞DDL功能:设置
loose_rds_nonblock_ddl_retry_interval参数值为 6,loose_rds_nonblock_ddl_lock_wait_timeout参数值为1。执行相同的DDL操作,观察TPS变化。ALTER TABLE sbtest1 ENGINE = InnoDB; -- 预期:该DDL线程可以获取MDL锁,不会完全被阻塞
测试结果
关闭非阻塞DDL功能时,DDL线程无法获取MDL锁,会话被完全阻塞。
开启非阻塞DDL功能后,DDL线程可以间歇性地获取MDL锁,会话不会被完全阻塞,系统稳定性得到保障。

