REBALANCE与分区

最近更新时间: 2024-10-17 17:10:00

Range/List一级分区表数据重分布

针对range/list表的数据重分布:目前建议通过proxy运行重分布sql的方式完成。

proxy运行rebalance重分布sql

针对range/list一级分区表的重分布语法,支持将range分区或者list枚举范围进行搬迁。共有offline和online两种方式。offline锁表时间较长,使用数据导入导出的方式完成数据重分布。online方式不锁表,但是依赖多源同步组件实现重分布。

注意:

  • 重分布不能和添加set(扩容操作)同时进行
  • online 方式需要部署kafka,consumer组件,并开启实例的数据订阅开关
  • 需要有涉及重分布的数据所占用的空间大小。如果全部分区都参与重分布,则是要有两倍空间
  • 仅TXSQL8.0.24内核版本可以使用该rebalance功能。

重分布基本功能

offline重分布分区:

alter table t_range TDSQL_DISTRIBUTED (s1 valuesless than(50), s2 values less than(200)) offline;

online重分布分区:

alter table t_range TDSQL_DISTRIBUTED (s1 values less than(50), s2 values less than(200));

查看正在运行的任务信息:

/*proxy*/show rebalance_task;

查看所有任务信息:

/*proxy*/show all rebalance_task;

Kill任务:

kill rebalance_task 具体任务id;
kill rebalance_task 12;//停止id为12的任务

重分布增加分区示例

注意:

  • 至少需要具有3个set的分布式实例才可模拟以下示例
  • online 方式需要部署kafka,consumer组件
  • 开启实例的数据订阅开关(在实例详情页面可设置),用于支持online方式的rebalance功能,如下图所示:

示例:

--假设test数据库已有分区表t_range和t_list:
create table t_range(a int key, b int) TDSQL_DISTRIBUTED BY RANGE(a) (s1 values less than(100), s2 values less than(200));

create table t_list(a int key, b int) TDSQL_DISTRIBUTED BY LIST(a) (s1 values  in('1','10','100'), s2 values  in('110','150','200'));

--增加新的range分区s3:
alter table t_range add TDSQL_DISTRIBUTED (s3 values less than (300));

--增加新的list分区s3:
alter table t_list add TDSQL_DISTRIBUTED (s3 values in (40));

--s3增加range分区范围(只能在最后一个set上增加)
alter table t_range add TDSQL_DISTRIBUTED (s3 values less than (600));

--s2增加list分区范围:
alter table  t_list  add TDSQL_DISTRIBUTED (s2 values in (90)); 

注意:

  • 不支持altertable t_range add TDSQL_DISTRIBUTED (s2 values less than (300),s2 values lessthan (400));会报语法错误。s2重复时不能通过语法解析。
  • 支持altertable t_range add TDSQL_DISTRIBUTED (s2 values less than (300),s3 values lessthan (400));一次增加多个分区。

重分布删除分区示例

示例:

--强制删除
alter table t_range force drop TDSQL_DISTRIBUTED s3;

--删除,但是有数据会提示并停止删除操作
alter table t_list drop TDSQL_DISTRIBUTED s3;

--一次性删除多个分区
alter table t_range drop TDSQL_DISTRIBUTED s2,s3;

注意:

  • 当全局分区表只剩下一个分区时,会拒绝删除分区的操作。
  • 删除分区会清空数据,删除路由,请谨慎操作。
  • 当想删除所有分区时,会拒绝:Can'tdelete all partitions。
  • force删除一个分区后,会把指定分区上的表清空,但是表结构还在。
  • 当有s1<100, s2<200,force drop s1后,s1上数据会清空,路由会转到s2(0-200),此功能同drop partition,往后归属。

Range表支持语法

注意:

  • offline和online支持范围一致。下面以offline为例,online方式只需去掉后面的offline标志即可
  • 分区表语句中指定的s1、s2、s3…是每个set的别名,基于实现原理,不能自定义,只能按照顺序依次命名为s1、s2、s3…
--重分布后路由:s1:0-100 s2:100-200 s3:200-300 s4:300-500
alter table t_range add TDSQL_DISTRIBUTED (s4 values less than (500));

--重分布后路由:s1:0-100 s2:100-200 s3:200-300 s4:300-400 s5:400-500  
alter table t_range add TDSQL_DISTRIBUTED (s5 values less than (500)); 

--重分布后路由:s1:0-100 s4:100-400
alter table t_range drop TDSQL_DISTRIBUTED s2,s3;

--重分布后路由:s1:0-50 s2:50-200 s3:200-300 s4:300-400
alter table t_range TDSQL_DISTRIBUTED (s1 values less than(50), s2 values less than(200)) offline;

--重分布后路由:s1:0-300 s4:300-400
alter table t_range TDSQL_DISTRIBUTED (s1 values less than(300)) offline;

--重分布后路由:s1:0-100 s2:100-300 s4:300-400
alter table t_range TDSQL_DISTRIBUTED (s1 values less than(100), s2 values less than(300)) offline;

