mysql在线增加字段_MySQL在线加字段实现原理

article/2025/10/6 0:56:26

作者:vinchen

腾讯互娱内部维护了一个TMySQL分支,基于官方5.5.24,实现了类似于Oracle 11g的快速加字段功能。该功能通过扩展存储格式来实现,原理类似于Oracle 11g,以下介绍下其实现原理。

1. GCS行格式

需要在innodb中实现类似oracle的快速加字段功能,仅仅基于原来的行格式是不行的,必须对其进行扩展。为了保证原MySQL和innodb的兼容性,不改变原存储格式的行为,在线加字段功能是通过新增一种innodb行格式GCS(Game Cloud Storage)来实现,从而避免对其他格式造成影响。

61f6a8a93438e86f6005ab3cd82b075b.png

虽然说是新增格式,但该格式与原默认的compact是基本一样的,只是新增了关键的Field Count(字段数)控制信息。

下面先回顾下compact行格式

compact聚集索引记录的格式由下图所示,由记录头和记录内容组成。

931ebed2710f0232e411ce0ddc8752fa.png

记录头记录了解析字段的关键信息,其结构下图所示。

a9733c398957f5c81547d0321426528e.png

Record Extra Bytes:是固定的5字节,表示记录的额外信息。

Nullable Bitmap:记录可空位图,使用1个bit来表示一个可空字段是否为NULL。

non-NULL Variable-Length Array:非空变长字段数组,表示非空变长字段(如varchar、varbinary)在该行的长度。

关于Compact格式的详细介绍可以参考

compact格式有很重要的两个特点:

1、字段的定义顺序与存储顺序基本一致(主键除外)

2、字段为NULL不占存储空间,只需通过Nullable Bitmap记录。

基于以上特点,实现快速加字段功能GCS格式只需在记录头添加Field Count(字段数),来表示当前记录的字段数,占用1~2字节(若大于127,则使用2字节)。

4c6a3b6359bf6f0a80bf9b7fb6984a56.png

那么,解析GCS记录的关键逻辑就变为:

假设某GCS记录的Field count记录为x,表字段数为y,那么x <= y总是成立的。对于GCS格式,字段的解析变为:

1、如果x == y或非GCS格式,按原来compact方式解析

2、如果x < y,那么记录必定是在Alter Table加字段前就生成,那么最后y-x个字段必为NULL或默认值。

3、如果该字段是允许为NULL,则为NULL。

4、如果该字段不允许为NULL,则为默认值。

这样就可以将新增的字段解析出来。

另外,GCS格式在TMySQL中会替代compact作为innodb的默认行格式。

mysql> create table t1(c1 int, c2 int);

Query OK, 0 rows affected (0.00 sec)

mysql> show table status like 't1'\G

*************************** 1. row ***************************

Name: t1

Engine: InnoDB

Version: 10

Row_format: Gcs

Rows: 0

Avg_row_length: 0

Data_length: 16384

Max_data_length: 0

Index_length: 0

Data_free: 0

Auto_increment: NULL

Create_time: 2013-09-10 11:44:21

Update_time: NULL

Check_time: NULL

Collation: utf8_general_ci

Checksum: NULL

Create_options:

Comment:

1 row in set (0.00 sec)

#插入大量数据

mysql> insert into t1 values(1,1);

Query OK, 1 row affected (0.00 sec)

#快速加字段

mysql> alter table t1 add column d1 int not null default 0, add column d2 int;

Query OK, 0 rows affected (0.00 sec)

Records: 0Duplicates: 0Warnings: 0

mysql> select * from t1 limit 1;

+------+------+----+------+

| c1| c2| d1 | d2|

+------+------+----+------+

|1|1|0 | NULL |

+------+------+----+------+

1 row in set (0.00 sec)

2.兼容性

仅仅新增GCS存储格式,必定导致原来数据的不兼容(每行增加Field Count),只能通过重导数据或alter table来使其支持在线加字段功能。

# compact格式转换为GCS格式

mysql> alter table t_compact row_format=gcs;

如果数据量越大,上述语句所花时间就会越长,这样对升级和使用都带来困难。为了解决这个问题,GCS格式实现了对compact格式的全面兼容。

在innodb实现中,compact格式记录头的Record Extra Bytes首字节最高位和次高位是保留的,总是为0。因此,GCS记录占用了其中的最高bit,若为1表示使用GCS格式,记录中会包含Field count信息,这里称该bit为控制位。

