当前位置: 首页 > news >正文

mysql-analyze table导致waiting for table flush

一、背景

一次普通的analyze table操作却锁住了后续的查询

mysql> select sleep(100) from a;

analyze table a;

mysql> select * from a;


# 遇到这种情况就需要查询阻塞的sql,然后kill掉,或者也可以等待
68050436 | test          | 2025-02-26 11:52:40 | select sleep(100) from a

二、源码分析

这是percona解决这个问题所涉及的改动,增加了一个skip_flush 的布尔常量

@@ -906,6 +906,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
    }
    if (table->table)
    {

+      const bool skip_flush=
+        (operator_func == &handler::ha_analyze)
+        && (table->table->file->ha_table_flags() & HA_ONLINE_ANALYZE);
      if (table->table->s->tmp_table)
      {
        /* 
@@ -915,7 +918,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
- 原逻辑:只要需要修改表或发生致命错误,就移除表缓存
- 新逻辑:当且仅当(不需要跳过刷新 且 需要修改表)或发生致命错误时,才移除表缓存
- 保留了致命错误时的强制刷新逻辑
 */
        if (open_for_modify && !open_error)
          table->table->file->info(HA_STATUS_CONST);
      }
-      else if (open_for_modify || fatal_error)
+      else if ((!skip_flush && open_for_modify) || fatal_error)
      {
        tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
                         table->db, table->table_name, FALSE);

下面是当前的完整代码

// 当表对象存在时
if (table->table)  
{
    // 判断是否需要跳过缓存刷新(在线分析且引擎支持在线分析时跳过)
    const bool skip_flush = 
        (operator_func == &handler::ha_analyze) &&
        (table->table->file->ha_table_flags() & HA_ONLINE_ANALYZE);

    // 处理临时表逻辑
    if (table->table->s->tmp_table) 
    {
        /*
          如果表未成功打开,则不尝试获取状态信息
          (修复Bug#47633)
        */
        if (open_for_modify && !open_error)
            table->table->file->info(HA_STATUS_CONST); // 获取存储引擎状态信息
    }
    // 非临时表且满足以下条件时
    else if ((!skip_flush && open_for_modify) || fatal_error) 
    {
        // 从表定义缓存中移除该表(非强制模式)
        tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
                        table->db, table->table_name, FALSE);
        
        /*
          可能有修改操作发生,因此需要
          使查询缓存失效
        */
        table->table = 0;                        // 重置表指针(用于查询缓存失效)
        query_cache.invalidate(thd, table, FALSE); // 使该表的查询缓存失效
    }
    else 
    {
        /*
          当执行 ALTER TABLE 的分区管理操作时
          (如 ANALYZE/CHECK PARTITION)
          重置需要处理的分区状态
        */
        if (table->table->part_info &&
            lex->alter_info.flags & Alter_info::ALTER_ADMIN_PARTITION) 
        {
            set_all_part_state(table->table->part_info, PART_NORMAL); // 将所有分区状态设为正常
        }
    }
}

/* 错误处理路径:管理命令执行失败时 */
if (thd->transaction_rollback_request) 
{
    /*
      罕见情况:存储引擎请求事务回滚
      (例如发生死锁时),执行回滚操作
    */
    if (trans_rollback_stmt(thd) || trans_rollback_implicit(thd))
        goto err; // 跳转到错误处理
}
else 
{
    // 正常提交事务
    if (trans_commit_stmt(thd) || trans_commit_implicit(thd))
        goto err; // 提交失败则跳转错误处理
}

// 关闭线程相关的表对象
close_thread_tables(thd);  
// 释放事务相关的元数据锁
thd->mdl_context.release_transactional_locks();

三、percona解释

发生这种情况的原因是,在修复之前, ANALYZE TABLE 的 工作方式如下:

  1. 打开表统计信息:允许并发 DML 操作(INSERT / UPDATE / DELETE / SELECT )
  2. 更新表统计信息:允许并发 DML 操作
  3. 更新完成
  4. 使表定义缓存中的表条目无效:禁止并发 DML 操作
    4.1. 这里发生的事情是ANALYZE TABLE 将当前打开的表共享实例标记为无效。这不会影响正在运行的查询:它们将照常完成。但所有传入查询都将无法启动,直到它们可以重新打开表共享实例。并且这在所有当前正在运行的查询完成之前不会发生。
  5. 使查询缓存无效:禁止并发 DML 操作

最后两个操作通常很快,但如果另一个查询触及表共享实例或获取查询缓存互斥锁,则它们无法完成。反过来,它也无法允许传入查询启动。

但是ANALYZE TABLE 修改的是表统计信息,而不是表定义!实际上,它不会以任何方式影响已经运行的查询。如果查询在ANALYZE TABLE 完成更新统计信息之前启动,则它使用旧统计信息。ANALYZE TABLE不会影响表中的数据。因此,查询缓存中的旧条目仍然是正确的 。它没有更改表的定义。因此,无需将其从表定义缓存中删除。因此,我们避免了上面的操作 4 和 5。

对lp:1704195的修复(迁移至PS-2503)删除了这些额外的更新以及它们所需的锁,并使ANALYZE TABLE 始终能够在繁忙的生产环境中安全运行。

参考文章
八怪大佬的文章
percona解决的版本
mysql官方bug记录地址
percona解决的详细信息
percona解决的版本

相关文章:

  • 【AI+智造】在阿里云Ubuntu 24.04上部署DeepSeek R1 14B的完整方案
  • Redis---缓存穿透,雪崩,击穿
  • GNN入门与实践——基于GraphSAGE在Cora数据集上的节点分类研究
  • 思维训练(算法+技巧)
  • 大白话TypeScript第八章TypeScript 项目的部署与监控
  • Kafka零拷贝
  • springcloud组件调用顺序
  • 游戏引擎学习第128天
  • 1-3压缩命令
  • 内存中的缓存区
  • 数据结构:二叉搜索树(排序树)
  • 介绍一款飞算JavaAI编程工具,集成到idea,图文并茂
  • AcWing 5933:爬楼梯 ← 递归 / 递推 / 高精度
  • Vue 安装 wangEditor 富文本编辑器
  • 【Redis】Mac系统一键安装redis
  • Python基于Django和人脸识别的在线票务系统设计与实现
  • Java进阶——注解一文全懂
  • MR-图解
  • 学生考勤请假管理系统
  • ai说话人分离 | 基于语音大模型进行说话人拆分
  • 东莞营销商城网站建设/开发app需要多少资金
  • 婚恋网站做翻译/免费建站哪个比较好
  • 鳌江哪里有做网站/设计公司排名前十强
  • 做爰网站名称/百度seo营销
  • wordpress点击图片/百度seo快速见效方法
  • 湖南奶茶加盟网站建设/国外新闻最新消息