--重分布后路由:s1:0-50 s5:50-100 s2:100-200 s3:200-300 s4:300-400
alter table t_range TDSQL_DISTRIBUTED (s1 values less than(50), s5 values less than(100)) offline;

--重分布后路由:s2:0-50 s1:50-200 s3:200-300 s4:300-400
alter table t_range TDSQL_DISTRIBUTED (s2 values less than(50), s1 values less than(200)) offline;

--重分布后路由:s1:0-100 s2:100-200 s3:200-400
alter table t_range TDSQL_DISTRIBUTED (s1 values less than(100), s2 values less than(200),s3 values less than(400)) offline;

注意:

  • alter table t_range TDSQL_DISTRIBUTED (s1 values less than(150)) offline;//不支持,需要写为s1 values less than(150),s2 values less than(200)
  • alter table t_range TDSQL_DISTRIBUTED (s1 values less than(100), s2 values less than(300),s4 values less than(400)) offline;和alter table test.t_range TDSQL_DISTRIBUTED (s2 values less than(300),s4 values less than(400)) offline;的区别,前者是表示s2和s3分区重分布,s1不参与重分布;后者是s1,s2,s3重分布到s2上

List表支持语法

示例:

--重分布后路由:s1:1 2 3 11 12   s2:4 5 6   s3:7 8 9
alter table t_list add TDSQL_DISTRIBUTED (s1 values in ('11','12'));

--重分布后路由:s1:1 2 3   s2:4 5 6   s3:7 8 9 s4:11 12
alter table t_list add TDSQL_DISTRIBUTED (s4 values in ('11','12'));

--重分布后路由:s3:7 8 9
alter table t_list drop TDSQL_DISTRIBUTED s1,s2;

--重分布后路由:s1:1 2 6   s2:4 5 3   s3:7 8 9
alter table t_list TDSQL_DISTRIBUTED (s1 values in ('1','2','6'),s2 values in ('4','5','3')) offline;

--重分布后路由:s1:1 2 3 4 5 6   s3:7 8 9
alter table t_list TDSQL_DISTRIBUTED (s1 values in ('1','2','3','4','5','6')) offline;

--重分布后路由:s1:1 2   s2:4 5 6   s3:7 8 9 s4:3
alter table t_list TDSQL_DISTRIBUTED (s1 values in ('1','2'), s4 values in ('3')) offline;

List表不支持语法

--缺少6
alter table t_list TDSQL_DISTRIBUTED (s1 values in ('1','2'),s2 values in ('4','5','3')) offline;

--多出7,写成s1 values in ('1','2''6','7'),s2 values in ('4','5','3'),s3 values in ('8','9')则支持
alter table t_list TDSQL_DISTRIBUTED (s1 values in ('1','2''6','7'),s2 values in ('4','5','3')) offline;

Range表的rebalance示例

