共计 4037 个字符,预计需要花费 11 分钟才能阅读完成。
一、调研
1. 反对状况调研
以 varchar 数据类型为例,开启调研。
1)其余引擎 / 数据库调研
对象 | 字段长度批改反对状况 | 详情 |
---|---|---|
mysql-innodb | 反对 | 严格模式:能够改大;能够改小,但不能批改小于已有数据的长度;非严格模式:能够改大;能够改小,会失落精确度 |
mysql-myisam | 反对 | 严格模式:能够改大;能够改小,但不能批改小于已有数据的长度;非严格模式:能够改大;能够改小,会失落精确度 |
mariadb-columnstore | 不反对 | 会报错 |
ClickHouse | 不反对 | 有 String 类型,主动扩大,无需反对 |
TiDB | 反对 | 只反对改大,不反对改小 |
验证过程:
innodb:
myisam:
mariadb-columnstore:
2)字段长度范畴限度
varchar 的长度范畴与字符集无关;
例如:
字符集 | 长度范畴 |
---|---|
latin1 字符集 | 0~65532 |
utf8mb4 字符集 | 0~16383 |
utf8 字符集 | 0~21844 |
验证过程:
2.alter table 语法调研
1)反对性能
次要包含以下性能:
- 索引的减少、删除
- 列的减少、删除
- 列的属性批改:类型批改、长度批改、重命名等
- 引擎批改
- 表重命名
-
等
2)并发管制
通过锁来进行管制并发,反对以下锁:
LOCK= DEFAULT | NONE | SHARED | EXCLUSIVE
DEFAULT:默认形式,MySQL 自行判断应用哪种 LOCK 模式,尽量不锁表。
NONE:无锁:容许 Online DDL 期间进行并发读写操作。如果 Online DDL 操作不反对对表的持续写入,则 DDL 操作失败,对表批改有效。
SHARED:共享锁:Online DDL 操作期间梗塞写入,不影响读取。
EXCLUSIVE:排它锁:Online DDL 操作期间不容许对锁表进行任何操作。
3)算法反对
反对两种算法,8.0 后新增了一种算法:INSTANT。
ALGORITHM=COPY
ALGORITHM=INPLACE
- copy 这个操作一行一行的 copy 数据从原始表到新表,而且不反对并发 DML,然而并发查问依然是反对的,默认应用共享锁(能够并发查问),也可指定排他锁(并发查问和 DML 都不反对)。
- inplace 这个操作会防止 copy 表数据,然而可能会重建表。在数据筹备和执行阶段会进行行锁定,通常反对并发 DML。
mysql 默认抉择 inplace,如果存储引擎不反对,就会选中 copy。
应用 INPLACE 的算法场景包含:
- alter table 的操作被 InnoDB online DDL 的个性所反对。
- 重命名表。mysql 会重命名 table 对应的文件,并不会做 copy 数据的操作。(per_file_on_table 须要关上)
- 仅批改表的元数据的操作。包含:rename column,变更列的默认值,不扭转数据类型存储空间的操作。
- 重命名索引。
- 增加或者删除一个二级索引。
4)总体反对状况
执行操作 | 容许 ALGORITHM=INPLACE | 是否拷贝表 | 容许并发 DML | 容许并发查问 | 备注和注意事项 |
---|---|---|---|---|---|
create index add index | Yes* | No* | Yes | Yes | 对于全文索引,有一些限度,具体看下一行。目前,该操作不是在原地执行,须要拷贝表。 |
add fulltext index | Yes | No* | No | Yes | 创立第一个全文索引波及到拷贝表,除非有应用 FTS_DOC_ID 列。前面的全文索引则在原地执行。 |
drop index | Yes | No | Yes | Yes | |
optimize table | Yes | Yes | Yes | Yes | 在 MySQL5.6.17 里应用 ALGORITHM=INPLACE。如果设置 old_alter_table= 1 或应用 mysqld –skip-new 选项,则应用 ALGORITHM=COPY。如果表应用了全文索引,则 ALGORITHM=INPLACE 不实用 |
set default value for column | Yes | No | Yes | Yes | 批改.frm 文件,不波及数据文件 |
change auto-increment value | Yes | No | Yes | Yes | 批改存储到内存的一个值,不批改数据文件 |
add foreign key constraint | Yes* | No* | Yes | Yes | 禁用 foreign_key_checks, 则能够防止拷贝表 |
drop forgien key constraing | Yes | No | Yes | Yes | foreign_key_checks 能够禁用或开启 |
rename column | Yes* | No* | Yes* | Yes | 容许并发 DML,放弃雷同的数据类型,仅扭转字段名 |
add column | Yes | Yes | Yes* | Yes | 减少 auto-increment 字段时不容许 DML 操作。尽管 ALGORITHM=INPLACE 能够容许,然而数据要重组,代价比拟低廉. |
drop column | Yes | Yes | Yes | Yes | 尽管 ALGORITHM=INPLACE 能够容许,然而数据要重组,代价比拟低廉. |
reorder columns | Yes | Yes | Yes | Yes | 尽管 ALGORITHM=INPLACE 能够容许,然而数据要重组,代价比拟低廉. |
change ROW_FORMAT property | Yes | Yes | Yes | Yes | 尽管 ALGORITHM=INPLACE 能够容许,然而数据要重组,代价比拟低廉. |
change KEY_BLOCK_SIZE property | Yes | Yes | Yes | Yes | 尽管 ALGORITHM=INPLACE 能够容许,然而数据要重组,代价比拟低廉. |
make column null | Yes | Yes | Yes | Yes | 尽管 ALGORITHM=INPLACE 能够容许, |
make cplumn not null | Yes* | Yes | Yes | Yes | 当 SQL_MODE 为 strict_all_tables, 如果执行的列蕴含 null,则会执行失败。尽管 ALGORITHM=INPLACE 能够容许,然而数据要重组,代价比拟低廉. |
change data type of column | No | Yes | Yes | Yes | |
add primary key | Yes* | Yes | Yes | Yes | 尽管 ALGORITHM=INPLACE 能够容许,然而数据要重组,代价比拟低廉。如果列必须转换为非空的条件下,ALGORITHM=INPLACE 是不容许的。 |
drop primary key and add other | Yes | Yes | Yes | Yes | 当在同一个 alter table 新增主键时 ALGORITHM=INPLACE 是容许的. 数据要重组,因而代价比拟低廉。 |
drop primary key | No | Yes | No | Yes | 删除主键然而又不新增主键是被限度的 |
convert character set | No | Yes | No | Yes | 如果新的字符编码不同将会重建表 |
specify character set | No | Yes | No | Yes | 如果新的字符编码不同将会重建表 |
rebulid with force option | Yes | Yes | Yes | Yes | 在 MySQL5.6.17 里应用 ALGORITHM=INPLACE。如果设置 old_alter_table= 1 或应用 mysqld –skip-new 选项,则应用 ALGORITHM=COPY。如果表应用了全文索引,则 ALGORITHM=INPLACE 不实用 |
rebulid with “null” alter table … engine=innodb | Yes | Yes | Yes | Yes | 在 MySQL5.6.17 里应用 ALGORITHM=INPLACE。如果设置 old_alter_table= 1 或应用 mysqld –skip-new 选项,则应用 ALGORITHM=COPY。如果表应用了全文索引,则 ALGORITHM=INPLACE 不实用 |
二、计划总结
1.alter table 执行流程
通过后期调研和代码剖析,批改字段长度总体实现流程如下:
函数整体调用流程如下:
次要性能实现集中在 mysql_alter_table 函数中,具体执行流程如下:
次要性能介绍和对应接口如下:
1. 关上表:
open_tables(thd, &table_list, &tables_opened, 0,&alter_prelocking_strategy);
2. 查看引擎是否反对,批改后的表的数据类型:
check_engine
3. 查看引擎是否反对 alter 操作:
ha_check_storage_engine_flag
4.alter table 预处理:包含列属性的赋值、新列的增加、列的删除等,其中会调用到引擎的 update_create_info 函数,用于赋值一些创立表的信息,stonedb 引擎的此函数为空:
mysql_prepare_alter_table
5. 算法抉择
判断每个引擎是否反对 inplace 算法进行 alter table:
check_if_supported_inplace_alter
如果反对 inplace 算法进行 alter table 解决:
通过 mysql_inplace_alter_table 调用引擎的
prepare_inplace_alter_table
inplace_alter_table
commit_inplace_alter_table
这三个接口进行解决
如果不反对则采纳 copy 算法,创立新表 -> 复制数据 > 新表旧表重命名 > 删除旧表,达到 alter table 目标:
ha_create_table -- 创立表
copy_data_between_tables -- 复制数据
mysql_rename_table -- 重命名表
quick_rm_table -- 删除表
2. 批改计划
1)批改引擎代码,使其走 copy 算法。
2)update_create_info 函数,须要实现,用于更新创立新表时候的一些信息。
3)inplace 算法须要批改,减少性能,使其反对索引的减少和删除等其余操作。
波及批改的函数,包含以下函数:
check_if_supported_inplace_alter
check_if_incompatible_data
prepare_inplace_alter_table
inplace_alter_table
commit_inplace_alter_table