当前位置: 首页 > news >正文

MySQL 5.7 DDL 与 GH-OST 对比分析

作者:来自 vivo 互联网存储研发团队- Xia Qianyong

本文首先介绍MySQL 5.7 DDL以及GH-OST的原理,然后从效率、空间占用、锁阻塞、binlog日志产生量、主备延时等方面,对比GH-OST和MySQL5.7 DDL的差异。

一、背景介绍

在 MySQL 数据库中,DDL(数据定义语言)操作包括对表结构、索引、触发器等进行修改、创建和删除等操作。由于 MySQL 自带的 DDL 操作可能会阻塞 DML(数据操作语言)写语句的执行,大表变更容易产生主备延时,DDL 变更的速度也不能控制,因此在进行表结构变更时需要非常谨慎。

为了解决这个问题,可以使用 GitHub 开源的工具 GH-OST。GH-OST 是一个可靠的在线表结构变更工具,可以实现零宕机、低延迟、自动化、可撤销的表结构变更。相比于 MySQL 自带的 DDL 操作,GH-OST 可以在不影响正常业务运行的情况下进行表结构变更,避免了 DDL 操作可能带来的风险和影响。

通过使用 GH-OST工具,可以对 MySQL 数据库中的表进行在线结构变更,而不会对业务造成太大的影响。同时,GH-OST 工具还提供了多种高级特性,如安全性检测、自动化流程等,可以帮助用户更加高效地进行表结构变更。

二、MySQL5.7几种DDL介绍

2.1 copy

  • server层触发创建临时表

  • server层对源表加MDL锁,阻塞DML写、不阻塞DML读

  • server层从源表中逐行读取数据,写入到临时表

  • 数据拷贝完成后,升级字典锁,禁止读写

  • 删除源表,把临时表重命名为源表

MySQL copy方式的DDL变更,数据表的重建(主键、二级索引重建),server层作为中转把从innodb读取数据表,在把数据写到innodb层临时表。简单示意图如下:

图片

2.2 inplace

(1)rebuild table

需要根据DDL语句创建新的表结构,根据源表的数据和变更期间增量日志,重建新表的主键索引和所有的二级索引。

Prepare阶段

  • 创建新的临时frm文件

  • 持有EXCLUSIVE-MDL锁,禁止读写

  • 根据alter类型,确定执行方式(copy,online-rebuild,online-norebuild)假如是Add Index,则选择online-norebuild

  • 更新数据字典的内存对象

  • 分配row_log对象记录增量

  • 生成新的临时ibd文件

ddl执行阶段 :

  • 降级EXCLUSIVE-MDL锁,允许读写

  • 扫描old_table的聚集索引每一条记录rec

  • 遍历新表的聚集索引和二级索引,逐一处理各个索引

  • 根据rec构造对应的索引项

  • 将构造索引项插入sort_buffer块排序

  • 将sort_buffer块更新到新表的索引上

  • 记录ddl执行过程中产生的增量(记录主键和索引字段)

  • 重放row_log中的操作到新表索引商

  • 重放row_log间产生dml操作append到row_log最后一个Block

commit阶段 :

  • 当前Block为row_log最后一个时,禁止读写,升级到EXCLUSIVE-MDL锁

  • 重做row_log中最后一部分增量

  • 更新innodb的数据字典表

  • rename临时idb文件,frm文件

  • 增量完成

MySQL rebuild table方式的DDL,数据不需要通过sever层中转,innodb层自己完成数据表的重建。简单示意图如下:

图片

(2)build-index

需要根据DDL语句创建新的表结构,根据源表的数据和变更期间增量日志,创建新的索引。

Prepare阶段 :

  • 持有EXCLUSIVE-MDL锁,禁止读写

  • 根据alter类型,确定执行方式(copy,online-rebuild,online-norebuild)

  • 假如是Add Index,则选择online-norebuild

  • 更新数据字典的内存对象

  • 分配row_log对象记录增量

ddl执行阶段 :

  • 降级EXCLUSIVE-MDL锁,允许读写

  • 扫描old_table的聚集索引每一条记录rec

  • 遍历新表的聚集索引,根据rec构造新的索引数据

  • 将构造索引项插入sort_buffer块排序

  • 将sort_buffer块更新到新表的索引上

  • 记录ddl执行过程中产生的增量(仅记录主键和新索引字段)

  • 重放row_log中的操作到新表索引上

  • 重放row_log间产生dml操作append到row_log最后一个Block

commit阶段 :

  • 当前Block为row_log最后一个时,禁止读写,升级到EXCLUSIVE-MDL锁

  • 重做row_log中最后一部分增量

  • 更新innodb的数据字典表

  • 增量完成

MySQL rebuild index方式的DDL,数据不需要通过sever层中转,innodb层只需要完成变更二级索引的创建。简单示意图如下:

图片

(3)only modify metadata

只修改元数据(.frm文件和数据字典),不需要拷贝表的数据。

图片

三、GH-OST

在GH-OST端,根据DDL语句创建新的表结构,根据源表的数据和增量期间增量日志,重建新表的主键索引和所有的二级索引,最终完成DDL增量。

主要流程如下:

  • 根据DDL语句和源表创建新的表结构

  • 根据唯一索引(主键索引或者其它唯一索引)

- 优先应用新增量的binlog到新的表中,需要经过GH-OST把binlog日志转换为sql,然后回放到影子表

- 其次拷贝源表中的数据到新的表中,表数据拷贝通过sql语句 insert ignore into (select .. from)直接在MySQL实例上执行,无需经过GH-OST中转

  • 数据拷贝完成并应用完binlog后,通过lock table write 锁住源表

  • 应用数据完成-获取到锁期间产生的增量binlog

  • delete源表,rename影子表为源表,完成数据增量

GH-OST 进行DDL变更,GH-OST服务通知server层,server层作为中转把从innodb读取数据表,在把数据写到innodb层影子表。并且GH-OST作为中转读取DDL变更期间增量binlog解析成SQL写语句回放到影子表。简单示意图如下:

图片

四、对比分析

DDL变更执行时长、对磁盘的额外占用(临时数据表+binlog)、锁阻塞时长、主备延时都是执行DDL变更人员比较关心的问题,本章将从从执行效率、占用表空间、锁阻塞、产生binlog日志量、主备延时等方面对MySQL原生的DDL和GH-OST进行对比分析。

4.1 执行效率

(1)only modify metadata(正常小于1S)

(2)build-index: 数据条目越多、新索引字段越大耗时越多

  • 增量日志超过innodb_online_alter_log_max_size造成DDL失败

(3)rebuild table: 数据条目越多、所有索引字段之和越大耗时越多

  • 增量日志超过innodb_online_alter_log_max_size造成DDL失败

(4)copy:数据条目越多,所有索引字段之和越大耗时越多,相对于rebuild table,数据需要从server层中转,所以比rebuild table耗时多

(5)GH-OST :数据条目越多,所有索引字段之和越大耗时越多,

  • 相对于copy,增量日志数据需要从GH-OST中转,所以比copy耗时多

  • 有各种限流,(主备延时,threads超限延时…),增加耗时

  • 增量期间应用binlog速度如果跟不上业务产生binlog日志的速度,将无法完成增量

  • critical 参数还会导致主动退出,例如thread_running

耗时:only modify metadata < build-index < build < copy < GH-OST

4.2 占用表空间

  • 【only modify metadata】:忽略

  • 【build-index】:额外需要,新增索引字段占用的空间

  • 【rebuild-table】:额外需要约两倍的表空间

  • 【copy】:额外需要约两倍的表空间

  • 【GH-OST】 :临时表占用约两倍的表空间,另外生成影子表会产生大量的binlog日志会占用表空间

占用表空间: only modify metadata < build-index < build = copy < GH-OST

4.3 锁阻塞

(1)only modify metadata

  • DDL prepare阶段短暂的MDL排他锁,阻塞读写

(2)build-index table

  • DDL prepare阶段短暂的MDL排他锁,阻塞读写

  • 执行阶段(主要耗时阶段),MDL SHARED_UPGRADABLE锁,不阻塞读写

  • 执行阶段的最后会回放增量日志row_log,两个block间隙和最后block,持有源表索引的数据结构锁,会阻塞写

  • 提交阶段,MDL锁升级为排他锁

  • 回放剩余的row_log(执行完成致MDL锁升级期间新增的row_log,持有源表索引的数据结构锁,阻塞读写)

(3)rebuild-table: 和build-index table一致

(4)copy

  • DDL prepare阶段短暂的MDL排他锁,阻塞读写

  • 执行阶段(主要耗时阶段),阻塞写,不阻塞读

(5)GH-OST

  • 等待锁的时间也会阻塞业务

  • 进入rename到拿表写锁的间隙有少量的新增binlog,后续需要持锁回放这部分日志

  • rename表本身的耗时通常1s以内左右

锁阻塞时间:

only modify metadata=GH-OST < build-index table = rebuild-table  < copy(整个DDL期间都会阻塞业务的写)

锁阻塞分析:

