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 Committed或Read 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阻塞问题。
操作步骤
- 登录PolarDB控制台。 
- 在左上角,选择集群所在地域。 
- 找到目标集群,单击集群ID。 
- 在左侧导航栏中选择。 
- 找到目标参数loose_polar_slave_work_on_nonblock_mdl_mode,单击修改参数。  
- 参数修改完成后,单击提交修改,在保存改动对话框中,单击确定。  
使用示例
开启polar_slave_work_on_nonblock_mdl_mode后,在只读节点上,同一事务将可能会看到不一样的表结构,如下:
- 首先,在只读节点上查询 - test.t:- mysql> begin; mysql> select * from test.t; +------+ | a | +------+ | 1 | +------+ 1 row in set (0.00 sec)
- 然后,在主节点上对 - 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
- 最后,再次在只读节点上查询 - 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。