0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MySQL如何优雅的执行DDL

京东云 来源:jf_75140285 作者:jf_75140285 2024-07-18 15:06 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、前言

关于MySQL DDL表结构变更,各个工单平台基本上都支持了pt-osc及Online DDL的方式,但是,我相信仍然有一大部分人,不太了解这两种方式各自的优缺点是啥,以至于实际当中,会稀里糊涂的随机选一种去执行,选对了固然好,选错了,自然免不了领导的一顿K,这......当然是开玩笑的哈。



在各搜索平台上,介绍关于pt-osc及Online DDL工作原理的文章,不计其数,但是,对于非专业选手而已,又有几个人是完全吃透的呢?所以,在这,不打算对其原理再重复一遍,仅从他们的执行机制角度出发,介绍各种DDL在选择不同方式时所产生的影响,并基于此来分析该如何选择。



另,现在普遍使用的版本为5.7,所以,咱就以 MySQL 5.7.24 版本为例。



二、pt-osc及Online DDL执行机制

2.1 Online DDL

•机制:MySQL通过Innodb引擎在内部执行一系列的操作进行表变更,当然,同一个表,不同的DDL,会有不同效果,甚至会出现一天上一个地下的差异,所以不同DDL,后面再对其进行具体分析;如果有从库,则在主库执行完成后,从库再操作一遍,动作和主库一模一样(执行时间也很接近)。

•优点:这个咱后面在讲具体SQL时再进行具体分析。

•缺点:

◦某些场景下,会锁表引发堵塞增删改操作,这个是需要重点注意的,具体场景后面会标红说明。

◦如果有从库,这有一个很致命的弱点:复制延迟。因为主库执行的动作,会在从库再来一遍,如果这个动作是非常耗时的,那在从库执行(重放主库的动作)的时间点开始,其后续所有动作都被堵塞住,直到从库也执行完这个DDL后,才会继续按顺序执行其他SQL。这就就意味着,从从库执行开始,从库复制就出现了延迟,延迟的时间会慢慢变大,直到DDL执行完后,延迟才会慢慢变小。

◦存在数据copy的情况时,需要额外的磁盘空间,但有可能同样的SQL,空间需求会比使用pt-osc低。

◦特殊情况:云侧MySQL RDS,本身有一个隐藏从库用于高可用,因为这个隐藏从库不对外提供服务,所以基本上业务侧也不需要去关注他。但极端情况,如果大表DDL操作使用Online DDL模式时,在隐藏从库正在执行DDL期间,主库挂了,那常理就需要切换到隐藏从库,才能继续提供服务,但为了保证数据的一致性,隐藏从库必须要等DDL执行完,再回放DDL之后的binlog,然后,才能将其提升为主库,对外提供服务,所以这个恢复时间有可能很长。总得来讲,这个情况对业务而言也是致命的,只不过概率极低。



2.2 pt-osc

•机制:创建一个新临时表,并在老表上创建3个触发器,再进行新老表的数据同步,直至新老表数据一致后,再进行表名互换,达到表变更的目的。不同的DDL,只要pt-osc支持,他的操作方式都是一样的,这点与Online DDL完全不同。

•优点:

◦可以设置相应的参数,根据主、从库负载(比如复制延迟)的情况,动态调整数据拷贝速度,整个表结构变更过程相对比较温和。

◦不会引发从库复制延迟超级大的情况;

◦执行完后,新表会将老表占用的碎片空间完全释放掉。

•缺点:

◦需要将老表的所有数据都拷贝到新表上,这就意味着拷贝期间,磁盘IO可能较高。

◦要拷贝全量数据,所以执行时间也会很长。

◦新临时表存放数据也需要空间(最大空间需求可能和原表一样),拷贝数据时还会产生大量binlog,所以对于本来空间就紧张的实例而言,这方式真的是雪上加霜。



2.3 加锁

加锁情况,想必是大家使用时关心较多的一个问题,但是,我想说,MySQL 5.7加锁情况会比你想象中的要好。Online DDL及pt-osc,大部分情况下,只会在执行前后加表元数据锁,其在获取到表元数据锁并上锁后,在极短时间内做完后续相关动作,紧接着就会将锁释放掉。Online DDL除特殊操作外(后面会说明),大部分情况下,不会对现有业务造成堵塞影响。在业务足够繁忙时,反而有可能会出现表结构变更操作获取不到表元数据锁(锁等待超时),从而导致执行失败的情况。



三、各种DDL操作

在具体分析后面各种DDL之前,咱统一假设要操作的表足够大,要不然表太小的话,不管什么方式都是瞬间完成,就没有对比的意义了。另,编写的DDL语句,如果想用Online DDL方式,咱也不需要刻意去指定 ALGORITHM 及 LOCK 选项,就让MySQL自动判断后默认选择就好。



下面,咱就从MySQL官方文档Online DDL对各种操作的支持角度去分析两种方式的差异情况。当然,如果你的DDL语句同时含有好几种不同的操作,那就以最坏的那种情形做参考即可。



3.1 索引操作

图一:Online DDL 索引操作

wKgZomaYvvKAb4HjAAGyklNYP_0685.png





3.1.1 创建普通二级索引

Online DDL:从图一,我们可以看出,这会选择In Place的方式执行,整个过程,只会涉及到拷贝二级索引列相关的数据用于创建索引,所以需要拷贝的数据,相对于pt-osc而已,肯定会少很多,反过来说,执行需要的时间也相对会少。如果没从库,不存在复制延迟的问题,那选择Online DDL显然会比pt-osc更优;但如果有从库,那复制延迟的问题,自然是需要考虑的,而且大表复制延迟的时间,当然也会较长,如果接受不了延迟,那直接选pt-osc就好。



pt-osc:复制整个表的数据用于建新表,优势是有从库时,几乎不存在复制延迟的问题;劣势也很明显,因为拷贝整个表的数据,所以时间长,同时磁盘IO也会变高。



3.1.2 删除索引、索引重命名

Online DDL:从图一可以看到Only Modifies Metadata对应的是YES,也就意味着仅修改元数据,速度非常快,几乎瞬间完成,必选Online DDL。



pt-osc:直接无视



3.1.3 变更索引类型、全文索引、空间索引

咱现在使用的索引类型基本上都是BTREE,几乎很少用到HASH,同时也很少见到有用全文索引及空间索引的,所以,这几种咱就不讨论了。



3.2 唯一索引及主键操作

图二:Online DDL主键操作

wKgaomaYvvOASSbnAAGEruH2AyE360.png





因为pt-osc拷贝数据的过程,会依赖于唯一键(主键或者唯一索引)来校验数据的一致性,对唯一键进行相关的操作可能会引发各种各样的问题,所以不管pt-osc实际支持或不支持这类操作,咱都直接默认为不支持就好。也就是涉及主键及唯一索引相关的操作,都直接选Online DDL。但是,需要注意的是,单独删除主键的操作,会引发锁表,导致不允许对表进行其他增删改的操作,也就是增删改会被堵塞住,这操作需要慎重考虑。而同一个DDL里面,删除老主键的同时又加上新主键,是不会引起堵塞的。



3.3 列操作

图三:Online DDL列操作

wKgZomaYvvSAVCEgAAO4PeRxRVA931.png





3.3.1 添加列、删除列、重排列顺序、变更列类型、修改列为空或非空

Online DDL:从图三可以看出,这6种DDL操作,在选择Online方式时,都会重建表,效果上与pt-osc并无太大差别,还得担忧从库复制延迟的问题,那既然如此,直接选择pt-osc的方式更省事。



Online DDL以下这几种情况会锁表,堵塞其他增删改操作,需要注意:

1)增加一个自增列。

2)单纯修改列类型。

3)修改列名,同时修改了列类型(该情形应该算修改列类型的一个特殊例子)(只支持 Online DDL)。



pt-osc:首选。需要注意的是,因为pt-osc不支持修改列名,所以上述的第三点,只能选择Online DDL的方式执行,但是选择Online DDL,又会出现锁表导致堵塞其他增删改的操作,所以慎重。



3.3.2 VARCHAR列增加列大小

Online DDL:MySQL底层在存储变长列VARCHAR列的内容时,还会额外记录内容占用字节数的大小,记录这个大小,也是需要空间的。另外,还有个东西咱需要了解下,VARCHAR列存储一个字符,使用utf8字符集时,最大需要3字节(比如存储一个中文字符),而utf8mb4最大需要4字节(比如存储一个表情符)。知道了使用什么字符集,咱就可以计算出存储一个VARCHAR变长列最大需要多少字节了。



列存储最大需要字节数 = VARCHAR列定义的长度 * 不同字符集存储单个字符需要最大字节数



而记录列占用字节数大小,所需的空间,会根据 列存储最大需要字节数 细分出两种情况:

1)列存储最大需要字节数为0-255时,记录列占用字节数大小需要1字节。

2)列存储最大需要字节数为256-65535时,记录列占用字节数大小需要2字节。

3)因表数据行,非大对象的列,总的存储内容长度限制就是65535,所以,单列VARCHAR存储需求自然也不能超过这个限制,也就是不存在超过65535的情况。



回归正题,VARCHAR列增加大小:

1)如果列长度增加后,记录列占用字节数大小所需字节数不变,也就是列存储最大需要字节数依然在同一个范围内:0-255或256-65535,那这类操作,ALGORITHM支持使用 In Place算法,只会修改表的元数据信息,瞬间完成,此情形,直接选Online DDL即可。

2)如果列长度增加后,记录列占用字节数大小所需字节数变了,从1字节变成2字节,ALGORITHM 则只支持COPY算法,这就意味着会出现数据拷贝的情况,同时会堵塞其他增删改的操作,这情形选pt-osc。



例子:

# 建表
create table t1(name varchar(10) null) charset=utf8mb4;

# 列存储最大需要字节数计算:长度 10,utf8mb4字符集存储单字符最大需要字节数 4
# 列存储最大需要字节数 = 10 * 4 = 40
# 记录列占用字节数大小所需空间为1字节


# 表结构变更一
alter table t1 modify name varchar(63) null;

# 列存储最大需要字节数计算:长度 63,utf8mb4字符集存储单字符最大需要字节数 4
# 列存储最大需要字节数 = 63 * 4 = 252
# 记录列占用字节数大小所需空间依然为1字节,ALGORITHM默认选用In Place,Online DDL执行瞬间完成


# 表结构变更二
alter table t1 modify name varchar(64) null;

# 列存储最大需要字节数计算:长度 64,utf8mb4字符集存储单字符最大需要字节数 4
# 列存储最大需要字节数 = 64 * 4 = 256
# 记录列占用字节数大小所需空间变为2字节,ALGORITHM只能使用COPY,引发数据拷贝,堵塞其他增删改操作,选择pt-osc




pt-osc:根据上述信息选合适的。



3.3.3 修改列名(只改列名)、设置/删除默认值、修改ENUM/SET列定义

Online DDL:从图三可以看出,这类操作会只修改表元数据信息,速度极快,直接选Online DDL方式即可



pt-osc:直接无视



3.3.4 修改自增列的自增值

Online DDL:在MySQL 8.0版本前,自增值不存在持久化的概念,修改这个值,只会在内存中修改,更不涉及数据的拷贝及变动,所以直接使用Online DDL方式即可。



pt-osc:直接无视



3.4 Generated列操作

图四:Online DDL 虚拟列操作

wKgaomaYvvWAbgIbAAIWU26vLqM873.png





3.4.1 新增/删除Generated虚拟列

Online DDL:虚拟列不涉及数据存储的问题,所以新增和删除都只会涉及到表元数据的变更,几乎瞬间完成,直接选用Online DDL方式执行即可。



pt-osc:直接无视



3.4.2 新增/修改/删除Generated存储列、修改Generated虚拟列顺序

Online DDL:这几种操作,在选择Online DDL时,都会涉及到表重建的问题,大表执行时间不会短,另外,新增/修改Generated存储列 以及 修改Generated虚拟列顺序,都会锁表,引发堵塞其他增删改操作,所以,建议选pt-osc。



pt-osc:首选



3.5 外键操作

图五:Online DDL外键操作

wKgZomaYvvaALI-YAAFwC3Ekk1Q448.png





如果表存在外键依赖,后期对父表进行各种DDL操作时,数据库会有较大的风险,严重的甚至会锁表,所以不建议用外键。



3.6 表操作

图六:Online DDL表操作

wKgaomaYvveAdDmkAALYuWHnn0c540.png





3.6.1 修改表名

Online DDL:从图六看出,Online DDL修改表名,只会涉及到修改表的元数据信息,瞬间完成。



pt-osc:不支持