MySQL DDL在获取MDL排它锁和GH-OST获取表的的写锁,在获取锁的等待期间都会阻塞业务的读写

  • MySQL等待锁的超时时间为MySQL参数innodb_lock_wait_timeout。等待超时则失败

  • GH-OST等待锁的时间,等待超时时间可配(默认6秒),等待超时次数可配

4.4 产生binlog日志量

【MySQL5.7 DDL】: 在DDL执行结束时仅向binlog中写入一条DDL语句,日志量较小。

【GH-OST】: 影子表在全量数据拷贝和增量数据应用过程中产生大量的binlog日志(row模式),对于大表日志量非常大。

产生binlog日志量:MySQL5.7 DDL < GH-OST

4.5 主备延时分析

(1)MySQL5.7 DDL:MySQL集群主备环境

  • Master上DDL执行完成,binlog提交后,slave才开始进行DDL。

  • slave串行复制、group复制模式,需要等前面的DDL回放完成后才会进行后续binlog回放,主备延时至少是DDL回放的时间。

图片

(2)GH-OST:主备复制延时基本可以忽略

  • GH-OST在master上创建一个影子表,在执行数据拷贝和binlog应用阶段,GHO表的binlog会实时同步到备。

  • 影子表(_GHO表)应用完成后,通过rename实现新表切换,这个rename动作也会通过binlog传到salve执行完成DDL。

图片

延时时间:GH-OST < MySQL DDL

备库执行DDL期间主库异常,主备切换。备库升级为主过程中,要回放完relaylog中的DDL和dml,才能对外服务,否则会出现数据丢失,这将造成业务较长时间的阻塞。

4.6 总结

图片

GH-OST 工具和 MySQL 原生 DDL 工具的适用场景不同,具体使用哪种工具需要根据实际需求进行选择。

  • 变更人员无法判断本次DDL是否会造成DML阻塞、锁阻塞等,建议使用GH-OST工具。

  • 如果需要进行在线表结构变更,并且需要减少锁阻塞时间、减少主备延时等问题,建议使用 GH-OST 工具。

  • 变更只涉及到元数据的修改,建议使用mysql原生DDL。

  • 如果表结构变更较小,对锁阻塞时间和主备延时要求不高,建议使用 MySQL 原生 DDL 工具。

参考资料:

  • online DDL Operations

  • MySQL · 源码阅读 · 白话Online DDL

  • 【腾讯云CDB】源码分析·MySQL online ddl日志回放解析 

  • GH-OST一些使用限制

  • mysql mdl锁类型

相关文章:

MySQL 5.7 DDL 与 GH-OST 对比分析

作者&#xff1a;来自 vivo 互联网存储研发团队- Xia Qianyong 本文首先介绍MySQL 5.7 DDL以及GH-OST的原理&#xff0c;然后从效率、空间占用、锁阻塞、binlog日志产生量、主备延时等方面&#xff0c;对比GH-OST和MySQL5.7 DDL的差异。 一、背景介绍 在 MySQL 数据库中&…...

【Python】爬取网易新闻今日热点列表数据并导出

1. 需求 从网易新闻的科技模块爬取今日热点的列表数据&#xff0c;其中包括标题、图片、标签、发表时间、路径、详细文本内容&#xff0c;最后导出这些列表数据到Excel中。 网易科技新闻网址&#xff1a;https://tech.163.com 2. 解决步骤 2.1 前期准备 爬虫脚本中需要引用…...

软件设计之HTML5

软件设计之HTML5 【狂神说Java】HTML5完整教学通俗易懂 学习内容&#xff1a; 软件开发技能点参照&#xff1a;软件开发&#xff0c;小白变大佬&#xff0c;这套学习路线让你少走弯路是认真的&#xff0c;欢迎讨论 软件开发技能点参照&#xff1a;Java学习完整路线&#xff…...

CnosDB 元数据集群 – 分布式时序数据库的大脑

CnosDB 是一个分布式时序数据库系统&#xff0c;其中元数据集群是核心组件之一&#xff0c;负责管理整个集群的元数据信息。 1. 概述 CnosDB 是一个分布式时序数据库系统&#xff0c;其中元数据集群是核心组件之一&#xff0c;负责管理整个集群的元数据信息。元数据包括数据库…...

白骑士的Matlab教学进阶篇 2.5 Simulink

Simulink是MATLAB的扩展工具&#xff0c;提供了一个图形化的建模和仿真环境。它广泛应用于系统设计、仿真、自动控制、信号处理等领域。本文将详细介绍Simulink的简介与基本使用、建立与仿真模型、控制系统设计与仿真、与MATLAB的集成。 Simulink简介与基本使用 什么是Simuli…...

linux安装anaconda

