MySQL-5.7 innodb在线DDL操作(增删改索引、列、外键、表、外键)

基本概念

在开始阅读前,先熟悉下以下概念,以便更加方便理解。

DML
DML(Data Manipulation Language)数据操作语言-数据库的基本操作,SQL中处理数据等操作统称为数据操纵语言,简而言之就是实现了基本的“增删改查”操作。包括的关键字有:select、update、delete、insert、merge

DDL
DDL(Data Definition Language)数据定义语言-用于定义和管理 SQL 数据库中的所有对象的语言,对数据库中的某些对象(例如,database,table)进行管理。包括的关键字有:create、alter、drop、truncate、comment、grant、revoke

SQL_MODE
为当前会话设置严格模式:
执行SET sql_mode = ‘STRICT_TRANS_TABLES’ 或者SET sql_mode = ‘STRICT_ALL_TABLES’
全局设置严格模式:
执行SET global sql_mode = ‘STRICT_TRANS_TABLES’ 或者SET global sql_mode = ‘STRICT_ALL_TABLES’

INPLACE/COPY算法
在执行DDL时复制表数据,INPLACE表示不会复制表数据,COPY表示会复制表数据

重建表(Rebuild Table)
在执行DDL的时是否需要重建表,例如对于InnoDB,因为其是基于主键(聚集索引)组织数据的,所以如果修改主键(如增加一列),则会需要重建表。

允许并发DML
在执行DDL时是否允许并发的DML。例如,在增加一个二级索引时,允许对数据库执行DML等操作。

只修改元数据
在执行DDL时是否只修改表的元数据,而不需要修改数据。例如,对于修改表名,只需要修改该表的元数据,而不需要触及该表的数据。

索引操作

下表概述了对索引操作的在线 DDL 支持。星号表示附加信息、异常或依赖关系。

索引操作的在线 DDL 支持:

操作IN PLACE 算法重建表(Rebuild Table)允许并发DML只修改元数据说明
创建或添加二级索引YesNoYesNo创建的二级索引包含在创建index结束之前提交的数据,不包含未提交的数据、旧版本的数据、被标记为删除但未从旧索引删除的数据。
删除索引YesNoYesYes只有在所有访问该表的事务都结束后才会结束删除索引,即索引的初始状态是表的最近状态。
重命名索引YesNoYesYes只修改元数据而不触及数据
添加FULLTEXT索引Yes*No*NoNo如果没有用户定义的FTS_DOC_ID列,则需要重建表;其他的不需要重建表。
添加SPATIAL索引YesNoNoNo与FULLTEXT相同。
更改索引类型YesNoYesYes修改索引类型,USING BTREE 或者HASH,与创建索引类似

如果MySQL在创建二级索引时退出,则在MySQL服务器恢复时,会删除未完成创建的索引数据。您必须重新运行ALTER TABLE or CREATE INDEX语句。

主键操作

索引操作的在线 DDL 支持:

操作IN PLACE 算法重建表(Rebuild Table)允许并发DML只修改元数据说明
添加主键索引Yes*Yes*YesNo新增主键,需要重建数据表(根据聚集索引重排)。 如果有列必须要从NULL转成NOT NULL,那么不允许INPLACE算法。
删除主键索引NoYesNoNo在删除主键而不增加新主键时,只有COPY方式才能被使用
删除并且增加另一个主键索引YesYesYesNo需要重建表,所以此操作的代价非常大。

新增主键: 当新建UNIQUE和PK时,MySQL需要做重复值检查,对于PK,还需要检查不包含NULL值。使用COPY方式时,MySQL会将NULL转为对应的默认值(数字为 0,基于字符的列和 BLOB 为空字符串,0000-00-00 00:00:00 为DATETIME)。为了支持INPLACE,需要设置SQL_MODE(strict_trans_tables或strict_all_tables)。

新建主键的过程如下:从数据从原表t中复制到新的临时表t1(新的主键/聚集索引)中,然后将原表重命名到一个临时表的名字t2,然后将新索引的临时表t1重命名为原表名t,最后将旧表t2删除。

当采用INPLACE时,即使数据仍然需要复制,但性能仍然会比COPY方式要好:

  1. INPLACE不需要UNDO/REDO log;
  2. 二级索引是预排序的,能够有序地读取;
  3. 不需要更改缓冲区,因为没有二级索引的随机插入;

列操作

下表概述了对列操作的在线 DDL 支持。星号表示附加信息、异常或依赖关系。

