一、调研

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 indexYes*No*YesYes对于全文索引,有一些限度,具体看下一行。目前,该操作不是在原地执行,须要拷贝表。
add fulltext indexYesNo*NoYes创立第一个全文索引波及到拷贝表,除非有应用FTS_DOC_ID列。前面的全文索引则在原地执行。
drop indexYesNoYesYes
optimize tableYesYesYesYes在MySQL5.6.17里应用 ALGORITHM=INPLACE。如果设置old_alter_table=1或应用mysqld --skip-new选项,则应用 ALGORITHM=COPY。如果表应用了全文索引,则 ALGORITHM=INPLACE不实用
set default value for columnYesNoYesYes批改.frm文件,不波及数据文件
change auto-increment valueYesNoYesYes批改存储到内存的一个值,不批改数据文件
add foreign key constraintYes*No*YesYes禁用foreign_key_checks,则能够防止拷贝表
drop forgien key constraingYesNoYesYesforeign_key_checks能够禁用或开启
rename columnYes*No*Yes*Yes容许并发DML,放弃雷同的数据类型,仅扭转字段名
add columnYesYesYes*Yes减少auto-increment字段时不容许DML操作。尽管ALGORITHM=INPLACE能够容许,然而数据要重组,代价比拟低廉.
drop columnYesYesYesYes尽管ALGORITHM=INPLACE能够容许,然而数据要重组,代价比拟低廉.
reorder columnsYesYesYesYes尽管ALGORITHM=INPLACE能够容许,然而数据要重组,代价比拟低廉.
change ROW_FORMAT propertyYesYesYesYes尽管ALGORITHM=INPLACE能够容许,然而数据要重组,代价比拟低廉.
change KEY_BLOCK_SIZE propertyYesYesYesYes尽管ALGORITHM=INPLACE能够容许,然而数据要重组,代价比拟低廉.
make column nullYesYesYesYes尽管ALGORITHM=INPLACE能够容许,
make cplumn not nullYes*YesYesYes当SQL_MODE为strict_all_tables,如果执行的列蕴含null,则会执行失败。尽管ALGORITHM=INPLACE能够容许,然而数据要重组,代价比拟低廉.
change data type of columnNoYesYesYes
add primary keyYes*YesYesYes尽管ALGORITHM=INPLACE能够容许,然而数据要重组,代价比拟低廉。如果列必须转换为非空的条件下,ALGORITHM=INPLACE是不容许的。
drop primary key and add otherYesYesYesYes当在同一个alter table新增主键时ALGORITHM=INPLACE是容许的.数据要重组,因而代价比拟低廉。
drop primary keyNoYesNoYes删除主键然而又不新增主键是被限度的
convert character setNoYesNoYes如果新的字符编码不同将会重建表
specify character setNoYesNoYes如果新的字符编码不同将会重建表
rebulid with force optionYesYesYesYes在MySQL5.6.17里应用 ALGORITHM=INPLACE。如果设置old_alter_table=1或应用mysqld --skip-new选项,则应用 ALGORITHM=COPY。如果表应用了全文索引,则 ALGORITHM=INPLACE不实用
rebulid with "null" alter table ... engine=innodbYesYesYesYes在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