4 数据字典
InnoDB存储引擎关于列的数据字典中并不包含默认值信息,默认值只存储在MySQL层的frm文件中。
为了支持默认值的加字段操作,InnoDB存储引擎层需要存储新增列的默认值信息。一种办法是在原SYS_COLUMNS系统表增加def_val列,表示默认值。但这必定导致TMySQL和官方版本的不兼容,并且不是所有列的默认值都需要存储的,只需保存新增列的默认值信息。
因此,TMySQL新增一个系统表SYS_ADDED_COLS_DEFAULT,保存新增列的默认值,并通过(tableid,pos)与SYS_COLUMNS的列信息关联起来。
SYS_ADDED_COLS_DEFAULT(
tableid bigint,
pos int,
def_val binary(65535),
def_val_len int,
Primary key (tableid, pos)
);
为了实现与官方版本兼容,SYS_ADDED_COLS_DEFAULT使用动态创建功能,即TMySQL启动加载数据字典子系统时发现该表不存在,会动态创建。这样,从官方版本升级原地升级为TMySQL时就不需考虑该表导致的不兼容问题。
除了默认值,systables系统表还需记录GCS格式标记,第一次加字段前字段数等新增元数据信息。
5 加字段流程
MySQL官方版本加字段其实是新建表导入数据,并删除原表的过程,整个过程是阻塞写的。
而TMySQL的GCS格式支持原数据不改变的情况下解析新增字段,并且可以在原表上直接修改元数据,不需拷贝数据,从而实现加字段时间可以大大缩短。
GCS表在线加字段的过程为:
目标表T1上字典锁(SHARED_NO_WRITE),阻塞所有写操作
判断是否符合在线加字段的条件,如符合,执行步骤3,否则按照官方拷贝数据的方式来新增字段。
创建跟目标表T1同构的临时表frm文件S1.frm(含新增字段)
目标表T1的字典锁升级为排它锁,所有关于T1表的所有读写操作被阻塞
修改T1表InnoDB存储引擎内部数据字典信息,增加新字段。
将S1.frm重命名为T1.frm
释放表T1的字典锁
以上流程处理参考了5.6 online DDL的部分实现。
TMySQL并不支持任何情况的加字段操作,必须符合以下条件:
表必须是innodb存储引擎的GCS表,原Compact表不支持在线加字段功能。
不支持临时表。
一次alter table仅允许加一列或多列,但不允许同时进行多个alter table的不同操作(如增删索引、删字段、修改字段等)。
加字段不支持指定Before或After关键字表示定义在某列之前或之后。
所加字段不能包含除not null外的任何约束,包括外键约束、唯一约束。
不支持允许为NULL并指定默认值的加字段操作(同Oracle 11g)
所加字段不能自增列(auto_increment)
6 总结
以上是TMySQL在线加字段操作的实现原理,除了以上内容还包括语法、故障恢复、事务回滚、自适应哈希索引等适配改造,比较细节,这里就先不介绍了。对以上有任何疑问,欢迎讨论~
除了在线加字段,TMySQL还有不少其他新特性,后续再介绍了。