likes
comments
collection
share

【StoneDB】修改字段长度调研

作者站长头像
站长
· 阅读数 25

一、调研

1.支持情况调研

以varchar数据类型为例,开启调研。

1)其他引擎/数据库调研

对象字段长度修改支持情况详情
mysql-innodb支持严格模式:可以改大;可以改小,但不能修改小于已有数据的长度;非严格模式:可以改大;可以改小,会丢失精确度
mysql-myisam支持严格模式:可以改大;可以改小,但不能修改小于已有数据的长度;非严格模式:可以改大;可以改小,会丢失精确度
mariadb-columnstore不支持会报错
ClickHouse不支持有String类型,自动扩展,无需支持
TiDB支持只支持改大,不支持改小

验证过程:

innodb:【StoneDB】修改字段长度调研myisam:【StoneDB】修改字段长度调研mariadb-columnstore:【StoneDB】修改字段长度调研

2)字段长度范围限制

varchar的长度范围与字符集有关;例如:

字符集长度范围
latin1字符集0~65532
utf8mb4字符集0~16383
utf8字符集0~21844

验证过程:【StoneDB】修改字段长度调研

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=COPYALGORITHM=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执行流程

经过前期调研和代码分析,修改字段长度总体实现流程如下:【StoneDB】修改字段长度调研函数整体调用流程如下:

【StoneDB】修改字段长度调研主要功能实现集中在mysql_alter_table函数中,具体执行流程如下:【StoneDB】修改字段长度调研主要功能介绍和对应接口如下: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