DDL锁等待超时控制

RDS MySQL支持DDL锁等待超时控制功能,其基于HINT灵活控制DDL线程等待MDL锁的超时时间,避免因长时间等待MDL锁导致的会话阻塞和连接堆积。

功能说明

简介:MySQL中使用lock_wait_timeout参数来控制MDL超时时间,对于需要精确控制等待行为的DDL操作,用户必须在执行前显式修改该参数。RDS MySQL基于HINT提供了一种更简单、直观的方式来控制DDL语句的MDL锁等待时间,支持通过/*+ WAIT(n) *//*+ NO_WAIT() */直接在语句中指定MDL锁等待时间。

优势:相比引入新语法,使用HINT具有更好的兼容性。HINT以注释形式写入Binlog,在不支持该特性的下游实例或订阅服务中,会被解析器自动忽略,视为普通注释,不会导致SQL解析错误或复制中断。

适用范围

  • 仅当数据库大版本为MySQL 8.0且内核小版本大于等于20250531时,才能使用DDL锁等待超时控制功能。当版本不符合要求时,可以升级升级内核小版本数据库大版本

  • 使用该功能时有以下限制:

    • 仅支持CREATEDROPALTERRENAMETRUNCATEOPTIMIZE操作。

    • 主节点同步至备节点或只读实例时,备节点或只读实例上本功能不生效。

    • 设置MDL等待时间(/*+ WAIT(n) */)时,n(等待时间)的取值范围为[0, 31536000],单位:秒。

使用方法

在执行CREATEDROPALTERRENAMETRUNCATEOPTIMIZE操作时,您只需在上述关键字后添加/*+ WAIT(n) *//*+ NO_WAIT() */,即可实现 MDL 锁等待时间的控制。使用示例如下:

-- 创建表t1并设置MDL超时时间为10s。
CREATE /*+ WAIT(10) */ TABLE t1(a INT);

-- 为表t1添加列并设置MDL超时不等待。
ALTER /*+ NO_WAIT() */ TABLE t1 ADD COLUMN b INT;

-- 删除表 t1 添加列并设置 MDL 超时时间为 1s
DROP /*+ WAIT(1) */ TABLE t1;

功能效果

测试方法

  1. 开启一个会话,创建表t1并持有表MDL S锁。

    CREATE TABLE t1(a INT);
    LOCK TABLE t1 READ;
  2. 开启另一个会话,使用/*+ WAIT(n) */ /*+ NO_WAIT() */执行表结构变更和删除操作,观察语句执行情况。

    ALTER /*+ NO_WAIT() */ TABLE t1 ADD COLUMN b INT;
    DROP /*+ WAIT(1) */ TABLE t1;

测试结果

使用/*+ WAIT(n) *//*+ NO_WAIT() */方式控制 MDL 超时时间之后,表结构变更和删除操作会在预期的时间内快速失败。

mysql> ALTER /*+ NO_WAIT() */ TABLE t1 ADD COLUMN b INT;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> DROP /*+ WAIT(1) */ TABLE t1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction