MySQL:8028新加入的LOCK INSTANCE报错

2024-04-14  本文已影响0人  重庆八怪

最近在进行purge binary logs的时候遇到一个错误如下,

当然这个错误提示非常明显,就是在某个session执行了LOCK INSTANCE FOR BACKUP的情况下,不允许进行purge binary logs 命令,但是这个错误视乎没有遇到过,是不是8028新加入的报错呢?

一、什么是LOCK INSTANCE FOR BACKUP

在文章<<MySQL:8.0新的备份锁的浅析及其在xtrbackup的应用>>一文中我们详细描述过他的作用,以及其实现方式,如下。
这个操作主要堵塞的是DDL操作,包含不限于如下一些常见的操作:

CREATE_TABLE、CREATE_INDEX、ALTER_TABLE、TRUNCATE、DROP_TABLE、LOAD、CREATE_DB
、DROP_DB、ALTER_DB、RENAME_TABLE、DROP_INDEX、CREATE_VIEW、DROP_VIEW、CREATE_TRIGGER、DROP_TRIGGER、CREATE_EVENT、ALTER_EVENT、DROP_EVENT、IMPORT、RENAME_USER、DROP_USER、ALTER_USER、GRANT、REVOKE、GRANT_ROLE、REVOKE_ROLE、DROP_ROLE、CREATE_ROLE、OPTIMIZE、CREATE_FUNCTION、CREATE_PROCEDURE、DROP_PROCEDUR、DROP_FUNCTION、ALTER_PROCEDURE、ALTER_FUNCTION、REPAIR、ANALYZE、ALTER_TABLESPACE

我也随意测试了一些操作,确实都会被堵塞。从内部来看,实际上这个操作的功效依然是通过MDL LOCK的实现的,其策略为m_scoped_lock_strategy,那么从scoped策略的兼容性来看,如下:


image.png

对于lock instance for backup本生而言实际上是做了的如下操作:

Sql_cmd_lock_instance::execute
 ->acquire_exclusive_backup_lock
  ->acquire_mdl_for_backup
获取的MDL LOCK为 MDL_key::BACKUP_LOCK+MDL_SHARED(S)

并且看起来 MDL_key::BACKUP_LOCK的锁类型只会是MDL_SHARED(S)或者MDL_INTENTION_EXCLUSIVE(IX),因为acquire_mdl_for_backup里有断言:

 DBUG_ASSERT(mdl_type == MDL_SHARED || mdl_type == MDL_INTENTION_EXCLUSIVE);

对于上面提到的会被堵塞的这些操作,则是在响应的地方加入了获取 MDL_key::BACKUP_LOCK+MDL_INTENTION_EXCLUSIVE(IX)
根据兼容矩阵,S和IX并不兼容,但是IX和IX之间是兼容的,因此只要不执行lock instance for backup操作,则不会有任何影响。而对于用户而言会发现processlist出现Waiting for backup lock字样则为这样的堵塞。测试如下:

mysql> show processlist;
+----+------+-----------+---------+---------+------+-------------------------+-------------------+
| Id | User | Host      | db      | Command | Time | State                   | Info              |
+----+------+-----------+---------+---------+------+-------------------------+-------------------+
| 11 | root | localhost | testpri | Query   |    4 | Waiting for backup lock | OPTIMIZE table t1 |
| 12 | root | localhost | t10     | Sleep   |  175 |                         | NULL              |
| 13 | root | localhost | testpri | Query   |    0 | init                    | show processlist  |

当然既然是MDL LOCK,它同样受到参数lock_wait_timeout参数的影响。比如我这里的操作为OPTIMIZE如下:

mysql> OPTIMIZE table t1;
+------------+----------+----------+--------------------------------------------------------+
| Table      | Op       | Msg_type | Msg_text                                               |
+------------+----------+----------+--------------------------------------------------------+
| testpri.t1 | optimize | Error    | Lock wait timeout exceeded; try restarting transaction |
| testpri.t1 | optimize | status   | Operation failed                                       |
+------------+----------+----------+--------------------------------------------------------+
2 rows in set (2 min 0.01 sec)

需要的注意的这个锁并不会堵塞任何DML和SELECT操作(即便是mysiam表也不会堵塞DML操作),但是保护了元数据的正确性。如果要获取的一致的数据我们就需要额外的机制也就是下面谈到的ps.log_status。

二、常用场景

关于LOCK INSTANCE FOR BACKUP的常用场景大概有2个地方,如下,

    /* Acquire backup lock */
    if (block_ddl()) {
      auto failed = mysql_service_mysql_backup_lock->acquire(
          thd, BACKUP_LOCK_SERVICE_DEFAULT, m_client_ddl_timeout);

这里可以看到就是lock instance的调用
mysql_acquire_backup_lock
  ->acquire_exclusive_backup_lock
     ->acquire_mdl_for_backup
       ->MDL_context::acquire_lock

三、新的报错

而如前文所言,在8.0.28中为了防止在lock instance for backup下能够修改文件,因此把清理binlog也加入其中,所以有了新的报错,引入这个错误的BUG修复如下,


161e35f45f4478b7e5e4c51b3204b9d.png

也就是修复这个BUG引入的新的报错,主要增加的判定函数就是,


image.png

以上。。。

上一篇 下一篇

猜你喜欢

热点阅读