美文网首页
MySQL:5.7中delete长期处于preparing状态简

MySQL:5.7中delete长期处于preparing状态简

作者: 重庆八怪 | 来源:发表于2022-01-24 16:33 被阅读0次

    一、问题展示

    实际这里是是一个delete in语句。

    mysql> show processlist;
    +----+------+-----------+------+---------+------+-----------+-----------------------------------------------------------------------------+-----------+---------------+
    | Id | User | Host      | db   | Command | Time | State     | Info                                                                        | Rows_sent | Rows_examined |
    +----+------+-----------+------+---------+------+-----------+-----------------------------------------------------------------------------+-----------+---------------+
    |  2 | root | localhost | ttt  | Query   |   14 | preparing | delete from testout2 where id not in(select id from testin2 where name='t') |         0 |         37151 |
    |  7 | root | localhost | NULL | Query   |    0 | starting  | show processlist                                                            |         0 |             0 |
    +----+------+-----------+------+---------+------+-----------+-----------------------------------------------------------------------------+-----------+---------------+
    2 rows in set (0.00 sec)
    
    mysql> show processlist;
    +----+------+-----------+------+---------+------+-----------+-----------------------------------------------------------------------------+-----------+---------------+
    | Id | User | Host      | db   | Command | Time | State     | Info                                                                        | Rows_sent | Rows_examined |
    +----+------+-----------+------+---------+------+-----------+-----------------------------------------------------------------------------+-----------+---------------+
    |  2 | root | localhost | ttt  | Query   |   15 | preparing | delete from testout2 where id not in(select id from testin2 where name='t') |         0 |         37744 |
    |  7 | root | localhost | NULL | Query   |    0 | starting  | show processlist                                                            |         0 |             0 |
    +----+------+-----------+------+---------+------+-----------+-----------------------------------------------------------------------------+-----------+---------------+
    2 rows in set (0.01 sec)
    
    

    大概就是这样一个语句,处于preparing 状态,问delete为什么会处于这个状态?

    二、简析

    对于preparing状态一般归结为优化阶段,并还没有进入实际的语句执行阶段。但是这里有所不同。并且我们知道一般delete执行慢一般状态会处于,

    • updating
    • 子查询的sending data中

    但是这里是preparing状态。那么为什么会处于这种状态呢?简单分析一下。

    我们知道5.7的delete in实际上还是用的DEPENDENT SUBQUERY。这个类似exists的操作,都会用外层查询驱动内层。稍微跟了一下5.7的delete in(不做详细研究),发现所有的query block并没有完全完成优化,实际上这种子查询会在调用Item_subselect::exec的时候通过

    • if (!unit->is_optimized() && unit->optimize(thd))

    进行判断,如果unit->is_optimized()判断为false,则会调入unit->optimize(thd),对subquery的query block进行优化,而优化结束后查询的状态会被设置为preparing。也就出现了这种现象,如下:

    T@2: | | | | | THD::enter_stage: 'init' /opt/percona-server-locks-detail-5.7.22/sql/sql_delete.cc:79
    T@2: | | | | | | | THD::enter_stage: 'System lock' /opt/percona-server-locks-detail-5.7.22/sql/lock.cc:323
    T@2: | | | | | THD::enter_stage: 'updating' /opt/percona-server-locks-detail-5.7.22/sql/sql_delete.cc:425
    T@2: | | | | | | | | | | THD::enter_stage: 'optimizing' /opt/percona-server-locks-detail-5.7.22/sql/sql_optimizer.cc:151
    T@2: | | | | | | | | | | THD::enter_stage: 'statistics' /opt/percona-server-locks-detail-5.7.22/sql/sql_optimizer.cc:386
    T@2: | | | | | | | | | | THD::enter_stage: 'preparing' /opt/percona-server-locks-detail-5.7.22/sql/sql_optimizer.cc:494
    T@2: | | | | | THD::enter_stage: 'end' /opt/percona-server-locks-detail-5.7.22/sql/sql_delete.cc:538
    
    Item_in_subselect::val_bool
      ->st_select_lex_unit::optimize
        ->st_select_lex::optimize
          ->JOIN::optimize
            ->THD::enter_stage(stage_preparing)
    
    

    这种现象当前看起来是5.7(5.7以下没有测试)中DML语句带in/not in常见的,也可以归结为状态转换稍微考虑欠妥,可能开发大佬也没意识到这个状态已经变为DBA诊断问题的一个主要手段。
    而到了8.0状态已经更加精细,有了一些细微的变化,而且8.0.21后支持DML 中的in使用semi join(not in还不行,但是状态是executing)优化。所以我们简单的将其归结为正在执行类似sending data状态即可。需要优化的是将这种delete改写为联合delete形式。

    相关文章

      网友评论

          本文标题:MySQL:5.7中delete长期处于preparing状态简

          本文链接:https://www.haomeiwen.com/subject/orbbhrtx.html