您好,欢迎访问一九零五行业门户网

MySQL数据库InnoDB存储引擎在线加字段实现原理详解

腾讯互娱内部维护了一个mysql分支,基于官方5.5.24,实现了类似于oracle 11g的快速加字段功能,这个分支我们内部称为tmysql。该功
腾讯互娱内部维护了一个mysql分支,基于官方5.5.24,实现了类似于oracle 11g的快速加字段功能,这个分支我们内部称为tmysql。该功能通过扩展存储格式来实现,原理类似于oracle 11g,以下介绍下其实现原理。
1. gcs行格式
需要在innodb中实现类似oracle的快速加字段功能,仅仅基于原来的行格式是不行的,必须对其进行扩展。为了保证原mysql和innodb的兼容性,不改变原存储格式的行为,在线加字段功能是通过新增一种innodb行格式gcs(game cloud storage)来实现,从而避免对其他格式造成影响。
虽然说是新增格式,但该格式与原默认的compact是基本一样的,只是新增了关键的field count(字段数)控制信息。
下面先回顾下compact行格式
compact聚集索引记录的格式由下图所示,由记录头和记录内容组成。
记录头记录了解析字段的关键信息,其结构下图所示。
record extra bytes:是固定的5字节,表示记录的额外信息。
nullable bitmap:记录可空位图,,使用1个bit来表示一个可空字段是否为null。
non-null variable-length array:非空变长字段数组,表示非空变长字段(如varchar、varbinary)在该行的长度。
关于compact格式的详细介绍可以参考文章。
compact格式有很重要的两个特点:
字段的定义顺序与存储顺序基本一致(主键除外)
 字段为null不占存储空间,只需通过nullable bitmap记录。
基于以上特点,实现快速加字段功能gcs格式只需在记录头添加field count(字段数),来表示当前记录的字段数,占用1~2字节(若大于127,则使用2字节)。
那么,解析gcs记录的关键逻辑就变为:
假设某gcs记录的field count记录为x,表字段数为y,那么x
如果x == y或非gcs格式,按原来compact方式解析
 如果x  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: 0 duplicates: 0 warnings: 0
mysql> select * from t1 limit 1;
+------+------+----+------+
| c1 | c2 | d1 | d2 |
+------+------+----+------+
|1 |1 | 0 | null |
+------+------+----+------+
1 row in set (0.00 sec)
--------------------------------------分割线 --------------------------------------
ubuntu 14.04下安装mysql
《mysql权威指南(原书第2版)》清晰中文扫描版 pdf
ubuntu 14.04 lts 安装 lnmp nginx\php5 (php-fpm)\mysql
ubuntu 14.04下搭建mysql主从服务器
ubuntu 12.04 lts 构建高可用分布式 mysql 集群
ubuntu 12.04下源代码安装mysql5.6以及python-mysqldb
mysql-5.5.38通用二进制安装
--------------------------------------分割线 --------------------------------------
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格式是完全一致的。这样做,有两个好处:
第一次在线加字段前,减少每条gcs记录field count 1~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: 1 duplicates: 0 warnings: 0
# online操作,只需修改元数据,不需拷贝数据
mysql> alter table t_compact row_format = gcs;
 query ok, 0 rows affected (0.00 sec)
 records: 0 duplicates: 0 warnings: 0
# online操作
mysql> alter table t_compact add column d2 int not null default 0;
 query ok, 0 rows affected (0.00 sec)
 records: 0 duplicates: 0 warnings: 0
这样,tmysql可实现基于5.5的覆盖升级,对于compact表只需执行alter table row_format = gcs命令就能快速支持在线加字段功能,大大降低升级成本,并且实现加字段前没有存储空间的额外消耗!
3 dml操作
存储格式得以支持,相应的dml操作逻辑需要修改。
select:按照gcs格式进行解析
insert:根据当前表的字段数构造记录中field count和标记控制位
delete:不变
update:原地更新不变;非原地更新走delete+insert,会更新为新的field count
更多详情见请继续阅读下一页的精彩内容:
其它类似信息

推荐信息