Mysql Scheme 变更|小册免费学

436 阅读3分钟

这个部分也是日常开发中很常见的问题。在数据量在的情况下,我们修改表结构,会发生什么?

DDL

DDL定义了数据在数据库中的结构、关系以及权限等。比如 CREATE,ALTER,DROP 这些

既然是定义啊,其实 DDL 的作用就是改变表结构,那么问题来了:表结构在 InnoDB 下是什么样的?

  1. 数据 ==> 索引即数据,Innodb 中存储的数据其实就是按照聚簇索引排列的
  2. 每一行数据依次排列

第一个问题:我现在要加一列?

  1. 要在每一行都加一列
  2. 修改表空间中的元数据
  3. 重建索引

等同于我需要重建一整张表,这个可想而之时非常高昂的!

Scheme 变更

说几个我们可以想到的方案:

  1. 直接 alter table ,数据少并不会造成太长时间的锁表
  2. 停机就完事~~~。停机升级~~~。【是不是juejin以前干过这种事】
  3. 在线淦

最后一个其实才是我们日常最多遇到的情况。最核心的问题是:

  1. 用户数据在业务运行中也在产生,这部分数据一定要保存
  2. 操作不能对现有的数据产生影响

所以可以想到的做法,也是早期 mysql 的做法是:

DDL 操作(如创建索引等)通常都需要对数据表加锁,操作过程中 DML 操作都会被阻塞,影响正常业务。

既然新来的数据会影响,那干脆就直接拒绝掉,等我重建完再来接受请求。

Online DDL

MySQL 5.6 开始支持 Online DDL,可以在执行 DDL 操作的同时,不影响 DML 的正常执行,线上直接执行 DDL 操作对用户基本无感知(部分操作对性能有影响)。

ALTER TABLE 语句中,支持通过 ALGORITHMLOCK 语句来实现 Online DDL:

  • ALGORITHM - 控制 DDL 操作如何执行,使用哪个算法
  • LOCK - 控制在执行 DDL 时允许对表加锁的级别
ALTER TABLE tab ADD COLUMN c varchar(50), ALGORITHM=INPLACE, LOCK=NONE;

算法有如下这些:

  • DEFAULT:默认算法,自动使用可用的最高效的算法
  • COPY :最原始的方式,所有的存储引擎都支持,不使用 Online DDL,操作时会创建临时表,执行全表拷贝和重建,过程中会写入 Redo Log 和大量的 Undo Log,需要添加读锁,非常低效
  • INPLACE :尽可能避免表拷贝和重建,由存储引擎决定如何实现,有些操作是可以立即生效的(比如重命名列,改变列的默认值等),但有些操作依然需要全表或者部分表的拷贝和重建(比如添加删除列、添加主键、改变列为 NULL 等)
  • NOCOPY 避免聚簇索引(主键索引)的重建造成全表重建
  • INSTANT所有涉及到表拷贝和重建的操作都会被禁止

运行过程:

整个 Online DDL 执行过程:

  1. 建立一个临时文件,扫描表的全部数据页
  2. 使用当前表的记录生成一个 B+ 🌲,存储到临时文件中
  3. 生成临时文件的过程中,将所有对当前表的操作记录在一个日志文件(row log)中
  4. 临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑数据上与表A相同的数据文件
  5. 用临时文件替换表A的数据文件。

工具

介绍一个平时我们日常用的最多的:

pt-online-schema-change

www.percona.com/doc/percona…

有一说一,percona 这家公司真的NB,生产了很多mysql运维的toolkit,强烈推荐大家使用