网站首页 > 教程文章 正文
MySQL大表添加字段,会带来下面几个影响:
- 锁表(MDL锁)
- 主从同步延迟
- 负载较高
- 占用额外空间
由于会锁表,将会影响到正常业务处理,因此在大表加字段时,应该要慎重!!!在了解如何正确给大表加字段之前,咱们先了解了解DDL的算法和实现原理。
MySQL DDL自带的算法有3种,分别时copy,inplace和instant。
- copy算法:copy算法为最古老的算法,在 MySQL 5.5 及以下为默认算法。
- inplace算法:从 MySQL 5.6 开始,引入了 inplace 算法并且默认使用。inplace 算法还包含两种类型:rebuild-table 和 not-rebuild-table。这2个算法的区别在于是否需要rebuild表。MySQL 使用 inplace 算法时,会自动判断,能使用 not-rebuild-table 的情况下会尽量使用,不能的时候才会使用 rebuild-table。当 DDL 涉及到主键和全文索引相关的操作时,无法使用 not-rebuild-table,必须使用 rebuild-table。其他情况下都会使用 not-rebuild-table。
- instant算法:从 MySQL 8.0开始,引入了 instant 算法并且默认使用。目前 instant 算法只支持增加列等少量 DDL 类型的操作,其他类型仍然会默认使用 inplace。
copy算法-实现原理:
新建跟原表格一致的临时表,并在该临时表上执行DDL语句
锁原表,不允许DML,允许查询
逐行数据从原表拷贝到临时表中(这个过程是没有排序的)
拷贝结束后,原表禁止读操作,也就是原表此时不提供读写服务
进行rename操作,完成DDL过程
inplace算法-实现原理:
有3个阶段:prepare、execute、commit。
PREPARE
创建新的临时frm文件
持有EXCLUSIVE_MDL锁,禁止读写
根据alter类型,确定执行方式(copy,rebuild,no-rebuild)
更新数据字典的内存对象
若是需要rebuild,分配row_log对象记录的增量
若是需要rebuild, 生成新的临时ibd文件
EXECUTE
如果是仅修改元数据:
这部分无操作
其他,则是:
降低EXCLUSIVE-MDL锁,允许读写(copy 不允许写)
记录ddl执行过程中产生的增量row-log(仅rebuild类型需要)
扫描old_table的聚集索引每一条记录record
遍历新表的聚集索引和二级索引,逐一处理
根据record构造对应的索引项
将构造索引项插入sort_buffer块
将sort_buffer块插入新的索引
把row-log中的操作应用到新临时表中,应用到最后一个Block
COMMIT
升级到EXECLUSIVE-MDL锁,禁止读写
重做最后一部分的row_log增量
更新innodb的数据字典表
提交事务,写redo日志
修改统计信息
rename 临时的ibd文件、frm文件
DDL完成
instant算法-实现原理:
在增加列时,实际上只是修改了schema,并没有修改原来存储在文件中的行记录,不需要执行最耗时的rebuild和apply row log过程,因此效率非常高。
三方工具(pt-online-schema-change)-实现原理:
首先它会新建一张一模一样的表,表名一般是_new后缀
然后在这个新表执行更改字段操作
然后在原表上加三个触发器,DELETE/UPDATE/INSERT,将原表中要执行的语句也在新表中执行
最后将原表的数据拷贝到新表中,然后替换掉原表
以表格的形式,对比下这3种算法性能:
copy算法 | inplace算法 | instant算法 | |
锁表 | 基本禁止DML | prepare和commit禁止DML | 基本不会DML |
锁表耗时 | 太长 | 短暂 | 几乎不耗时 |
通过上面的分析,了解了DDL的算法和实现原理,就可以针对大表加字段制定解决方案了。
MySQL(<5.6) | MySQL(5.6~8.0) | MySQL(>=8.0) | |
DDL算法 | copy算法 | inplace算法 | instant算法 |
锁表 | 基本禁止DML | prepare和commit禁止DML | 基本不会DML |
锁表耗时 | 太长 | 短暂 | 几乎不耗时 |
大表加字段方案 | - 三方工具(pt-osc) | - 夜深人静时,直接加 - 三方工具(pt-osc) - 一次多加几个扩展字段,后面直接用 | - 直接加 |
- 上一篇: MySQL数据库入门(四)数据类型简介
- 下一篇: mysql给表增加字段
猜你喜欢
- 2025-04-26 MySQL与SQLite:如何通过DESCRIBE命令查看表结构并解决常见问题
- 2025-04-26 设计 MySQL 表的 14 条原则
- 2025-04-26 使用MySQL全文索引,我让女同事的代码快了1000倍
- 2025-04-26 mysql 替换某一个字段中的字符串
- 2025-04-26 mysql数据库——约束
- 2025-04-26 Mysql数据库替换整张表中某字段中指定的部分字符
- 2025-04-26 对线面试官:MySQL 给数据表增加一列,一定会锁表吗?
- 2025-04-26 如何确保mysql的alter语句不锁表
- 2025-04-26 MySQL字段内容拆分及合并
- 2025-04-26 MySQL笔试题-INSERT SELECT批量插入
- 最近发表
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- md5 sha1 (32)
- mybatis plus page (35)
- semaphore 使用详解 (32)
- update from 语句 (32)
- vue @scroll (38)
- 堆栈区别 (33)
- 在线子域名爆破 (32)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)