然而GCS行格式新增的Field Count仅仅是为了表示记录的字段数,如果表不执行加字段操作,该部分其实是不起作用的(记录字段数恒等于表字段数)。换句话说,如果GCS表不执行快速加字段操作,记录其实并不需要存储Field Count信息。

因此,当表第一次快速加字段前,GCS记录可以与compact完全相同,即控制位为0;当第一次快速加字段时,可将加字段前的字段数存储在扩展的数据字典中,用来解析控制位为0的GCS记录(充当记录上的field count信息);新插入或修改的记录,则按照第一节介绍的存储格式进行构建。

最后,这个设计中的GCS记录在第一次快速加字段前可以跟Compact格式是完全一致的。这样做,有两个好处:

1、第一次在线加字段前,减少每条GCS记录Field Count 1~2字节的存储消耗

2、可以支持Compact表快速转换为GCS表,实现快速升级

由于存储格式完全兼容,不管原来的compact表数据量有多少,仅需执行以下命令,修改表的元数据信息,就能将格式快速转换为GCS,从而获得快速加字段功能。

mysql> create table t_compact(c1 int, c2 int) row_format=compact;

Query OK, 0 rows affected (0.00 sec)

mysql> insert into t_compact values(1,1);

Query OK, 1 row affected (0.00 sec)

# compact格式非onlie操作,需要拷贝数据

mysql> alter table t_compact add column d1 int;

Query OK, 1 row affected (0.01 sec)

Records: 1Duplicates: 0Warnings: 0

# online操作,只需修改元数据,不需拷贝数据

mysql> alter table t_compact row_format = gcs;

Query OK, 0 rows affected (0.00 sec)

Records: 0Duplicates: 0Warnings: 0

# online操作

mysql> alter table t_compact add column d2 int not null default 0;

Query OK, 0 rows affected (0.00 sec)

Records: 0Duplicates: 0Warnings: 0

这样,TMySQL可实现基于5.5的覆盖升级,对于compact表只需执行alter table row_format = gcs命令就能快速支持在线加字段功能,大大降低升级成本,并且实现加字段前没有存储空间的额外消耗!

3 DML操作

存储格式得以支持,相应的DML操作逻辑需要修改。

·select:按照GCS格式进行解析

·insert:根据当前表的字段数构造记录中field count和标记控制位

·delete:不变

·update:原地更新不变;非原地更新走delete+insert,会更新为新的field count

4数据字典

InnoDB关于列的数据字典中并不包含默认值信息,默认值只存储在MySQL层的frm文件中。

为了支持默认值的加字段操作,InnoDB存储引擎层需要存储新增列的默认值信息。一种办法是在原SYS_COLUMNS系统表增加def_val列,表示默认值。但这必定导致TMySQL和官方版本的不兼容,并且不是所有列的默认值都需要存储的,只需保存新增列的默认值信息。

因此,TMySQL新增一个系统表SYS_ADDED_COLS_DEFAULT,保存新增列的默认值,并通过(tableid,pos)与SYS_COLUMNS的列信息关联起来。

SYS_ADDED_COLS_DEFAULT(

tableidbigint,

posint,

def_valbinary(65535),

def_val_len int,

Primary key (tableid, pos)

);

为了实现与官方版本兼容,SYS_ADDED_COLS_DEFAULT使用动态创建功能,即TMySQL启动加载数据字典子系统时发现该表不存在,会动态创建。这样,从官方版本升级原地升级为TMySQL时就不需考虑该表导致的不兼容问题。

除了默认值,systables系统表还需记录GCS格式标记,第一次加字段前字段数等新增元数据信息。

5加字段流程

MySQL官方版本加字段其实是新建表导入数据,并删除原表的过程,整个过程是阻塞写的。而TMySQL的GCS格式支持原数据不改变的情况下解析新增字段,并且可以在原表上直接修改元数据,不需拷贝数据,从而实现加字段时间可以大大缩短。

GCS表在线加字段的过程为:

1、目标表T1上字典锁(SHARED_NO_WRITE),阻塞所有写操作

2、判断是否符合在线加字段的条件,如符合,执行步骤3,否则按照官方拷贝数据的方式来新增字段。

3、创建跟目标表T1同构的临时表frm文件S1.frm(含新增字段)

