掘金 后端 ( ) • 2024-04-23 10:17

theme: channing-cyan

引言

随着数据库技术的发展,越来越多的数据库系统开始支持在线DDL操作,以满足企业对高可用性的需求。

MySQL一直都是有在线DDL的能力的,但是,随着MySQL 8.0 的发布,MySQL对在线 DDL 功能进行了显著性增强,在线 DDL 到底是什么呢,随着作者一起来学习吧。

一、MySQL 8.0 在线 DDL 概述

1.1 在线 DDL 的基本概念

在线 DDL(Data Definition Language)是指在不停止数据库服务,不影响用户对数据库的读写操作的情况下,对数据库结构进行修改的能力。MySQL 8.0 版本对在线 DDL 功能进行了增强,支持更多的 DDL 操作类型,如添加索引、修改列的数据类型等,同时保持了数据库的高可用性。

1.2 与传统 DDL 操作的对比

与传统 DDL 操作的对比,MySQL 8.0 版本对在线 DDL 功能进行了增强,下面将从以下几个方面详细对比一下:

image.png

  • 性能影响

    • 传统 DDL:在旧版本的 MySQL 中,许多 DDL 操作(如添加索引)会导致表锁定,使得在操作期间无法进行 DML(Data Manipulation Language)操作,如 SELECTINSERTUPDATEDELETE 等,这在生产环境中可能导致业务中断。

    • 在线 DDL:允许在执行 DDL 操作的同时进行 DML 操作,从而减少了对业务的影响。

  • 资源消耗

    • 传统 DDL:可能需要创建临时表,复制原表数据到临时表,然后再将临时表替换原表,这个过程中会消耗更多的磁盘空间和 I/O 资源。

    • 在线 DDL:通过使用 ALGORITHM=INPLACE 或 ALGORITHM=INSTANT 选项,可以在不复制数据的情况下对表结构进行修改,减少了资源消耗。

  • 操作类型支持

    • 传统 DDL:只支持有限类型的 DDL 操作,对于某些操作(如修改列的数据类型)可能不支持热操作,即不能在线完成。

    • 在线 DDL:MySQL 8.0 扩展了支持的 DDL 操作类型,包括原子 DDL 操作,如 INSTANT ADD COLUMN,这些操作几乎可以瞬间完成,且不会阻塞 DML。

  • 锁定行为

    • 传统 DDL:在执行 DDL 时可能会获取长时间的表级锁,导致其他事务无法对表进行操作。

    • 在线 DDL:通过使用 LOCK=NONE 或 LOCK=SHARED 选项,可以在保持一定级别的并发性的同时执行 DDL 操作。

  • 主从复制影响

    • 传统 DDL:DDL 操作可能导致主从复制延迟,因为从库需要等待 DDL 操作完成后才能继续复制 DML 操作。

    • 在线 DDL:尽管可以减少锁的持有时间,但是在某些情况下(如使用 ALGORITHM=COPY)仍然可能会对复制性能产生一定影响。

  • 易用性

    • 传统 DDL:需要 DBA 进行更多的规划和维护,以避免长时间的锁定和复制延迟。

    • 在线 DDL:简化了 DDL 操作的执行,使得 DBA 可以通过简单的 ALTER TABLE 语句执行复杂的结构变更。

二、性能提升与并发性

在线DDL通过减少或消除DDL操作期间对数据库的锁定,显著提升了数据库的性能并增强了并发性。以下是性能提升与并发性的一些关键点:

image.png

  1. 应用程序响应时间的改善

    • 在线DDL允许应用程序继续执行DML操作,如查询和更新,即使在进行DDL更改时也不会被阻塞。这意味着应用程序的响应时间不会因DDL操作而受到显著影响,从而提升了用户体验和应用程序的总体性能。
  2. 减少锁定和等待时间

    • 传统的DDL操作,如添加索引或修改表结构,通常会在表上施加长时间的锁,导致其他事务等待锁释放后才能继续执行。在线DDL通过使用更精细的锁定机制,减少了锁的持续时间和锁定的粒度,从而减少了其他事务的等待时间。
  3. 可伸缩性增强

    • 在线DDL操作减少了对数据库资源的占用,如通过使用ALGORITHM=INPLACE选项避免复制整个表的数据。这种资源消耗的减少使得数据库能够更有效地处理高并发工作负载,提高了数据库的可伸缩性。

    • 此外,由于减少了锁争用,系统能够支持更多的并发用户和事务,这对于大型分布式系统和高流量应用尤其重要。

