Sharding 是把数据库横向扩展到多个物理节点上的一种有效的方式。如果将一个数据库当作一块大玻璃,将块玻璃打碎的过程就叫 Sharding(可以翻译为分片,也称为分库),每一小块都称为数据库的碎片(DatabaseShard)。
分库分表规则
Hash 取模:将数值对分库/分表数量进行取模,得到的值作为分库位/分表位。如分表规则为 Hash 取模,分表总数为 100,值为 230,则分表位计算结果为:
230 % 100 = 30
。字段类型为数字。字符串截断(MySQL 风格):将值通过 MySQL 的 substr 函数进行截取,第一个参数为开始位置,从第 1 位开始计算,第二个参数为长度。将截取之后的值转为数字类型,再对分库/分表数量进行取模,得到的值作为分库位/分表位。字段类型为字符串。
如分表规则为字符串截断(MySQL 风格),分表数量为 100,第一个参数设置为 1,第二个参数设置为 2,值为 12345,则分表位计算结果为:
((int)substr('12345', 1, 2)) % 100 = ((int)'12') % 100 = 12 % 100 = 12
。如分表规则为字符串截断(MySQL 风格),分表数量为 100,第一个参数设置为 -2,第二个参数设置为 2,值为 12345,则分表位计算结果为:
((int)substr('12345', -2, 2)) % 100 = ((int)'45') % 100 = 45 % 100 = 45
。
自身位:将值直接作为分表位/分表位。字段类型为数字。
如分表规则为自身位,值为 23,则分表位计算结果为 23。
重要在计算分库规则时,如果不填写分库规则,则会生成一个默认的分库规则,其计算结果为:
分表规则的计算结果 / (分表数/分库数)
。如分表规则计算结果为 20,分库数为 10,分表数为 100,那么相同规则下分库规则计算结果为:
20 / ( 100 / 10) = 2
。
Sharding 语法和使用限制
下面简单介绍 Sharding 语句的通用语法,以及 Sharding 语句在单库单表和分库分表等不同情况下的使用限制。
语法
CREATE [TEMPORARY] TABLE tbl_name[(create_definition,...)][table_options] [dbshard by hash([id,str]) shards N] [tbshard by hash([id,str]) shards N]
使用限制
单库单表:在单库单表中执行 Sharding 语句创建分库分表时,会被拦截。
说明单库单表中执行 Sharding 语句,不带 shards 参数时,创建出来的是单表,符合逻辑,因此不会被拦截。
分库分表
一个分库
无论使用的是 tbshard 子句还是 dbshard 子句,带 shards 参数且
shards=1
时,均会出现“ERROR 7400 (HY000): create table failed, caused by: sharding rules”报错,创建失败。说明如果需要在一个分库条件下,创建分库不分表,可通过控制台手动创建。详情请参见 创建数据访问代理数据表。
使用 tbshard 子句时,不带 shards 参数,将创建单表。
create table xx (name varchar(20) not null) tbshard by hash (substr(name , -2, 2));
代码说明:
分表规则是字符串截取,具体规则请参见 分库分表规则。
执行语句,成功创建单表。
使用 tbshard 子句时,带 shards 参数且 shards=n(n大于1),将创建多个分表。
create table xx (name varchar(20) not null) tbshard by hash (substr(name , -2, 2)) shards 4;
代码说明:
分表规则是字符串截取,具体规则请参见 分库分表规则。
执行语句,成功创建多个分表。
使用 dbshard 子句时,不带 shards 参数,将创建单表。
CREATE TABLE xxx ( id int(10) primary key , name varchar(30) not null ) dbshard by hash (id);
代码说明:
分表规则是 Hash 取模 id,具体规则请参见 分库分表规则。
执行语句,成功创建单表。
使用 dbshard 子句时,带 shards 参数且 shards=n(n大于1),将创建多个分表。
CREATE TABLE xxx ( id int(10) primary key , name varchar(30) not null ) dbshard by hash (id) shards 2;
代码说明:
分表规则是 Hash 取模 ID,具体规则请参见 分库分表规则。
执行语句,成功创建多个分表。
多个分库(以两个分库为例)
使用 tbshard 子句时,不带 shards 参数,将创建单表。
create table xx (name varchar(20) not null) tbshard by hash (substr(name , -2, 2));
代码说明:
分表规则是字符串截取,具体规则请参见 分库分表规则。
执行语句,成功创建单表。
使用 tbshard 子句时,带 shards 参数且参数 shards 的值等于分库数,则成功创建分表。
create table xx (name varchar(20) not null) tbshard by hash (substr(name , -2, 2)) shards 2;
代码说明:
分表规则是字符串截取,具体规则请参见 分库分表规则。
执行语句,成功创建分表。
使用 tbshard 子句时,带 shards 参数且参数 shards 的值为分库的整数倍,则成功创建整数倍分表。
create table xx (name varchar(20) not null) tbshard by hash (substr(name , -2, 2)) shards 4;
代码说明:
分表规则是字符串截取,具体规则请参见 分库分表规则。
执行语句,成功创建整数倍分表。
使用 tbshard 子句时,带 shards 参数且参数 shards 的值不是分库的整数倍,则创建失败,语句执行报错。
create table xx (name varchar(20) not null) tbshard by hash (substr(name , -2, 2)) shards 3;
代码说明:
分表规则是字符串截取,具体规则请参见 分库分表规则。
语句执行报错为:ERROR 1149 (HY000): Table shards illegal。
如果执行 Sharding 语句时,shards 的数值不规范,会出现“ERROR 1149 (HY000): Table shards illegal”报错 。之后再执行其他命令时,会出现延迟。
例如,执行 Sharding 语句报错后,执行命令
show tables
会出现“ERROR 7400 (HY000): create table failed, caused by: table count mod group count must be zero”报错。之后执行命令select 1
,展示的却是show tables
的结果。如果遇到了执行异常的情况,可断开 Server 后重新连接 Server。
使用 dbshard 子句时,不带 shards 参数,将创建单表。
CREATE TABLE xxx ( id int(10) primary key , name varchar(30) not null ) dbshard by hash (id);
代码说明:
分表规则是 Hash 取模 ID,具体规则请参见 分库分表规则。
执行语句,成功创建多个分表。
使用 dbshard 子句时,带 shards 参数且参数 shards 的值等于分库数,则将创建分库不分表。
CREATE TABLE xxx ( id int(10) primary key , name varchar(30) not null ) dbshard by hash (id) shards 2;
代码说明:
分表规则是 Hash 取模 ID,具体规则请参见 分库分表规则。
执行语句,成功创建分库不分表。
使用 dbshard 子句时,带 shards 参数且参数 shards 的值为分库的整数倍,则成功创建整数倍分表。
CREATE TABLE xxx ( id int(10) primary key , name varchar(30) not null ) dbshard by hash (id) shards 6;
代码说明:
分表规则是 Hash 取模 ID,具体规则请参见 分库分表规则。
执行语句,成功创建整数倍分表。
使用 dbshard 子句时,带 shards 参数且参数 shards 的值不是分库的整数倍,则创建失败,语句执行报错。
CREATE TABLE xxx ( id int(10) primary key , name varchar(30) not null ) dbshard by hash (id) shards 5;
代码说明:
分表规则是 Hash 取模 ID,具体规则请参见 分库分表规则。
语句执行报错为:ERROR 1149 (HY000): Table shards illegal。
注意事项
当两个实例下的逻辑库共用一个节点时,在控制台中可以删除逻辑库下面的逻辑表。如果一个实例进行了删除逻辑表的操作(同时删除物理库),另一个实例的逻辑表不会消失。但是在操作时,对于另一边的实例来说,虽然逻辑表没有消失,但物理表已经被删除了,这个逻辑表也不可用。操作人员需要注意自己的操作行为。
使用 Sharding 语句中的 dbshard 子句,参数 shards 的值是分库数的整数倍时,创建出来的分表通过
show topology from
命令查询出来的信息和在物理库中的展示信息不统一:在物理库中的展示信息是分库分表;在 server 中通过命令查询出来的信息则是分库不分表。