MySQL8.0 Online DDL进一步

DDL变更是MySQL运维当中,避免不了日常工作,也是影响比较大的操作。为了较少风险,开源社区提供了gh-ost,pt-online-schema-change这样便利的工具,解决了一些堵塞问题。但还是存在很多不确定的因数。
比如当数据量较大的表需要表更时:

  • 创建触发器过程中穷住了
  • binlog同步发生了延迟,导致ddl无法完成
  • 执行过程中,内存占满,CPU 100% ,IO等待
    最终导致阻塞读写请求(DML操作阻塞),影响系统的可用性。
    所以ddl操作,要考虑这些因素,避开高峰期,操作评估,备手段需要准备好。

除了上诉方式,官方的Online DDL也是一种很好的方式。online DDL是在mysql5.6版本后加入的特性,用于支持DDL执行期间DML语句的并行操作,提高数据库的吞吐量。目前迭代到8.0 了解一下都有那些变化。

1. online DDL

MySQL在线DDL特性提供了即时支持instant ,copy方式,还有原表in-place方式。有些过程中也允许并发DML。

2.1.关键点
就是 ALGORITHM,LOCK 这个指标。

ALTER TABLE tbl_name , alter_option: {...},
ALGORITHM [=] {DEFAULT | INSTANT | INPLACE | COPY} 
LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}

为了避免在执行ALTER TABLE 操作时表可读 或不可写,可以在ALTER TABLE 语句中指定一个子句,如果请求是并发级别不可用,则操作立即停止。

构建方式:

  • COPY:对原始表的一个副本执行操作,将表数据从原始表逐行复制到新表。不允许并发DML。
    通过临时表拷贝的方式实现的。新建一个带有新结构的临时表,将原表数据全部拷贝到临 时表,然后Rename,完成创建操作。可能内存,io,cpu,硬盘空间使用上升。
    image.png

  • INPLACE:操作避免复制表数据,在操作的准备和执行阶段,可以简单地使用表上的独占元数据锁。通常,支持并发DML。所谓Inplace,也就是在原表上直接进行,不会拷贝临时表。与copy操作相比,向缓冲池中读取的数据更少,这减少了从内存中清除频繁访问的数据。
    image.png
    image.png

  • INSTANT:操作仅修改数据字典中的元数据。在准备和执行期间,表上没有独占元数据锁,并且表数据不受影响,这使得操作是瞬时的。允许并发DML。(MySQL8.0.12开始)
    上诉图中image.png符号的就是即时操作

备注:
可以理解COPY方式是把数据抽出来,在灌入进去,类似于server层的操作。可以支持所有引擎。
INPLACE方式 是在innodb引擎层完成,比如会多个frm ,ibd方式。底层innodb引擎在协助处理这个过程。
INSTANT就是元数据的更改了。

锁级别:

  • LOCK=NONE:允许并发查询和DML(允许读和写) 。
  • LOCK=SHARED:允许并发查询,但阻塞DML (允许读)
  • LOCK=EXCLUSIVE:阻塞并发查询和DML (独占元数据锁),尽可能短的时间内完成DDL操作。特备是服务器空闲时候,可以使用这个子句。

2. Online DDL的实现过程

在线DDL操作可以被看作有三个阶段:

阶段1: Initialization初始化

在初始化阶段,服务器将考虑存储引擎功能、语句中指定的操作以及用户指定的ALGORITHM和LOCK选项,确定操作期间允许多少并发性。在此阶段,使用一个共享的可升级元数据锁来保护当前表定义。

阶段2:Execution执行

在这个阶段,语句是准备和执行的。元数据锁是否升级为排他锁取决于初始化阶段评估的因素。如果需要独占元数据锁,则只在语句准备期间短暂地使用它。

阶段3:Commit Table Definition 提交表定义

在提交表定义阶段,元数据锁升级为排他锁,以排除旧表定义并提交新表定义。一旦授予,独占元数据锁的持续时间就会很短。

3. Online DDL要求