三、在线 DDL 关键参数

在线DDL(Data Definition Language)是在数据库运行时修改表结构而不中断对表的访问的能力。

在MySQL中,实现在线DDL主要依赖于ALGORITHMLOCK参数。

image.png

3.1 ALGORITHM 参数及其用法

ALGORITHM参数指定了执行DDL操作时采用的算法,它直接影响到DDL操作是否会对表进行重建或复制。该参数可以取以下值:

  1. INPLACE:尝试在原有表上进行修改,而不是创建一个新表。这个选项适用于那些不需要重建表的DDL操作,如添加或删除非主键索引,它可以减少IO和CPU消耗,保持DDL期间的良好性能和并发。

  2. COPY:需要拷贝原始表,因此不允许并发DML写操作,但允许读操作。使用COPY算法时,因为需要记录undo和redo日志,并且临时占用buffer pool,所以效率不如INPLACE

  3. INSTANT:这是MySQL 8.0中引入的新选项,它只修改数据字典中的元数据,不需要拷贝数据,不需要重建表,也不需要加排他MDL锁,几乎瞬间完成且不会阻塞DML4。

3.2 LOCK 参数及其对并发访问的影响

LOCK参数控制了DDL操作期间对表的锁定级别,影响并发DML操作的可行性。该参数可以取以下值:

  1. NONE:允许并发查询和DML。这适用于那些可以执行就地修改的操作,如添加或删除索引。

  2. SHARED:允许并发查询但阻止DML。这可以用于数据仓库表,可以延迟数据加载操作,但不能长时间延迟查询。

  3. DEFAULT:允许尽可能多的并发(查询、DML或两者兼有)。这是默认行为,MySQL会根据操作类型选择最合适的锁定级别。

  4. EXCLUSIVE:阻止并发查询和DML。当主要关注在尽可能短的时间内完成DDL操作,并且不需要并发查询和DML访问时,可以使用此选项。

注意:即使指定了LOCK=NONE,某些操作可能仍然需要短暂的独占锁来准备和完成DDL操作。此外,如果表上有长事务运行,它们可能会阻塞DDL操作,因为DDL操作需要获取元数据锁来修改表结构。

四、支持的在线 DDL 操作

MySQL 8.0 引入了对在线 DDL (Data Definition Language) 的支持,这使得数据库管理员和开发者可以在不停止数据库服务的情况下执行 DDL 操作。以下是 MySQL 8 支持的一些在线 DDL 操作的简要说明:

image.png

4.1 索引操作

  • 在线添加或删除索引,包括普通索引和唯一索引。

  • 在线重建索引,这允许在不锁定表的情况下对索引进行重建,减少了对数据库性能的影响。

4.2 主键和外键操作

  • 在线添加或删除主键

  • 在线修改外键约束,包括添加、删除或修改外键关系。

4.3 列操作

  • 在线添加列,允许在表中添加新的列而不影响现有数据和查询。

  • 在线删除列,可以移除不再需要的列,同时保持表的其余部分可用。

  • 在线修改列,可以更改现有列的数据类型、大小或其他属性。

4.4 表结构操作

  • 在线重命名表,允许更改表的名称而不影响数据库的其他操作。

  • 在线修改表的字符集或校对规则

注意:尽管许多 DDL 操作可以在线进行,但某些特定的操作,如修改表的存储引擎,仍然可能需要暂时锁定表。

五、即时操作(INSTANT)

5.1 即时操作的优势

image.png

  1. 性能提升:即时操作仅修改数据字典中的元数据,不影响表数据,因此操作速度极快,通常在毫秒级别完成。

  2. 并发DML支持:在执行即时操作时,允许同时进行数据插入、更新和删除操作,这在高并发系统中非常有用。

  3. 无需锁定:使用 INSTANT 算法的操作不需要对表进行长时间的锁定,这减少了对其他数据库操作的影响。

  4. 减少资源消耗:因为不需要复制或重建整个表,所以对 CPU、内存和 I/O 的要求较低。