操作IN PLACE 算法重建表(Rebuild Table)允许并发DML只修改元数据说明
添加列YesYesYes*No添加列时不允许并发 DML 。需要重建表,所以此操作的代价非常大。所以增加列时可以增加 ALGORITHM=INPLACE, LOCK=SHARED。
删除列YesYesYesNo需要重建表,所以此操作的代价非常大。
重命名列YesNoYes*Yes如果需要允许并发 DML,需要保持相同的数据类型和[NOT] NULL属性,只改变列名。如果重命名属于外键约束的列,外键定义会自动更新以使用新的列名。重命名参与外键的列仅适用于 ALGORITHM=INPLACE. 如果您使用该 ALGORITHM=COPY子句,或者某些其他条件导致操作使用 ALGORITHM=COPY,则该ALTER TABLE语句将失败。
重新排序列YesYesYesNo需要重建表,所以此操作的代价非常大。
设置列默认值YesNoYesYes仅修改表元数据。默认列值存储在表的.frm 文件 中,而不是InnoDB 数据字典中。
更改列数据类型NoYesNoNo仅支持更改列数据类型 ALGORITHM=COPY。
扩展VARCHAR列大小YesNoYesYes
删除列默认值YesNoYesYes仅修改表元数据。默认列值存储在表的.frm 文件 中,而不是InnoDB 数据字典中。
更改自动增量值YesNoYesNo*修改存储在内存中的值,而不是数据文件。
修改列为NULLYesYes*YesNo需要重建表,所以此操作的代价非常大。
修改列为NOT NULLYes*Yes*YesNo需要重建表,所以此操作的代价非常大。
修改定义为enum或者set列YesNoYesYes

重新排序列

如果需要重新排序列,使用FIRST或者 AFTER in CHANGE或者 MODIFY操作。

ALTER TABLE tbl_name MODIFY COLUMN col_name column_definition FIRST, ALGORITHM=INPLACE, LOCK=NONE;

扩展VARCHAR列大小

扩展VARCHAR列大小操作是平常最常见的操作了。列的字节长度VARCHAR取决于字符集的字节长度,ascii为一个字节(单字节),utf8为三个字节。

对于VARCHAR大小为 0 到 255 字节的列,需要一个长度字节来对值进行编码。
对于VARCHAR 大小为 256 字节或更多的列,需要两个长度字节。

ALTER TABLE仅支持将 VARCHAR列大小从 0 字节增加到 255 字节,或从 256 字节增加到更大的大小。

ALTER TABLE不支持增加a列的大小 VARCHAR从小于 256 字节到等于或大于 256 字节的列。在这种情况下,所需的长度字节数从 1 变为 2,这情况只能使用ALGORITHM=COPY。例如,尝试VARCHAR使用将单字节字符集(例如ascii)的列大小从 VARCHAR(255) 更改为 VARCHAR(256) ,ALTER TABLE返回错误。如果使用utf8字符集则可以成功修改。

ascii字符集表使用ALGORITHM=INPLACE将varchar(200)修改为varchar(256):

ALTER TABLE employee ALGORITHM=INPLACE, CHANGE COLUMN remark remark VARCHAR(300);
ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

ascii字符集表使用ALGORITHM=COPY将varchar(200)修改为varchar(256):

ALTER TABLE employee ALGORITHM=copy , CHANGE COLUMN remark remark VARCHAR(300)
[2023-01-07 17:09:38] 1 row affected in 88 ms

不支持VARCHAR减小尺寸。ALTER TABLE减小VARCHAR 大小需要使用ALGORITHM=COPY。ascii或者utf8字符集表都不支持使用ALGORITHM=INPLACE。

VARCHAR(300)修改为VARCHAR(288):

ALTER TABLE employee ALGORITHM=INPLACE , CHANGE COLUMN remark remark VARCHAR(288);
ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

ALTER TABLE employee ALGORITHM=copy , CHANGE COLUMN remark remark VARCHAR(288)
[2023-01-07 17:12:36] 1 row affected in 97 ms

STORED操作

STORED列可能比较陌生。

举个例子:
user表有姓(surname)和name(名),创建一个full_name(全名) STORED列

ALTER TABLE user ADD COLUMN (full_name varchar(12) GENERATED ALWAYS AS (concat(surname,name)) STORED), ALGORITHM=COPY;

插入数据查询如下:

insert into user(surname, name) VALUES ('孙','悟空'),('诸葛','亮');
select * from user;

在这里插入图片描述

下表概述了对STORED列操作的在线 DDL 支持。

操作IN PLACE 算法重建表(Rebuild Table)允许并发DML只修改元数据说明
添加STORED列NoYesNoNo需要重建表,所以此操作的代价非常大。
修改STORED列顺序NoYesNoNo需要重建表,所以此操作的代价非常大。
删除STORED列YesYesYesNo需要重建表,所以此操作的代价非常大。
添加VIRTUAL列YesNoYesYes
修改VIRTUAL列顺序NoYesNoNo需要重建表,所以此操作的代价非常大。
删除VIRTUAL列YesNoYesYes

外键操作

