防止只读节点上长事务阻塞DDL操作

PolarDB支持参数polar_slave_work_on_nonblock_mdl_mode。开启该参数后,可以防止PolarDB只读节点上的长事务阻塞主节点上的DDL操作。本文介绍如何为PolarDB开启该参数。

使用限制

PolarDB集群版本需满足如下条件之一:

  • PolarDB MySQL版8.0版本且修订版本为8.0.1.1.23或以上

  • PolarDB MySQL版5.7版本且修订版本为5.7.1.0.19或以上

  • PolarDB MySQL版5.6版本且修订版本为5.6.1.0.32或以上

说明

您可以通过查询版本号确认集群的内核版本。

仅当PolarDB只读节点事务隔离级别为Read CommittedRead Uncommitted时,polar_slave_work_on_nonblock_mdl_mode参数才有效。

polar_slave_work_on_nonblock_mdl_mode参数仅在PolarDB的只读节点生效。

背景信息

PolarDB只读节点上的长事务会一直持有访问过的数据表的元数据锁(MDL),它将导致PolarDB主节点上的DDL操作无法完成MDL同步,并最终超时,返回错误ERROR 8007 (HY000): Fail to get MDL on replica during DDL synchronize

说明

MDL同步过程的超时时间由参数replica_lock_wait_timeout控制,该参数值默认为50s。

当发生该问题时,在PolarDB主节点上执行命令show processlist,查询结果中State字段若提示Wait for syncing with replicas,您可以在PolarDB只读节点上执行命令select * from information_schema.innodb_log_mdl_slot where slot_state = "SLOT_ACQUIRING"查询处于等待状态的MDL信息。若该命令返回如下结果,则表明PolarDB只读节点上存在MDL等待问题。

+---------+----------------+-----------+----------+-----------+
| slot_id | slot_state     | slot_name | slot_lsn | thread_id |
+---------+----------------+-----------+----------+-----------+
|       0 | SLOT_ACQUIRING | test/t    | 35025648 | thread-0  |
+---------+----------------+-----------+----------+-----------+

注意事项

polar_slave_work_on_nonblock_mdl_mode只能解决长事务导致的DDL阻塞问题。开启polar_slave_work_on_nonblock_mdl_mode后,您仍将可能遇到大查询(即耗时超过MDL同步过程超时时间的查询)导致的MDL同步失败。

由于lock table和flush table获取的MDL需要显式通过unlock tables来释放,因此polar_slave_work_on_nonblock_mdl_mode无法解决lock table和flush table导致的MDL阻塞问题。

操作步骤

  1. 登录PolarDB控制台

  2. 在左上角,选择集群所在地域。

  3. 找到目标集群,单击集群ID。

  4. 在左侧导航栏中选择配置与管理 > 参数配置

  5. 找到目标参数loose_polar_slave_work_on_nonblock_mdl_mode,单击修改参数

    参数配置

  6. 参数修改完成后,单击提交修改,在保存改动对话框中,单击确定

    保存改动

使用示例

开启polar_slave_work_on_nonblock_mdl_mode后,在只读节点上,同一事务将可能会看到不一样的表结构,如下:

  1. 首先,在只读节点上查询test.t

    mysql> begin;
    mysql> select * from test.t;
    +------+
    | a    |
    +------+
    |    1 |
    +------+
    1 row in set (0.00 sec)
  2. 然后,在主节点上对test.t进行DDL操作:

    mysql> alter table test.t add column b int;
    Query OK, 0 rows affected (0.32 sec)
    Records: 0  Duplicates: 0  Warnings: 0
  3. 最后,再次在只读节点上查询test.t

    mysql> select * from test.t;
    +------+------+
    | a    | b    |
    +------+------+
    |    1 | NULL |
    +------+------+
    1 row in set (0.00 sec)

通过上述示例,可以看出在开启polar_slave_work_on_nonblock_mdl_mode的情况下,由于在主节点上进行了DDL操作,从而在只读节点上的同一个事务看到了不同的列数目。如果关闭polar_slave_work_on_nonblock_mdl_mode,在主节点上的DDL操作将持续等待只读节点上的事务,直至该事务被提交或等待超时(报错:ERROR 8007 (HY000): Fail to get MDL on replica during DDL synchronize)。

联系我们

若您对DDL操作有任何疑问,可通过钉钉搜索群号入群咨询。您可以直接@群内专家,并附上您要咨询的问题;同时群内也有PolarDB MySQL版小助手24*7小时在线回答您的问题。钉钉群号:15375044501。