基本存放临时日志文件的空间有关系:

  • 当在线DDL操作创建索引或修改表时,一个临时日志文件记录并发的DML。临时日志文件根据innodb_sort_buffer_size的值扩展到innodb_online_alter_log_max_size指定的最大值。如果临时日志文件的大小超过限制,则在线DDL操作失败(出现DB_ONLINE_LOG_TOO_BIG错误),未提交的并发DML操作将回滚。较大的innodb_online_alter_log_max_size设置允许在在线DDL操作期间使用更多的DML,但也会延长锁定表以应用日志DML时DDL操作结束的时间。

  • 用于临时排序文件的空间
    建表的在线DDL操作在创建索引时将临时排序文件写入MySQL临时目录(Unix上的$TMPDIR, Windows上的%TEMP%,或由——TMPDIR指定的目录)。在包含原始表的目录中不会创建临时排序文件。每个临时排序文件都足够大,可以容纳一列数据,当将每个排序文件的数据合并到最终的表或索引中时,每个排序文件都会被删除。涉及临时排序文件的操作可能需要的临时空间等于表中的数据量加上索引。如果在线DDL操作使用了数据目录所在文件系统上的所有可用磁盘空间,则报告一个错误。
    如果MySQL临时目录不够大,不能保存排序文件,那么将tmpdir设置为另一个目录。或者,使用innodb_tmpdir为在线DDL操作定义一个单独的临时目录

  • 中间表文件的空间
    一些重建表的在线DDL操作在与原始表相同的目录中创建一个临时中间表文件。中间表文件可能需要与原始表大小相等的空间。中间表文件名以#sql-ib前缀开始,仅在在线DDL操作期间短暂出现。innodb_tmpdir选项不适用于中间表文件。

4. 失败条件

  • ALGORITHM子句指定了与特定类型的DDL操作或存储引擎不兼容的算法。

  • LOCK子句指定与特定类型的DDL操作不兼容的低级别锁定(SHARED或NONE)。

  • 在等待表上的排他锁时发生超时,这可能在DDL操作的初始和最终阶段短暂需要。

  • tmpdir或innodb_tmpdir文件系统的磁盘空间耗尽

  • 并发的DML修改了很多表,以至于临时在线日志的大小超过了innodb_online_alter_log_max_size配置选项的值。这种情况会导致DB_ONLINE_LOG_TOO_BIG错误。

  • 并发DML对原始表定义允许的表进行更改,但新表定义不允许。当MySQL尝试应用并发DML语句的所有更改时,这个操作只会在最后失败。例如,在创建唯一索引时,可以在列中插入重复值,或者在列上创建主键索引时,可以在列中插入NULL值。并发DML所做的更改优先,并且ALTER TABLE操作被有效回滚。

4. 可进度监控

独占元数据锁(exclusive ):在线DDL操作可能必须等待持有表上元数据锁的并发事务提交或回滚。通过show processlist通常看到穷住的情况如下

State: Waiting for table metadata lock
  • 元数据锁信息还通过performance_schema库查看
mysql> SELECT * FROM performance_schema.metadata_locks\G;
  • 使用性能模式更改表监视:
mysql> UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'stage/innodb/alter%';

再通过performance_schema.events_stages_current表来检查ALTER TABLE操作的进度。显示的阶段事件根据当前正在进行的ALTER TABLE阶段的不同而不同。

 
 
mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM performance_schema.events_stages_current; 
+------------------------------------------------------+----------------+----------------+ | EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED | 
+------------------------------------------------------+----------------+----------------+ | stage/innodb/alter table (read PK and internal sort) | 280 | 1245 | 
+------------------------------------------------------+----------------+----------------+ 1 row in set (0.01 sec)

备注:
1)WORK_COMPLETED列显示已完成的工作。
2)work_estimate列提供了对剩余工作的估计

4. 总结

在线DDL变更可能带来的风险,如果操作失败,回滚在线DDL操作的代价可能很高。

  • 修改大表结构执行时间往往不能预估,一般时间较长,可能带来的风险有:修改表结构是表级锁,影响DML写入操作。

  • 修改大表耗时较长,中途写入失败需要进行回滚,回滚这段时间也是不可写入。

  • 修改大表结构容易导致数据库CPU、IO性能损耗,降低MySQL服务性能。

  • 修改大表结构容易造成主从延迟加大,影响业务读取。

需要DBA介入评估。
其实最好的方式在从库上修改表结构,将结构变更了的从库设置为主库。

image.png

猜你喜欢

转载自blog.csdn.net/dreamyuzhou/article/details/119090273