3.6.2 表碎片整理、更改行格式、修改字符集、收集统计信息

Online DDL:咱对表的操作,常用到的,可能就是表碎片整理、更改行格式(比如改成压缩模式),修改字符集(含内容转换)以及收集统计信息,这些操作,从图六也看到了,基本都是需要重建表,建议首选pt-osc。



pt-osc:首选



3.6.3 其他相关的表操作

其他操作平常基本很少用到,暂时不讨论。



3.7 表空间操作

图七:Online DDL表空间操作

wKgZomaYvviAKXiTAAEQrGq-8tc779.png





在实际使用中,几乎见不到,咱就不讨论了。



3.8 表分区操作

图八:Online DDL表分区操作

wKgaomaYvvmAE75kAAdjVH5DRuc440.png





表分区相关的操作较多,咱就挑比较常用的进行分析,其他操作不做赘述。



3.8.1 普通表转分区表

Online DDL:他的本质是新建一个临时表,每个分区对应一个数据文件,然后进行拷贝,拷贝完毕后,表名互换,删除老表。眼熟不?从某种程度上讲,这个过程与pt-osc是相似的,但是,Online DDL方式会锁表,堵塞其他增删改操作,所以,直接选择pt-osc方式即可。



pt-osc:必选



3.8.2 新增分区、删除分区、TRUNCATE分区

Online DDL:

新增分区,只分析常用的RANGE及LIST分区。RANGE分区新增分区,有个严格的限制,新分区less than的值必须是递增的,换句话讲就是不存在数据拷贝的问题。LIST分区,这个更直接,相关内容如果在LIST分区中不存在,直接不允许插入,新增分区也不存在数据拷贝的问题。所以,这两种选用Online DDL时,操作几乎都是瞬时完成的,直接使用Online DDL即可。



删除分区时,会对当前分区上锁,堵塞该分区的其他增删改操作,但既然你都打算删除分区了,想必自然也不会再对该分区有其他操作。 其对应系统底层的操作,类似于直接将分区对应的物理文件进行删除,操作时,如果文件足够大,系统IO会瞬间暴涨,继而影响业务,所以建议在业务低峰期间进行。



TRUNCATE分区操作,对应系统底层的操作,类似于直接将分区对应的物理文件进行清空,操作时,如果文件足够大,系统IO会瞬间暴涨,继而影响业务,所以建议在业务低峰期间进行。



pt-osc:直接无视



四、结束语