参考 如何在Linux服务器上安装Anaconda&#xff08;超详细&#xff09;_linux安装anconda-CSDN博客 官网 Index of / 安装网站 https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Lin…...

python装饰器作用和使用场景

当谈到装饰器时&#xff0c;很多初学者很迷糊&#xff0c;有一个经典的例子可以帮助理解它们的作用。装饰器允许你在不修改函数代码的情况下&#xff0c;动态地改变函数的行为。 一、用法 假设我们有一个简单的函数&#xff0c;用来输出一条简单的问候语&#xff1a; 复制代码…...

Apache Tomcat 7下载、安装、环境变量配置 详细教程

Apache Tomcat 7下载、安装、环境变量配置 详细教程 Apache Tomcat 7下载Apache Tomcat 7 安装Apache Tomcat 7 环境变量配置启动 Apache Tomcat 7测试Tomcat7是否启动成功 Apache Tomcat 7下载 1、下载地址&#xff0c;找到Archives 链接: 官网下载地址 2、找到Tomcat 7&…...

SQL注入实例(sqli-labs/less-20)

0、初始页面 1、确定闭合字符 2、爆库名 3、爆表名 4、爆列名 5、查询最终目标...

Linux Shell面试题大全及参考答案(3万字长文)

目录 解释Shell脚本是什么以及它的主要用途 主要用途 Shell脚本中的注释如何编写? 如何在Shell脚本中定义和使用变量? Shell支持哪些数据类型? 什么是Shell的命令替换?请举例说明。 管道(pipe)和重定向(redirection)有什么区别? 如何在Shell脚本中使用条件语句…...

速盾:cdn优化静态资源加载速度机制

CDN&#xff08;Content Delivery Network&#xff09;是一种优化静态资源加载速度的机制。它通过在全球多个地点部署服务器&#xff0c;将静态资源缓存到离用户最近的服务器上&#xff0c;从而提高资源加载速度。 在传统的网络架构中&#xff0c;当用户访问一个网站时&#x…...

04.C++类和对象(中)

1.类的默认成员函数 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数。一个类&#xff0c;我们不写的情况下编译器会默认生成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前4个&#xff0c;最后两个取地址重载不重…...

【代码随想录训练营第42期 Day23打卡 回溯Part2 - LeetCode 39. 组合总和 40.组合总和II 131.分割回文串

目录 一、做题心得 二、题目与题解 题目一&#xff1a;39. 组合总和 题目链接 题解&#xff1a;回溯 题目二&#xff1a;40.组合总和II 题目链接 题解&#xff1a;回溯 题目三&#xff1a;131.分割回文串 题目链接 题解&#xff1a;回溯 三、小结 一、做题心得 今天是代码随想录…...

书生.浦江大模型实战训练营——(三)Git基本操作与分支管理

最近在学习书生.浦江大模型实战训练营&#xff0c;所有课程都免费&#xff0c;以关卡的形式学习&#xff0c;也比较有意思&#xff0c;提供免费的算力实战&#xff0c;真的很不错&#xff08;无广&#xff09;&#xff01;欢迎大家一起学习&#xff0c;打开LLM探索大门&#xf…...

数据可视化Axure大屏原型制作分享

数据可视化大屏通过清晰、直观且易于理解的方式呈现大量复杂数据&#xff0c;已成为各行各业中不可或缺的工具。Axure作为一款功能强大的原型设计工具&#xff0c;为数据可视化大屏的制作提供了强大的支持和丰富的资源。 Axure RP 是一款强大的原型设计工具&#xff0c;非常适…...

Python3安装

更新镜像&#xff1a; yum -y install epel-release.noarch 1.安装Python3 [root18 ~]# yum -y install python3 2.查看版本&#xff1a; [root18 ~]# python3 --version Python 3.6.8 3.执行镜像包&#xff1a; pip3 install -i https://pypi.tuna.tsinghua.edu.cn/sim…...

基于Python的数据科学系列(4):函数

引言 在前几篇文章中&#xff0c;我们探讨了Python中的基本数据类型、列表、元组和字典。在本文中&#xff0c;我们将深入研究Python中的函数。函数是编程中非常重要的概念&#xff0c;它允许我们将代码组织成模块化、可重用的组件。通过学习如何定义和使用函数&#xff0c;我们…...

高频焊接设备配电系统无源滤波系统的设计

1、高频焊机系统谐波状况简介 变压器容量&#xff1a;S11-M-1600/10KVA&#xff08;105%&#xff09;/0.4KV 短路阻抗&#xff1a;3.9% 谐波负载情况&#xff1a;一台600KW高频焊接设备 型号&#xff1a;GGP600-0.3-HC 输入电压&#xff1a;380V 输出电压&#xff1a;0…...