下表概述了对外键操作的在线 DDL 支持。星号表示附加信息、异常或依赖关系。

操作IN PLACE 算法重建表(Rebuild Table)允许并发DML只修改元数据说明
添加外键约束Yes*NoYesNo当FOREIGN_KEY_CHECKS被禁用时,可以用INPLACE;否则只能COPY。
删除外键约束YesNoYesYes当FOREIGN_KEY_CHECKS被禁用时,可以用INPLACE;否则只能COPY。

FOREIGN_KEY_CHECKS
FOREIGN_KEY_CHECKS是用来启动和关闭外键约束的方法。
SELECT @@FOREIGN_KEY_CHECKS;查看当前FOREIGN_KEY_CHECKS的值
SET FOREIGN_KEY_CHECKS = 0;关闭外键约束
SET FOREIGN_KEY_CHECKS = 1;启动外键约束

表操作

下表概述了表操作的在线 DDL 支持。星号表示附加信息、异常或依赖关系。

操作IN PLACE 算法重建表(Rebuild Table)允许并发DML只修改元数据说明
改变ROW_FORMATYesYesYesNo需要重建表,所以此操作的代价非常大。
改变KEY_BLOCK_SIZEYesYesYesNo需要重建表,所以此操作的代价非常大。
设置持久表统计信息YesNoYesYes仅修改表元数据。
指定字符集YesYes*NoNo
转换字符集NoYes*NoNo需要重建表,所以此操作的代价非常大。
优化表Yes*YesYesNo
FORCE使用选项重建Yes*YesYesNo
执行空重建Yes*YesYesNo
重命名表YesNoYesYes

改变ROW_FORMAT

ALTER TABLE tbl_name ROW_FORMAT = row_format, ALGORITHM=INPLACE, LOCK=NONE;

需要重建表,所以此操作的代价非常大。

改变KEY_BLOCK_SIZE

ALTER TABLE tbl_name KEY_BLOCK_SIZE = value, ALGORITHM=INPLACE, LOCK=NONE;

需要重建表,所以此操作的代价非常大。

KEY_BLOCK_SIZE
创建innodb表时带上ROW_FORMAT=COMPRESSED参数能够使用比默认的16K更小的页。这样在读写时需要更少的I/O,对于SSD磁盘更有价值。
页的大小通过KEY_BLOCK_SIZE参数指定。

设置持久表统计选项

ALTER TABLE tbl_name STATS_PERSISTENT=0, STATS_SAMPLE_PAGES=20, STATS_AUTO_RECALC=1, ALGORITHM=INPLACE, LOCK=NONE;

STATS_PERSISTENT指定是否为InnoDB表启用持久统计信息。值DEFAULT 由innodb_stats_persistent设置。值1启用表的持久统计信息,而值0禁用该功能。为单个表启用持久统计信息后,请在加载表数据后使用ANALYZE table计算统计信息。

STATS_SAMPLE_PAGES指定在例如通过ANALYZE TABLE操作为索引列计算基数和其他统计信息时要采样的索引页数。

STATS_AUTO_RECALC指定是否自动重新计算持久统计信息。值DEFAULT使表的持久统计设置由innodb_stats_auto_recalc设置确定。如果值为1,则当10%的表数据发生更改时,将重新计算统计信息。值0阻止自动重新计算表。使用值0时,在对表进行实质性更改后,使用ANALYZE TABLE重新计算统计信息。

指定字符集

ALTER TABLE tbl_name CHARACTER SET = charset_name, ALGORITHM=INPLACE, LOCK=NONE;

如果新字符编码不同,则重建表。

转换字符集

ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name, ALGORITHM=COPY;

如果新字符编码不同,则重建表。

优化表

OPTIMIZE TABLE tbl_name;

优化表格,使用INPLACE(5.6.17后),但不支持ALGORITHM和LOCK的语法。但是有FULLTEXT索引的表不能够使用INPLACE。

FORCE使用选项 重建表

ALTER TABLE tbl_name FORCE, ALGORITHM=INPLACE, LOCK=NONE;

ALGORITHM=INPLACE从 MySQL 5.6.17 开始 使用。表有FULLTEXT 索引时不支持使用ALGORITHM=INPLACE。

执行“空”重建

ALTER TABLE tbl_name ENGINE=InnoDB, ALGORITHM=INPLACE, LOCK=NONE;

从 MySQL 5.6.17 开始使用ALGORITHM=INPLACE。表有FULLTEXT 索引时不支持使用ALGORITHM=INPLACE。

重命名表

ALTER TABLE old_tbl_name RENAME TO new_tbl_name, ALGORITHM=INPLACE, LOCK=NONE;

重命名表,不会执行copy操作。

参考:https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html#online-ddl-primary-key-operations

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冲上云霄的Jayden

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值