MySQL的在线模式学习笔记
wptr33 2025-08-03 08:47 2 浏览
什么是在线模式(ONLINE DDL)?
“在线模式 / 离线模式”是 MySQL 专门为 DDL 设计的术语。ONLINE DDL 定义其实就是在执行 DDL 语句时,不会阻塞 DML 语句,那么我们就称这样的 DDL 为ONLINE DDL。
什么是离线模式?
**离线模式** 是指在 MySQL 5.5 及更早版本中执行 DDL 操作时,表会被完全锁定,所有读写操作将被阻塞,直到操作完成。在离线 DDL 执行期间,需要修改的表会被完全锁定,这意味着所有对该表的读写操作都会被阻塞,直到 DDL 操作完成。由于表被锁定,任何依赖该表的应用程序都将无法正常工作,导致服务中断或延迟。对于高并发、7x24小时运行的线上系统而言,这种长时间的停机是不可接受的。
**在线模式** 是 MySQL 5.6 及更高版本引入的 重大改进 ,旨在解决离线模式带来的服务中断问题。它的核心思想是 允许在 DDL 操作进行的同时,对表进行并发的读写操作 ,从而最大程度地保证数据库的可用性。
#技术分享以下内容来自:MySQL Reference Manual — Online DDL Operations
在线 DDL 功能提供对原地表修改和并发 DML 的支持。此功能的优势包括:
- 在繁忙的生产环境中提高响应能力和可用性,因为使表不可用几分钟或几小时是不切实际的。
- 能够在 DDL 操作期间使用 LOCK 子句调整性能和并发之间的平衡。参见 LOCK 子句 。
- 比表复制方法使用的磁盘空间更少,I/O 开销也更小。
通常,您无需执行任何特殊操作即可启用在线 DDL。默认情况下,MySQL 在允许的情况下就地执行操作,并尽可能减少锁定。
您可以使用 ALGORITHM 和 LOCK 语句的子句来控制 DDL 操作的各种方面。这些子句位于语句的末尾,通过逗号与表和列规范分开。例如:
ALTER TABLE tbl_name ADD PRIMARY KEY (column), ALGORITHM=INPLACE, LOCK=NONE;
版本演进
MySQL Online DDL 功能自 5.6 版本正式引入,并在后续版本不断完善:
- MySQL 5.5 :MySQL 5.5 及之前,所有的 DDL 操作都是全程锁表(LOCK = EXCLUSIVE),仅支持 Fast Index Create(快速索引创建)。此时对 二级索引的增删 操作可以使用 Inplace 算法,从而避免重建整个表,但仍需对表加锁,阻塞写操作。其他变更仍只能采用复制表的方式。但是因为实现的问题,依然会阻塞 INSERT、UPDATE、DELETE 操作,造成的问题是:如果是在业务高峰期执行一条 DDL 语句,往往有明显的业务中断,从而出现直接引发“雪崩报警”,这也是 MySQL 早期版本长期被吐槽的原因之一。
- MySQL 5.6 :正式引入 Online DDL 概念,官方显著增加了可在线的 ALTER TABLE 类型,并允许在 DDL 执行时并发 DML,支持在不阻塞并发 DML 的情况下添加索引、修改自增值等操作。旨在显著减少(或消除)更改数据库对象所需的应用程序停机时间(该特性以下统称 Online DDL),从而减少重建表的需要。不过,并非所有 DDL 都支持在线模式,具体支持可以参考 各版本支持的详细情况 章节。
- MySQL 5.7 :在 5.6 的基础上扩展了对更多 DDL 操作的在线支持,例如支持在线重命名索引、在线增减数值类型长度、在线扩展 VARCHAR 长度等操作。但整体实现逻辑与 5.6 相似,依旧采用 Copy 和 Inplace 两种方式。
- MySQL 8.0 :大幅重构了 DDL 执行引擎,支持原子性 DDL(失败可回滚),并新增 ALGORITHM=INSTANT 算法。在 8.0.12+ 中,支持将列“秒加”到表的末尾,无需重建表;8.0.29 起 Instant 算法成为默认,可在任意位置添加或删除列。同时,MySQL 8.0 对 ALTER TABLE操作进行了重构与优化,引入 LOCK=NONE|SHARED|EXCLUSIVE 参数来更灵活地控制锁粒度和并发行为。
MySQL Online DDL详解:从历史演进到原理及使用
MySQL 8.0 新特性之 DDL 即时加列
Online DDL 解决的问题
Online DDL 的核心在于让 DDL 操作与 DML(查询/增删改)并发执行,从而避免长时间锁表。
原理
MySQL Online DDL 的底层实现主要依赖三种算法:COPY 、INPLACE ,以及在 MySQL 8.0.12+ 中引入的 INSTANT 。
- 复制表法(Copy Table)
COPY 是 Online DDL 中最常见的一种实现方式,它在后台模拟了传统 DDL 的重建流程。但在后台进行,从而减少了对在线业务的影响。其核心步骤如下:
- **创建临时表:** MySQL会创建一个与原始表结构相同的新临时表。
- **复制数据:** 将原始表中的数据复制到临时表中。 在数据复制期间,所有对原始表的 DML(数据操作语言)操作(INSERT、UPDATE、DELETE) 都会被捕获并记录为增量变更。
- **应用增量变更:** 当数据复制完成后,MySQL会暂停对原始表的DML操作一小段时间,然后将复制期间记录的所有增量DML操作应用到临时表上。
- **原子性替换:** 最后,MySQL会通过原子性的操作将原始表重命名,并将临时表重命名为原始表的名称。这个替换操作通常非常快,对业务的影响极小。
这种方式的优点是实现简单,兼容性好,但缺点是需要额外的磁盘空间(至少是原始表大小的一倍),并且在数据复制期间会消耗 CPU 和 I/O 资源。
- 原地变更法(In-Place)
对于某些特定的 DDL 操作(如添加、删除或重命名列,添加或删除索引等),MySQL 可以采用更高效的“原地变更”方式,即直接在原表上进行修改,而不需要创建临时表和复制数据。这种方式的效率更高,对系统资源的消耗更小,因为它避免了大量的数据复制。
原地变更的实现机制通常涉及对表的数据文件和索引文件进行直接修改。例如,添加新列可能只需要修改表的元数据信息,而不需要重写所有行数据。然而,并不是所有的 DDL 操作都能使用原地变更。
| 1 | 创建 frm(表结构定义文件)临时文件 | | ---
| 2 | 锁原表,不允许 DML(数据操作语言),允许查询 | | 3 | 根据聚集索引顺序构建新的索引项,按照顺序插入新的索引页 | | 4 | 原表升级锁,禁止读写,即原表暂停服务 | | 5 | rename 操作,替换原表的 frm 文件 |
根据是否需要重建表结构,又分为两种情况:
- 需要重建(Rebuild) :如添加索引、添加/删除列、修改列的 NULL 属性等操作需要重新组织聚簇索引。在此过程中,InnoDB 会后台构建新的表数据,同时缓存并发执行的 DML 操作。DDL 完成后再将缓存的 DML 增量应用到表上,实现变更和业务并行。
- 无需重建(No-Rebuild) :如删除索引、修改列名或默认值、修改自增值等操作只需更新表元数据即可,不改动行数据。
在 INPLACE 算法下,InnoDB 仍会对原表加元数据锁(MDL)以保证一致性:在数据转换阶段通常加 MDL 读锁(允许 DML,但不允许其他 DDL),在最后合并增量时加 MDL 写锁(阻止并发 DDL/DML)。由于数据并未真正移动到外部临时表,该过程对服务器来说是“原地”操作,减少了 IO 和空间开销。
- INSTANT 算法
只支持极少数简单操作(如修改字符集或在表末尾添加列)。此时 MySQL 仅修改数据字典中的元数据条目,不对表数据作任何变动,也无需表锁。由于仅更新元信息,所以 DDL 几乎瞬间完成,对业务没有任何阻塞。例如,MySQL 8.0.12 引入了 Instant 算法用于快速加列(仅限末尾列),8.0.29 起将其作为默认算法并支持任意位置添加和快速删除列。
说明: 在 Online DDL 过程中,为了保证数据一致性,MySQL 会对原表加上短暂的元数据锁。如在 COPY 或 INPLACE 的复制阶段对原表加 MDL 读锁,在应用增量阶段加 MDL 写锁;在最终替换表结构时,会再短暂地加独占锁重命名表。通过这种方式,Online DDL 保证了在大部分时间内业务可并发访问,只有在关键切换点才加锁。
关键参数: ALGORITHM 和 LOCK
在 ALTER TABLE 语句中,我们可以通过 ALGORITHM 和 LOCK 子句来控制 DDL 操作的行为:
- ALGORITHM : 指定DDL操作的算法,可选值有:
- INPLACE : 尝试原地变更,如果不支持则报错。
- COPY : 强制使用复制表法。
- INSTANT : (MySQL 8.0引入)某些操作可以在瞬间完成,无需重建表。
- DEFAULT : MySQL会自动选择最佳的算法,优先使用 INPLACE 的方式。
- LOCK : 指定DDL操作的锁定级别,可选值有:
- NONE : 允许并发读写。
- SHARED : 共享锁,允许并发读,但禁止并发写。
- EXCLUSIVE : 独占锁,禁止并发读写,指定 DDL 的表将被完全锁定,无法执行任何读写操作。
- DEFAULT : MySQL会自动选择最佳的锁定级别。
通常情况下,我们应该尽量选择 ALGORITHM=INPLACE 和 LOCK=NONE ,以实现最少的锁定和最高的可用性。
使用示例
在 ALTER TABLE 语句中,可以通过 ALGORITHM 和 LOCK 子句来启用和控制在线 DDL。例如,官方文档示例中提到使用原地算法:
ALTER TABLE tbl_name ADD PRIMARY KEY (col), ALGORITHM = INPLACE;
用户可以按需设置:如以下命令示例在添加列时尽量使用原地算法并允许并发读写:
ALTER TABLE mytable ADD COLUMN new_col INT DEFAULT 0 ALGORITHM = INPLACE, LOCK = NONE;
上述命令尝试在原表上增列并同时允许并发读写 developer.aliyun.com 。对于 MySQL 8.0.12 及以上版本,也可指定 ALGORITHM=INSTANT (仅限支持 Instant 的操作)来实现几乎即时的变更:
ALTER TABLE mytable ADD COLUMN new_col2 INT DEFAULT 1 ALGORITHM = INSTANT;
需要注意,Instant 算法仅支持在允许的位置(例如末尾)添加或删除列 MySQL 8.0 新特性之 DDL 即时加列 ;如果不指定算法(或指定 ALGORITHM=DEFAULT ),MySQL 会优先尝试 INPLACE,不行时回退到 COPY 模式
注意事项
集群模式下存在问题
在 Master-Slave 架构下,官方的 Online DDL 存在致命的缺陷,所以我们只能转向第三方工具。这里有 Percona 的公司的 pt-osc,是基于触发器的 Online DDL 的代表。以及比较新的,Github 的 gh-ost,是基于 Binlog 的。
gh-ost(Binlog 增量同步,无触发器)
pt-online-schema-change(触发器方式)
MySQL Online DDL 探究
针对生产环境,对于需要频繁读写的”大表“,执行 DDL 操作时,不推荐使用 MySQL 的在线模式 ,推荐使用第三方工具:
github.com/github/gh-o…
github.com/percona/per…
docs.percona.com/percona-too…
C Reference
MySQL Online DDL 详解:从历史演进到原理及使用
mysql 大表如何 ddl
dev.mysql.com/doc/refman/…
各版本支持的详细情况
doc.yonyoucloud.com/doc/mysql-5…
dev.mysql.com/doc/refman/…
dev.mysql.com/doc/refman/…
相关推荐
- MySql系列-常用命令
-
本篇是对...
- Record.ToTable 格式转换
-
本期案例对表格格式进行转换,前后转换效果如下:解题套路1.Record.ToTable解题思路:思路就是构造可以透视的样式。使用Record.ToTable对行记录进行转换,获得包含两列的表,首行可以...
- Table.Group 按时期累计计算唯一值
-
本期案例是根据不同id进行汇总统计:组内,相同日期的为一组,统计“from”、“to”中的非重复个数;连续日期的,统计累计数。前后转换效果如下:解题套路1.Table.Group...
- MySQL 9.1正式发布,有哪些值得关注的新特性?
-
MySQL创新版9.1.0于2024年10月15日正式发布。此外,MySQL8.0.40及8.4.3补丁版本也同时发布。8.4.3是目前MySQL的LTS长期支持版本,该版本中将不会增加新的功能与特性...
- SQL基本语句练习(基础版)
-
最近在学习SQL基本语句的练习,在此分享一下笔者做过的练习以及个人的解决教程:首先是基本练习表格的搭建,具体内容如下表所示:...
- SQL 从入门到精通:全面掌握数据库操作
-
学习SQL(StructuredQueryLanguage)是掌握数据库操作的关键步骤。SQL是一种用于管理和处理关系型数据库的标准语言,广泛应用于数据检索、插入、更新和删除等操作。以下是一些...
- ClickHouse学习笔记四ClickHouse基础语法
-
前言这里我们介绍ClickHouse的基本语法,使用环境是腾讯云的ClickHouse。默认情况下,ClickHouse在进行集群纬度执行建表等DDL操作时需要手动添加ONCLUSTERX...
- 程序员总结的常用sql语句大全
-
多年经验程序员总结的我们一般需要使用的sql语句,赶快收藏起来,方便以后使用。以下是一些常用的SQL语句及其用法:一、数据定义语言(DDL)创建库CREATEDATABASE:创建一个新数据库。...
- PQ03-分组求和
-
目标已知:销售清单求:每个销售员的销量合计方法数据准备...
- 好荐:一款数据库元数据管理平台工具
-
“元数据”的定义在不同的软件、项目、工程的定义范围都不太一样。本文这里指的是软件项目开发使用的数据库表结构信息。我今天介绍的这个开源项目叫Databasir,它是一个面向团队的关系型数据库模型文档管理...
- MySQL 8.0 SQL优化黑科技,面试官都不一定知道!
-
前言提到SQL优化,大多数人想到的还是那些经典套路:建索引、避免全表扫描、优化JOIN顺序…这些确实是基础,但如果你还停留在MySQL5.7时代的优化思维,那就out了。MySQL8.0已经发布好...
- MySQL数据库深度优化指南:从基础到架构层面的20个关键策略
-
一、核心性能优化原则数据最小化原则...
- 动物源性食品中兽药残留的检测——喹啉类药物残留
-
喹啉类药物(quinoxaline)是具有喹啉-N1,N4-二氧化物基本结构的一类化学合成的动物专用药,具有广谱抗菌、提高饲料转化率和促生长作用。1965年德国拜耳公司以邻硝基苯胺为原料合成喹乙醇(o...
- 适合普通开发者和产品经理的PHP应用模板开发AI的SaaS应用框架
-
简单到傻!Liang_SaaS适合普通开发者和产品经理的PHP应用模板开发AI的SaaS应用框架,利用Php开发AI的SaaS应用框架,是一个强大的内容管理仪表板模板,基于Bootstrap和...
- Power Query 交错合并表格的方法
-
两张表格合并成一张表格,需要交错排列,表1取一行,表2取一行,这样排列在一起:前提是两张表的行数相同,内容排列顺序相同:我们来看两张表:表1:12列10行表2:11列10行行数相同列数不同,我们在数据...
- 一周热门
-
-
因果推断Matching方式实现代码 因果推断模型
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
git pull命令使用实例 git pull--rebase
-
git 执行pull错误如何撤销 git pull fail
-
面试官:git pull是哪两个指令的组合?
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)