模拟退火的

题目链接 体验乱调参数而看天意的奇特体验 #include<bits/stdc.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<ll,ll> pii; const int inf0x3f3f3f3f; const int N1e510; const int mod1e97; //#define int long…...

为什么有的地方笔记本经常连不上wifi,而手机可以?

mm&#xff1a;程程&#xff0c;为什么我的笔记本在图书馆&#xff0c;老是连不上wifi&#xff1f;经常要手工连好几次&#xff0c;我的手机却没有这样的问题。 我&#xff1a;你先用手机热点连一下&#xff0c;我给你远程看一下吧。 mm&#xff1a;好了&#xff0c;我的远程代…...

组件化开发

iOS的组件化开发是一种将大型应用拆分成多个独立、可复用的组件的开发模式。每个组件负责完成特定的功能&#xff0c;并通过明确定义的接口与其他组件进行交互。这种开发模式有助于提高代码的可维护性、可读性和可扩展性&#xff0c;同时降低模块之间的耦合度。 组件化开发的概…...

java学习--文件

简介 文件,对我们并不陌生,文件是保存数据的地方,比如大家经常使用的word文档,txt文 件,excel文件 ... 都是文件。它既可以保存一张图片,也可以保持视频,声音 …. 文件流 常用的文件操作 创建文件的对象相关构造器和方法 示范 方式一&#xff1a; 方式二&#xff1a; 老师演示…...

k8s—Prometheus+Grafana+Altermaneger构建监控平台

目录 一、安装node-exporter 1.下载所需镜像 2.编写node-export.yaml文件并应用 3.测试node-exporter并获取数据 二、Prometheus server安装和配置 1.创建sa(serviceaccount)账号&#xff0c;对sa做rabc授权 1&#xff09;创建一个 sa 账号 monitor 2&#xff09;把 sa …...

Dijkstra算法求解最短路径 自写代码

#include <iostream> #define Max 503 #define INF 0xcffffffusing namespace std;typedef struct AMGraph { //定义图int vex, arc;int arcs[Max][Max]; //邻接矩阵 };int dist[Max], path[Max]; //dis保存最短路径总权值、path通过保存路径的前驱结…...

C#如何对某个词在字符串中出现的次数进⾏计数(LINQ)

文章目录 基础知识实现方法基础计数LINQ优化处理标点符号总结 LINQ&#xff08;Language-Integrated Query&#xff09;是C#和VB.NET中强大的查询语言&#xff0c;它可以用来查询集合、SQL数据库、XML文档等。在C#中&#xff0c;我们可以使用LINQ来简化对字符串中特定单词出现次…...

Linux篇之OS层内核参数的调优

Linux内核参数调优 Linux 内核参数的调优和分类是一个复杂的主题&#xff0c;这涉及到系统性能、稳定性和安全性等多个方面。 内核参数主要可以分为以下几类&#xff1a; 1. 内核参数的分类 1.1 系统性能参数 这些参数影响系统的整体性能&#xff0c;包括 CPU 调度、内存管理…...

DLMS/COSEM中的信息安全:安全密钥(上)

加密密钥是一个参数,和加密算法一起使用,加密算法决定了这样一种方式,带有密钥的实体,可以重现和进行逆操作,而没有密钥则不能。对DLMS/COSEM的用途,操作的例子包含: ——明文转换成密文; ——密文转换成明文; ——计算和验证认证码(MAC); …...

Taro基础知识学习

一、安装及使用 CLI工具安装 需要使用 npm 或者 yarn 全局安装 tarojs/cli //使用 npm 安装 CLI npm install -g tarojs/cli//使用 yarn 安装 CLI yarn global add tarojs/cli//使用 cnpm 安装 CLI cnpm install -g tarojs/cli//使用npm info查看Taro的版本信息 npm info ta…...

浮点型在内存中的存储

前言 在上一期中我们讲到了有关于整型在内存中的存储&#xff0c;新朋友可以点开&#x1f517;了解一下&#xff0c;那这一期中我们将讲到的浮点数是不是存储方式和整型一致呢&#xff1f; 一、浮点数在内存中的存储 为了探究这个问题我们先来看一段代码 #include<stdio…...

微信小程序之behaviors

目录 概括 Demo演示 进阶演示 1. 若具有同名的属性或方法 2. 若有同名的数据 3. 若有同名的生命周期函数 应用场景 最后 属性&方法 组件中使用 代码示例&#xff1a; 同名字段的覆盖和组合规则 概括 一句话总结: behaviors是用于组件间代码共享的特性, 类似一…...