4、目标表T1的字典锁升级为排它锁,所有关于T1表的所有读写操作被阻塞

5、修改T1表InnoDB内部数据字典信息,增加新字段。

6、将S1.frm重命名为T1.frm

7、释放表T1的字典锁

以上流程处理参考了5.6 online DDL的部分实现。

TMySQL并不支持任何情况的加字段操作,必须符合以下条件:

1、表必须是innodb的GCS表,原Compact表不支持在线加字段功能。

2、不支持临时表。

3、一次alter table仅允许加一列或多列,但不允许同时进行多个alter table的不同操作(如增删索引、删字段、修改字段等)。

4、加字段不支持指定Before或After关键字表示定义在某列之前或之后。

5、所加字段不能包含除not null外的任何约束,包括外键约束、唯一约束。

6、不支持允许为NULL并指定默认值的加字段操作(同oracle 11g)

7、所加字段不能自增列(auto_increment)

6总结

以上是TMySQL在线加字段操作的实现原理,除了以上内容还包括语法、故障恢复、事务回滚、自适应哈希索引等适配改造,比较细节,这里就先不介绍了。除了在线加字段,TMySQL还有不少其他新特性,后续再介绍了。


http://chatgpt.dhexx.cn/article/3RVntwwd.shtml

相关文章

mysql新增json_mysql5.7 新增的json字段类型用法实例分析

本文实例讲述了mysql5.7 新增的json字段类型用法。分享给大家供大家参考&#xff0c;具体如下&#xff1a; 一、我们先创建一个表&#xff0c;准备点数据 CREATE TABLE json_test ( id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT ID, json json DEFAULT NULL COMMENT j…

Mysql新增字段到大数据表导致锁表

昨天晚上7点左右&#xff0c;对一张表进行加字段&#xff0c;大概200多万条记录&#xff0c;字段90多个的大表&#xff0c;结果造成mysql锁表&#xff0c;进而导致服务不可用。执行语句如下&#xff1a; [sql] view plain copy ALTER TABLE sc_stockout_order ADD route_remar…

MySQL 新增字段(alter table add column),报错:Duplicate entry

问题 执行一个增加字段的DDL语句脚本时&#xff0c;报错&#xff0c;错误如下: Error 1062: Duplicate entry c51d3db8-59a5 2022-06-28 17:59:59 for key uniq_material_date重复执行报相同的错误。根据错误提示的条件去数据库中查询却只能查到一条记录&#xff0c;并没有重…

mysql新增、修改表字段

一、新增字段 说明&#xff1a;以下语句关键字COLUMN&#xff0c;都可以省略&#xff0c;“ACT_AAA”是表名 格式 ALTER TABLE 表名 ADD COLUMN 字段名称 字段类型&#xff08;字段长短-选填&#xff09; CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL&#xf…

ln命令使用

Linux中ln是一个非常重要的一个命令&#xff0c;主要是将两个文档进行连接&#xff0c;创建一个连接关系 连接档&#xff1a;ln 使用ln可以在两个文件之间建立关联&#xff0c;就类似Windows下的快捷方式&#xff0c;连接有两种方式 Hard Link&#xff08;硬式连接或实际连接…

Linux ln 命令是什么?C/C++代码实现

在Linux中&#xff0c;在命令行上工作时&#xff0c;需要在文件之间创建链接&#xff0c;将文件名与文件数据相关联。这可以使用名为 ln 的专用命令来实现。 什么是链接&#xff1f; 在讨论 ln 命令之前&#xff0c;让我们先讨论一下链接命令&#xff0c;什么是链接&#xff…

Linux命令详解(13)- ln命令

ln是英文“link files”的缩写&#xff0c;命令不算复杂&#xff0c;但是非常重要。 语法&#xff1a; ln option Source file or directory Destination file or directory 这里先讲下两个概念。 1.软连接 软链接类似于windows系统中的快捷方式。创建之后&#xff0c…

linux ln 远程,Linux 软连接 (ln命令)

这是linux中一个非常重要命令。它的功能是为某一个文件在另外一个位置建立一个同不的链接,这个命令最常用的参数是-s,具体用法是:ln -s 源文件 目标文件。 当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在某个…

linux 中的 ln 命令,Linux ln命令操作指南

