【StoneDB】修改字段长度调研

一、调研

1.支持情况调研

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

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

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

验证过程:

innodb:
【StoneDB】修改字段长度调研_第1张图片
myisam:
【StoneDB】修改字段长度调研_第2张图片
mariadb-columnstore:
【StoneDB】修改字段长度调研_第3张图片

2)字段长度范围限制

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

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

验证过程:
【StoneDB】修改字段长度调研_第4张图片

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

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

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

你可能感兴趣的:(数据库mysql)