一、调研
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_tableinplace_alter_tablecommit_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_altercheck_if_incompatible_dataprepare_inplace_alter_tableinplace_alter_tablecommit_inplace_alter_table