「背景:为什么要监控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, 2) AS 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 秒。
「欢迎关注我们的公众号,获取更多技术分享与经验交流。」




