MySQL 案例:如何监控DDL

2022-02-22 17:25:32 浏览数 (1)

背景

经常会有用户在咨询大表 DDL 的进度,预估时间等信息,其实依靠经验来做判断的话,比较容易出现误差,而且也和评估人的实际评估手段有较大的关系。事实上 MySQL 本身就有 DDL 的监控手段吗,只是默认情况没有进行开启。

实践一下

测试环境使用了腾讯云数据库 MySQL 5.7,官方的 MySQL 8.0,5.7 版本基本同理。首先需要打开performance_schema(腾讯云 MySQL 需要留意是否开启了这个参数),然后在setup_instruments表中开启 alter 操作对应的监控项以及p_f(performance_schema)对应的表。使用如下操作开启:

代码语言:txt复制
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%stages%';
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'stage/innodb/alter%';

测试使用的表:

代码语言:txt复制
CREATE TABLE `sbtest1` (
  `id` int NOT NULL AUTO_INCREMENT,
  `k` int NOT NULL DEFAULT '0',
  `c` char(120) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
  `pad` char(60) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=1000001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

测试的对象语句:

代码语言:txt复制
alter table sbtest.sbtest1 modify c varchar(128)  NOT NULL DEFAULT '';

因为开启了 p_f 的参数,所以现在能在内存表里面看到具体的数据了:

代码语言:txt复制
mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM performance_schema.events_stages_current;
 ----------------------------- ---------------- ---------------- 
| EVENT_NAME                  | WORK_COMPLETED | WORK_ESTIMATED |
 ----------------------------- ---------------- ---------------- 
| stage/sql/copy to tmp table |         309523 |        9863083 |
 ----------------------------- ---------------- ---------------- 
1 row in set (0.00 sec)

WORK_COMPLETED 表示已经完成的“工作量”,WORK_ESTIMATED表示预计的总工作量,所以评估 DDL 操作的进度的时候可以用两个指标来判断整体的进度。预估时间的时候,可以参考如下语句进行简单的估算:

代码语言:txt复制
mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM performance_schema.events_stages_current;select sleep(5);SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM performance_schema.events_stages_current;

 ----------------------------- ---------------- ---------------- 

| EVENT_NAME                  | WORK_COMPLETED | WORK_ESTIMATED |

 ----------------------------- ---------------- ---------------- 

| stage/sql/copy to tmp table |         385652 |        9863083 |

 ----------------------------- ---------------- ---------------- 

1 row in set (0.00 sec)

 ---------- 

| sleep(5) |

 ---------- 

|        0 |

 ---------- 

1 row in set (5.00 sec)

 ----------------------------- ---------------- ---------------- 

| EVENT_NAME                  | WORK_COMPLETED | WORK_ESTIMATED |

 ----------------------------- ---------------- ---------------- 

| stage/sql/copy to tmp table |         923696 |        9863083 |

 ----------------------------- ---------------- ---------------- 

1 row in set (0.00 sec)

mysql> select 9863083/(923696-385652)*5/60;

 ------------------------------ 

| 9863083/(923696-385652)*5/60 |

 ------------------------------ 

|                   1.52761407 |

 ------------------------------ 

1 row in set (0.00 sec)

简单计算出来的总时间是 1.57 分钟,大概就是 90 秒左右。实际上运行的时间可以参考语句执行的具体时间:

代码语言:txt复制
mysql> alter table sbtest.sbtest1 modify c varchar(120)  NOT NULL DEFAULT '';

Query OK, 9999999 rows affected (1 min 37.27 sec)

Records: 9999999  Duplicates: 0  Warnings: 0

不过 DDL 本身操作的时候也有很多的阶段,current 表本身只能看到当前阶段的进度,可以通过定期的查询来估算进度。

总结一下

其实 MySQL 自身已经集成了非常多的监控信息,有需求的时候可以多研究研究setup_instruments。实际上 DDL 也可以使用 Online DDL 工具来操作,本身 gh-ost 工具也会展示操作的进度。

0 人点赞