从上面的介绍可以看出,DDL相关的操作较多,想要完全记住各种操作选那种方式最合适,想必也是件费神的事情。如果上面信息对你有用,点赞收藏起来,用到时再慢慢参考即可。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • MySQL
    +关注

    关注

    1

    文章

    897

    浏览量

    29230
  • DDL
    DDL
    +关注

    关注

    0

    文章

    13

    浏览量

    6533
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    mysql数据恢复—mysql数据库表被truncate的数据恢复案例

    某云ECS网站服务器,linux操作系统,部署了mysql数据库。工作人员在执行数据库版本更新测试时,错误地将本应在测试库执行的sql脚本在生产库上执行了,导致部分表被truncate
    的头像 发表于 09-11 09:28 579次阅读
    <b class='flag-5'>mysql</b>数据恢复—<b class='flag-5'>mysql</b>数据库表被truncate的数据恢复案例

    CentOS 7下MySQL 8双主热备高可用架构全解

    https://repo.mysql.com//mysql80-community-release-el7-7.noarch.rpm sudo rpm -Uvh mysql80-community-release-el7-7.
    的头像 发表于 08-12 17:08 600次阅读

    MySQL 8.0性能优化实战指南

    作为一名运维工程师,MySQL数据库优化是我们日常工作中最具挑战性的任务之一。MySQL 8.0作为当前主流版本,在性能、安全性和功能上都有了显著提升,但如何充分发挥其潜力,仍需要我们掌握正确的优化策略。
    的头像 发表于 07-24 11:48 538次阅读

    MySQL数据备份与恢复策略

    数据是企业的核心资产,MySQL作为主流的关系型数据库管理系统,其数据的安全性和可靠性至关重要。本文将深入探讨MySQL的数据备份策略、常用备份工具以及数据恢复的最佳实践,帮助运维工程师构建完善的数据保护体系。
    的头像 发表于 07-14 11:11 465次阅读

    企业级MySQL数据库管理指南

    在当今数字化时代,MySQL作为全球最受欢迎的开源关系型数据库,承载着企业核心业务数据的存储与处理。作为数据库管理员(DBA),掌握MySQL的企业级部署、优化、维护技能至关重要。本文将从实战角度出发,系统阐述MySQL在企业环
    的头像 发表于 07-09 09:50 504次阅读

    除了增删改查你对MySQL还了解多少

    我们都知道MySQL服务器的默认端口为3306,之后就在这个端口号上等待客户端进程进行连接(MySQL服务器会默认监听3306端口)。
    的头像 发表于 04-14 17:20 513次阅读

    从Delphi、C++ Builder和Lazarus连接到MySQL数据库

      从 Delphi、C++ Builder 和 Lazarus 连接到 MySQL 数据库 MySQL 数据访问组件(MyDAC)是一个组件库,提供从 Delphi 和 C++ Builder
    的头像 发表于 01-20 13:47 1315次阅读
    从Delphi、C++ Builder和Lazarus连接到<b class='flag-5'>MySQL</b>数据库

    使用插件将Excel连接到MySQL/MariaDB

    使用插件将 Excel 连接到 MySQL/MariaDB 适用于 MySQL 的 Devart Excel 插件允许您将 Microsoft Excel 连接到 MySQL 或 MariaDB
    的头像 发表于 01-20 12:38 1129次阅读
    使用插件将Excel连接到<b class='flag-5'>MySQL</b>/MariaDB

    适用于MySQL和MariaDB的Python连接器:可靠的MySQL数据连接器和数据库

    适用于 MySQL 和 MariaDB 的 Python 连接器 Python Connector for MySQL 是一种可靠的连接解决方案,用于从 Python 应用程序访问 MySQL
    的头像 发表于 01-17 12:18 844次阅读
    适用于<b class='flag-5'>MySQL</b>和MariaDB的Python连接器:可靠的<b class='flag-5'>MySQL</b>数据连接器和数据库

    适用于MySQL和MariaDB的.NET连接器

    支持 ORM 的适用于 MySQL 和 MariaDB 的 .NET 连接器 dotConnect for MySQL 是一种高性能 ADO.NET 数据提供程序,可在开发 MySQL 的应用程序
    的头像 发表于 01-16 14:17 792次阅读
    适用于<b class='flag-5'>MySQL</b>和MariaDB的.NET连接器

    MySQL数据库的安装

    MySQL数据库的安装 【一】各种数据库的端口 MySQL :3306 Redis :6379 MongoDB :27017 Django :8000 flask :5000 【二】MySQL 介绍
    的头像 发表于 01-14 11:25 858次阅读
    <b class='flag-5'>MySQL</b>数据库的安装

    windows服务器备份mysql脚本

    osimport reimport datetimeimport subprocess## 需要备份数据库的登录信息mysql_host = { 'test': '10.10.3.207'}db_user
    的头像 发表于 01-02 09:14 667次阅读

    Flexus X 实例搭配华为云 EulerOS,快速部署 MySQL执行读写性能测试

    社区 openEuler 构建的 linux 操作系统,提供云原生、高性能、安全稳定的执行环境来开发和运行应用程序,助力企业客户快速上云及开发者创新 MySQL 安装与启动 原计划是通过指
    的头像 发表于 12-24 12:27 969次阅读
    Flexus X 实例搭配华为云 EulerOS,快速部署 <b class='flag-5'>MySQL</b> 并<b class='flag-5'>执行</b>读写性能测试

    MySQL 8.0/8.4执行DDL丢数据有什么影响

    Online DDL 操作。 在业务低谷时段执行DDL操作,有条件的话甚至可以在业务维护期间再执行DDL操作。 升级版本到已修复的 Per
    的头像 发表于 12-24 09:27 820次阅读
    <b class='flag-5'>MySQL</b> 8.0/8.4<b class='flag-5'>执行</b><b class='flag-5'>DDL</b>丢数据有什么影响

    数据库数据恢复—Mysql数据库表记录丢失的数据恢复流程

    Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
    的头像 发表于 12-16 11:05 1000次阅读
    数据库数据恢复—<b class='flag-5'>Mysql</b>数据库表记录丢失的数据恢复流程