--通过proxy连接数据库,创建数据库和range分区表
create database if not exists rebalance;
use rebalance;
CREATE TABLE `sbtest1` (
  `id` int NOT NULL,
  `k` int NOT NULL DEFAULT '0',
  `c` char(120) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
  `pad` char(60) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin TDSQL_DISTRIBUTED BY RANGE(id) (s1 values less than ('50000'),s2 values less than ('100000'));

--给range分区表增加一个分区s3
alter table sbtest1 add TDSQL_DISTRIBUTED (s3 values less than ('150000'));

--执行show create table sbtest1;语句确认range分区表的三个分区范围正确

--往各个分区分别插入数据,查询数据所在分区正确(数据量多少可自行决定,只要不超过分区范围限制)
insert into sbtest1(id,k,c,pad) values (19999,1,'abc','abc');
insert into sbtest1(id,k,c,pad) values (25000,1,'abc','abc');
insert into sbtest1(id,k,c,pad) values (49999,1,'abc','abc');
insert into sbtest1(id,k,c,pad) values (50000,2,'abc','abc');
insert into sbtest1(id,k,c,pad) values (55000,2,'abc','abc');
insert into sbtest1(id,k,c,pad) values (99999,2,'abc','abc');
insert into sbtest1(id,k,c,pad) values (100000,3,'abc','abc');
insert into sbtest1(id,k,c,pad) values (120000,3,'abc','abc');
insert into sbtest1(id,k,c,pad) values (149999,3,'abc','abc');
/*sets:allsets*/select * from sbtest1;

--执行如下sql语句进行offline方式的重分布,将s1分区的[40000,50000)迁到s2分区,s2分区的[70000,100000)迁到s3分区:
alter table sbtest1 TDSQL_DISTRIBUTED (s1 values less than(40000), s2 values less than(70000),s3 values less than(150000)) offline; 

--执行show create table sbtest1;语句确认range分区表的三个分区范围重分布正确

--查询offline方式数据重分布结果正确
/*sets:allsets*/select * from sbtest1;

--执行如下sql语句进行online方式的重分布,将s1分区的[20000,40000)迁到s2分区,s3分区的[70000,120000)迁到s2分区:
alter table sbtest1 TDSQL_DISTRIBUTED (s1 values less than(20000), s2 values less than(120000),s3 values less than(150000)); 

--执行show create table sbtest1;语句确认range分区表的三个分区范围重分布正确

--查询online方式数据重分布结果正确
/*sets:allsets*/select * from sbtest1;

List表的rebalance示例

--通过proxy连接数据库,创建数据库和list分区表
create database if not exists rebalance;
use rebalance;

CREATE TABLE `t_list` (
  `a` int NOT NULL,
  `b` int DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin TDSQL_DISTRIBUTED BY LIST(a) (s1 values in ('1','10','100'),s2 values in ('110','150','200'));

--给list分区表增加一个分区s3
alter table t_list add TDSQL_DISTRIBUTED (s3 values in ('40','300','180'));

--执行show create table t_list;语句确认list分区表的三个分区范围正确

--往各个分区分别插入数据,查询数据所在分区正确
insert into t_list(a,b) values(1,1),(10,1),(100,1),(110,2),(150,2),(200,2),(40,3),(300,3),(180,3);
/*sets:allsets*/select * from t_list;

--执行如下sql语句进行offline方式的重分布,将s1分区的100迁到s2分区
alter table t_list TDSQL_DISTRIBUTED (s1 values in('1','10'), s2 values in('100','110','150','200')) offline;

--执行show create table t_list;语句确认list分区表的三个分区范围重分布正确

--查询offline方式数据重分布结果正确
/*sets:allsets*/select * from t_list;

--执行如下sql语句进行online方式的重分布,将s2分区的100,150迁到s3分区:
alter table t_list TDSQL_DISTRIBUTED (s1 values in('1','10'), s2 values in('110','200'), s3 values in('40','300','180','100','150'));

--执行show create table t_list;语句确认list分区表的三个分区范围重分布正确

--查询online方式数据重分布结果正确
/*sets:allsets*/select * from t_list;

其他功能介绍

  1. 任务抢占:所有proxy都会执行select任务中未完成且时间戳停止时间超过租约时间(目前设置为120s)的任务,获得时间戳停止时间time1。然后尝试更新这条记录(带where update_time = time1条件)如果更新成功则代表拿到任务,开始写时间戳和自己的proxyid。如果更新失败则代表未拿到任务。

  2. kill任务id:直接写任务表的is_stop=1(重试,300s超时,可配置),然后想应proxy会感知到任务需要停止,执行停止。

  3. 任务迁移:当任务时间戳不更新时,时差超过租约则会被任务抢占,抢占到的proxy会重新执行重分布任务。

  4. proxy重启继续执行:因为在租约内,所以不会被抢占,重启后会查找proxyid为自身,is_finish=0且还在租约内的任务写入队列执行。

  5. 当前任务执行ctrl+c断开连接,会写入一个stop任务,stop任务执行时,会先从任务列表中查找是否存在该任务,如果存在,则表示当前proxy正在运行该任务,直接执行stop影响状态转换即可回滚。如果不存在,表示当前任务已经停止。

二级分区的自增

功能介绍

针对一级Hash二级Range分区自增的情况。

使用场景

使用二级分区的场景下。

Range表自动化创建分区示例

注意:

  • 测试前确保网关参数已经打开,默认是开启的,可以通过赤兔页面查看:
--创建range二级分区表:
DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
CREATE TABLE test.t1 (
id int primary key, 
hired varchar(100)
) shardkey=id partition by range (day(hired)) 
( 
PARTITION p0 VALUES LESS THAN (20211020), 
PARTITION p2 VALUES LESS THAN (20211021)
);
--查看当前分区:
MySQL [rebalance]> show create table test.t1\G;
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `id` int NOT NULL,
  `hired` varchar(100) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin shardkey=id PARTITION BY RANGE ( day(hired) ) ( PARTITION p0 VALUES LESS THAN (20211020), PARTITION p2 VALUES LESS THAN (20211021))
1 row in set (0.001 sec)

--等待数分钟左右,查看是否自动创建分区:
MySQL [rebalance]> show create table test.t1\G;
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `id` int NOT NULL,
  `hired` varchar(100) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin shardkey=id PARTITION BY RANGE ( day(hired) ) ( PARTITION p0 VALUES LESS THAN (20211020), PARTITION p2 VALUES LESS THAN (20211021), PARTITION p_auto_20211029 VALUES LESS THAN (20211030), PARTITION p_auto_20211030 VALUES LESS THAN (20211031), PARTITION p_auto_20211031 VALUES LESS THAN (20211101), PARTITION p_auto_20211101 VALUES LESS THAN (20211102), PARTITION p_auto_20211102 VALUES LESS THAN (20211103))
1 row in set (0.001 sec)

--在自动化创建的分区插入数据:
INSERT INTO test.t1(id,hired) VALUES(1,'20211027');
SELECT * from test.t1;