暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL 大表变更必看!如何实时监控ALTER TABLE进度?

数据库驾驶舱 2024-06-23
130

「背景:为什么要监控ALTER TABLE进度?」

ALTER TABLE
是一种常见的数据库操作,用于增加、删除或修改表中的列、索引和约束等。对于小型表,ALTER TABLE
通常是瞬间完成的,但对于拥有数百万甚至数亿行数据的大表来说,操作时间可能会从几分钟延长到几小时甚至几天。

监控这些操作的进度,不仅可以帮助数据库管理员合理安排维护时间,还能及时发现问题,避免因操作时间过长而导致的业务中断或性能问题。

「如何在 MySQL 中监控ALTER TABLE进度?」

从 MySQL 5.7 和 8.0 版本开始,Performance Schema
提供了一种高效的方法来监控数据库内部的运行状态,包括 ALTER TABLE
操作的进度。以下是详细的操作步骤和示例代码。

进度信息是通过 Performance Schema 中的阶段事件实现的。实测在5.7.40,8.0.12后版本,可以通过查询 setup_instruments Performance Schema 表,可以轻松列出能够报告进度信息的阶段:

mysql> SELECT NAME, ENABLED, TIMED
         FROM performance_schema.setup_instruments
        WHERE NAME LIKE 'stage/innodb/alter table%'
              AND PROPERTIES = 'progress';
+------------------------------------------------------+---------+-------+
| NAME                                                 | ENABLED | TIMED |
+------------------------------------------------------+---------+-------+
| stage/innodb/alter table (end)                       | YES     | YES   |
| stage/innodb/alter table (flush)                     | YES     | YES   |
| stage/innodb/alter table (insert)                    | YES     | YES   |
| stage/innodb/alter table (log apply index)           | YES     | YES   |
| stage/innodb/alter table (log apply table)           | YES     | YES   |
| stage/innodb/alter table (merge sort)                | YES     | YES   |
| stage/innodb/alter table (read PK and internal sort) | YES     | YES   |
+------------------------------------------------------+---------+-------+
7 rows in set (0.00 sec)

如您所见,默认情况下,所有工具都处于启用状态和定时状态。但是,默认情况下未启用的是可以使信息可用的使用者:

mysql> SELECT NAME, ENABLED,
              sys.ps_is_consumer_enabled(NAME) AS EnabledWithHierarchy
         FROM performance_schema.setup_consumers
        WHERE NAME = 'events_stages_current';
+-----------------------+---------+----------------------+
| NAME                  | ENABLED | EnabledWithHierarchy |
+-----------------------+---------+----------------------+
| events_stages_current | NO      | NO                   |
+-----------------------+---------+----------------------+
1 row in set (0.01 sec)

为了使用进度信息,需要启用 events_stages_current
消费者。这个消费者负责保持 performance_schema.events_stages_current
表的最新状态,即记录每个线程的当前阶段。默认情况下,Performance Schema
的其余部分是启用的,但需要单独启用 events_stages_current
消费者:

mysql> UPDATE performance_schema.setup_consumers
          SET ENABLED = 'YES'
        WHERE NAME = 'events_stages_current';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
mysql> SELECT NAME, ENABLED,
              sys.ps_is_consumer_enabled(NAME) AS EnabledWithHierarchy
         FROM performance_schema.setup_consumers
        WHERE NAME = 'events_stages_current';
+-----------------------+---------+----------------------+
| NAME                  | ENABLED | EnabledWithHierarchy |
+-----------------------+---------+----------------------+
| events_stages_current | YES     | YES                  |
+-----------------------+---------+----------------------+
1 row in set (0.00 sec)

监控进度信息的基础是 performance_schema.events_stages_current
表。以下是查询 ALTER TABLE
进度信息的示例:

mysql> ALTER TABLE salaries ADD COLUMN new_col int NOT NULL DEFAULT 0, ALGORITHM=INPLACE;


mysql> SELECT stmt.THREAD_ID, stmt.SQL_TEXT, stage.EVENT_NAME AS State,
              stage.WORK_COMPLETED, stage.WORK_ESTIMATED,
              ROUND(100*stage.WORK_COMPLETED/stage.WORK_ESTIMATED, 2AS CompletedPct
         FROM performance_schema.events_statements_current stmt
              INNER JOIN performance_schema.events_stages_current stage
                      ON stage.THREAD_ID = stmt.THREAD_ID
                         AND stage.NESTING_EVENT_ID = stmt.EVENT_ID\G
*************************** 1. row ***************************
     THREAD_ID: 63857
      SQL_TEXT: ALTER TABLE salaries ADD COLUMN new_col int NOT NULL DEFAULT 0, ALGORITHM=INPLACE
         State: stage/innodb/alter table (read PK and internal sort)
WORK_COMPLETED: 8906
WORK_ESTIMATED: 27351
  CompletedPct: 32.56
1 row in set (0.00 sec)

这个查询结合了events_statements_current 
events_stages_current
表,显示了当前正在执行的 ALTER TABLE
语句的进度信息。

使用 sys.sessio
n 视图查询进度信息
另一种更方便的方法是使用 sys.session
视图,它提供了更详细的进程列表信息,包括进度信息:

mysql> SET @sys.statement_truncate_len = 85;
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT thd_id, conn_id, db, command, state, current_statement,
              statement_latency, progress, current_memory, program_name
         FROM sys.session
        WHERE progress IS NOT NULL\G
*************************** 1. row ***************************
           thd_id: 63857
          conn_id: 63818
               db: employees
          command: Query
            state: alter table (merge sort)
current_statement: ALTER TABLE salaries ADD COLUMN new_col int NOT NULL DEFAULT 0, ALGORITHM=INPLACE
statement_latency: 4.22 s
         progress: 49.39
   current_memory: 464.27 KiB
     program_name: MySQLWorkbench
1 row in set (0.06 sec)

在此示例中,@sys.statement_truncate_len
用户变量设置为 85。默认情况下,sys 架构确保当前语句的长度最多为 64 个字符。为了避免在这种情况下截断,截断长度增加到 85。
示例输出显示进度约为 49%。需要注意的是,这是一个估计值,而不是一个确切的数字。ALTER TABLE 当时正在执行合并排序,查询已运行 4.22 秒。

「欢迎关注我们的公众号,获取更多技术分享与经验交流。」


文章转载自数据库驾驶舱,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论