5.2 从 MySQL 8.0.12 版本开始的改进

在 MySQL 8.0.12 版本之前,InnoDB 的 DDL 操作通常需要复制或重建表,这在大型表上可能会非常耗时。从 8.0.12 版本开始,引入了 INSTANT 算法,带来了以下改进:

  • 元数据字典的改进:MySQL 8.0 迁移到了新的事务数据字典,这使得即时 DDL 成为可能5。

  • 操作的即时性:添加列操作现在可以即时完成,而不需要逐行复制表数据5。

  • 数据字典的扩展:为了支持即时操作,数据字典被扩展以存储更多元数据,例如 information_schema.innodb_tables 表中新增了 instant_cols 列来记录表中即时列的数量5。

  • 更多的操作支持:随着版本的提升,更多的 DDL 操作类型开始支持即时算法,例如从 8.0.28 版本开始,重命名列的操作也开始支持 INSTANT 算法10。

六、并发 DML 操作

在 MySQL 8 中,对 DDL(Data Definition Language)操作的支持得到了显著增强,特别是在与 DML(Data Manipulation Language)操作的并发执行方面。以下是 MySQL 8 中 DDL 与 DML 并发执行的能力和对业务连续性的影响:

6.1 DDL 执行期间执行 DML 操作的能力

  • 在 MySQL 8.0 及更高版本中,引入了 ALGORITHM=INSTANT 选项,使得某些 DDL 操作(如添加或删除列)可以瞬间完成,而不需要复制或锁定整个表。这样,DML 操作可以与这些 DDL 操作并发执行,从而提高了数据库的可用性。

  • ALGORITHM=INPLACE 选项允许 DDL 操作在不复制表数据的情况下进行,通常支持并发 DML 操作。这种算法避免了与表复制方法相关的磁盘 I/O 和 CPU 周期,从而最小化数据库的总体负载。

6.2 对业务连续性的影响

  • 通过允许 DDL 和 DML 操作并发执行,MySQL 8 减少了因结构变更导致的业务中断时间。这对于 24/7 运行的业务尤其重要,因为它们需要最小的停机时间来进行维护操作。

  • 在线 DDL 操作可以减少锁定和等待 MySQL 服务器资源的时间,从而提高操作的响应速度并增加整体的可伸缩性。

  • 尽管 ALGORITHM=INSTANT 提供了即时操作,但并非所有 DDL 操作都支持这种算法。例如,修改表的存储引擎或对大表进行某些类型的索引操作可能仍然需要使用 ALGORITHM=COPY,这可能会阻塞 DML 操作。

七、元数据锁和性能监控

7.1 元数据锁的作用和类型

元数据锁(Metadata Lock,简称MDL)是MySQL中用于确保数据库对象在DDL和DML操作期间的一致性和完整性的机制。MDL锁的作用范围可以是表、模式、存储过程、函数、触发器、计划事件,甚至是表空间等。

MDL锁有两种基本类型

  1. MDL读锁:当对表进行SELECT或DML操作(如UPDATE、INSERT、DELETE)时,MySQL会自动给表加上MDL读锁。读锁允许其他线程继续读取表的元数据,但不允许修改表结构。

  2. MDL写锁:当执行DDL操作,如ALTER TABLE或CREATE INDEX时,MySQL会给表加上MDL写锁。写锁意味着只有持有锁的线程可以修改表结构,其他线程既不能修改结构也不能执行DML操作。

7.2 使用performance_schema.metadata_locks表进行监控

MySQL的performance_schema数据库提供了一个metadata_locks表,该表记录了当前所有活动的MDL锁及其相关信息,可以用于监控和分析MDL锁的使用情况。

通过查询metadata_locks表,可以获得以下信息:

  • 持有MDL锁的线程ID。

  • MDL锁的类型(读或写)。

  • 被锁定的数据库对象名称。

  • 锁的持续时间等。

启用和使用metadata_locks表的步骤如下:

  1. 确保performance_schema已经启用,这可以通过查询performance_schema.setup_instruments表来确认。

  2. 直接查询metadata_locks表来查看当前的MDL锁状态:

SELECT * FROM performance_schema.metadata_locks;
  1. 如果需要监控特定的MDL锁事件,可以通过performance_schema.setup_consumersperformance_schema.setup_instruments表来启用相应的事件监控。

八、复制阻塞问题

8.1 在线 DDL 与复制延迟的关系

在 MySQL 中,执行在线 DDL(Data Definition Language)操作时,为了保证数据的一致性和完整性,DDL 操作通常会在主从复制架构中引入延迟。这是因为:

  1. DDL 操作的原子性:DDL 操作如 ALTER TABLE 通常被视为一个原子操作,它需要在主服务器上完整执行后,才能将变化复制到从服务器。

  2. 复制线程的阻塞:在从服务器上,DDL 操作在默认情况下是由单个 SQL 线程顺序执行的。这意味着,当一个 DDL 操作正在进行时,它可能会阻塞后续的 DML 操作的回放,导致复制延迟。

  3. 日志记录:在线 DDL 操作会在 binlog 中记录,如果操作复杂或涉及大量数据,可能会产生大量的日志,从而增加从服务器处理的时间,进一步加剧延迟。

8.2 如何减少复制阻塞的影响

为了减少复制阻塞的影响,可以采取以下措施:

image.png

  1. 使用更快的硬件:提升主从服务器的硬件性能,尤其是 SSD 存储,可以加快 DDL 操作的执行速度,从而减少延迟。

  2. 优化 DDL 操作:尽可能在低峰时段执行 DDL 操作,减少对业务的影响。同时,优化 DDL 操作的复杂性,例如,避免对大表进行可能导致长时间锁定的操作。

  3. 并行复制:MySQL 5.6 引入了并行复制的概念,通过多个工作线程并行回放 relay log 中的事件,可以提高复制的效率。

  4. WriteSet 复制:MySQL 8.0 引入了基于 WriteSet 的并行复制方案,该方案可以更有效地利用从服务器的资源,减少单个大事务对复制延迟的影响。

  5. 使用第三方工具:使用如 pt-online-schema-changegh-ost 这样的工具可以在复制架构中进行在线 DDL 而不影响业务查询,因为它们通过双写集机制来保持数据一致性。

  6. 调整复制配置:调整 sync_binloginnodb_flush_log_at_trx_commit 参数,优化 redo log 和 binlog 的写入策略,可以在一定程度上减少I/O操作对复制延迟的影响。

  7. 避免大事务:尽可能避免长时间运行的事务,因为它们会锁定资源并导致复制延迟。

  8. 监控和预警:实施有效的监控系统,以便在复制延迟发生时及时发现并采取措施。

  9. 使用组提交:在 MySQL 中,可以使用组提交(Group Commit)技术来减少磁盘 I/O 操作的次数,从而提高性能。

九、与第三方工具的比较

下面是一个使用Markdown格式的表格,包含了与pt-osc、gh-ost和MySQL 8.0原生Online DDL功能相关的性能对比内容:

对比点 MySQL 8.0原生Online DDL pt-osc gh-ost 性能 优秀 良好 良好 存储开销 低 高 高 易用性 简便 中等 中等 主从复制延迟 低 中等 中等 复制阻塞问题 存在 较小 较小

十、总结

MySQL 8.0 的在线 DDL 功能显著提升了数据库维护的便捷性和性能。它通过减少锁定和支持 DDL 与 DML 操作的并发执行,降低了数据库维护对业务的影响。

此外,新引入的 INSTANT 算法使得某些 DDL 操作能瞬间完成,减少了资源消耗。这些改进不仅提高了数据库的可用性和性能,还简化了数据库的管理和优化工作,对数据库维护和开发产生了积极影响。

当然,不是说MySQL8做了升级你就可以为所欲为了,实际操作中我们还是要贴合实际情况,比如尽量不要在业务高峰期执行在线 DDL;总之一句话,稳着点,不要挑战极限。

希望本文对您有所帮助。如果有任何错误或建议,请随时指正和提出。

同时,如果您觉得这篇文章有价值,请考虑点赞和收藏。这将激励我进一步改进和创作更多有用的内容。

感谢您的支持和理解!