ln是Linux系统中一个重要的命令&#xff0c;能够为文件建立链接&#xff0c;保持链接文件的同步性&#xff0c;下面小编就给大家介绍下Linux下如何使用ln命令&#xff0c;通过实例来详细了解。 1. 使用ln命令给档案创建symbolic link。 linux系统下的symbolic link类似于window…

Linux ln命令详解

ln命令来自于英文单词link的缩写&#xff0c;中文译为“链接”&#xff0c;其功能是用于为某个文件在另外一个位置建立同步的链接。Linux系统中的链接文件有两种形式&#xff0c;一种是硬链接&#xff08;hard link&#xff09;&#xff0c;另一种是软链接&#xff08;symbolic…

ln命令应用

记录&#xff1a;352 场景&#xff1a;在CentOS 7.9操作系统上&#xff0c;使用ln命令创建软链接(symbolic links)和硬链接(hard links)。解决&#xff1a;Too many levels of symbolic links。 版本&#xff1a; 操作系统&#xff1a;CentOS 7.9 1.命令应用 (1)目录创建软…

linux ln命令

ln 命令的功能是在不同的位置创建一个链接&#xff0c;又分软链接和硬链接&#xff0c;一般软链接使用较多。 硬链接&#xff1a;ln 源文件 链接文件 是在选定的位置生成一个文件的镜像&#xff0c;镜像文件与源文件同样大小 软连接&#xff1a;ln –s 源文件 链接文件 是…

ln命令详解

Linux文件系统中&#xff0c;有所谓的链接(link)&#xff0c;我们可以将其视为档案的别名&#xff0c;而链接又可分为两种 : 硬链接(hard link)与软链接(symbolic link)&#xff0c;硬链接的意思是一个文件可以有多个名称&#xff0c;而软链接的方式则是产生一个特殊的文件&…

ubuntu18.04虚拟机崩掉导致硬盘错误,提示fsck manually

问题描述&#xff1a; 可能是一次性复制的文件太大了&#xff0c;导致内存吃紧&#xff0c;Windows10直接崩掉&#xff0c;接着就进入了我经常看到的那个蓝屏错误提示界面&#xff0c;有个正在恢复的百分数进度提示。 这个问题我经常碰到&#xff0c;或许是网页开多了吧&…

dos磁盘管理命令

dos磁盘管理命令 前言 磁盘管理命令用于日常的磁盘维护。DOS命令行提供了多种文件管理命令用于设置和管理磁盘列表。由于很多磁盘在没有安装图形界面的时候就需要对其进行操作&#xff0c;所以掌握DOS命令行下的磁盘管 理命令对系统管理员是十分必要的。 磁盘管理命令 以下…

centos 硬盘 修复

xfs_repair -n /dev/sdb centos 硬盘 修复 sudo parted -l sudo parted -l [localhost home]$ sudo parted -l Model: Dell VIRTUAL DISK (scsi) Disk /dev/sda: 1000GB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags:Number Start End…

电脑修复损坏文件--修复命令;系统盘磁盘空间不足

目录 sfc/scannow--修复损坏的系统文件命令解析command parse步骤 命令修复磁盘&#xff1b;磁盘空间的释放输入“sfc /purgecache”命令&#xff08;不含双引号&#xff0c;下同&#xff09;输入“cleanmgr”命令输入“CHKDSK D:/F”&#xff0c;修复D驱动器号 sfc/scannow–修…

mac 磁盘修复

1、使用磁盘工具 2、终端查看并修复 diskutil listdiskutil verifyVolume disknamediskutil repairDisk diskname

如何扫描和修复 Linux 磁盘错误

在本文中&#xff0c;将学习如何使用 fsck 和 xfs_repair 命令修复 Linux 磁盘错误。 什么是FSCK&#xff1f; fsck&#xff08;文件系统一致性检查&#xff09;是用于检查Linux操作系统文件系统一致性的工具。 列出 Linux 磁盘分区和类型&#xff1a; 首先&#xff0c;需要…

计算机磁盘修复工具,chkdsk磁盘修复工具

chkdsk磁盘修复工具是一款非常具有专业性、权威的工具,使用chkdsk磁盘修复工具时你不可以有任何其他操作(停止运行任何程序),只能锁定磁盘(也就是强制卸下该卷),如果出现其他程序在修复时运行,就需要你重启电脑后重新修复了。硬盘坏道修复工具使用简单且安全性高,推荐使用…