报错代码唯一性

【 TiDB 使用环境】
【概述】:场景 + 问题概述

执行split table命令报错了,报错代码是ERROR 1105(HY000),
ERROR 1105 (HY000): Split table t1 region step value should more than 1000, step 317 is invalid

我在社区上搜索这个报错代码,发现这个报错代码还代表其他意思:

ERROR 1105 (HY000): runtime error: index out of range [1] with length 1

跟我的报错信息不一样。

看样子是把一类报错归类到一个报错代码。
请问,tidb中,报错代码表示的含义不是唯一的吗?

【背景】:做过哪些操作
【现象】:业务和数据库现象
【问题】:当前遇到的问题
【业务影响】:
【TiDB 版本】:
【附件】:

1 个赞

split table语句发下

mysql> split table t1 between(82461) and (88804) regions 20;

TiDB 兼容 MySQL 的错误码,在大多数情况下,返回和 MySQL 一样的错误码。关于 MySQL 的错误码列表,详见 MySQL 5.7 Error Message Reference
在MySQL中1105代表的是一种类型


https://dev.mysql.com/doc/mysql-errors/5.7/en/server-error-reference.html

表结构也发一下?

CREATE TABLE t1 (
 id INT NOT NULL PRIMARY KEY auto_increment,
 b INT NOT NULL,
 pad1 VARBINARY(1024),
 pad2 VARBINARY(1024),
 pad3 VARBINARY(1024)
);

我觉得报错代码应该做的精细化一些

我这个split table,为啥会报错呢?是内部有限制吗?

提示就是显示region step value should more than 1000, step 317 is invalid, 你设置成regions 6
(88804-82461)/20≈317
(88804-82461)/6=1057

这个step是啥意思?怎么还有限制呢?

由于 row_id 是整数,所以根据指定的 lower_valueupper_value 以及 region_num ,可以推算出需要切分的 key。TiDB 先计算 step( step = (upper_value - lower_value)/region_num ),然后在 lower_valueupper_value 之间每隔 step 区间切一次,最终切出 region_num 个 Region

相当于每个region的数量吧

是不是说,这个step大于1000,是内部机制已经定义好的,必须大于1000?

TiDB 先计算 step (),然后在 和 之间每隔 step 区间切一次,最终切出 个 Region。 row_id lower_value upper_value region_num step = (upper_value - lower_value)/region_num lower_value upper_value region_num

Split Region 使用文档 |PingCAP 文档

看提示是这样

读TiDB 源码

https://github.com/pingcap/tidb/blob/v5.4.0/executor/split.go
https://github.com/pingcap/tidb/blob/v4.0.16/executor/split.go

var minRegionStepValue = int64(1000)

在 4 版本的时候会报该错误:
if step < minRegionStepValue {
return 0, 0, errors.Errorf(“Split table %s region step value should more than %v, step %v is invalid”, e.tableInfo.Name, minRegionStepValue, step)
}
return lowerValue, step, nil
在 5 版本的时候 信息提示会更明确
if step < minRegionStepValue {
errMsg := fmt.Sprintf(“the region size is too small, expected at least %d, but got %d”, minRegionStepValue, step)
return 0, 0, ErrInvalidSplitRegionRanges.GenWithStackByArgs(errMsg)
}
return lowerValue, step, nil

2 个赞

那看来就是代码里面定义了1000。:+1:

不过这样设计的话,就没办法预分配分区了,比如说,可能订单表里主键里有个时间字段,在大促之前,可以预计某个区间段的数据量会比较大,针对某个时间段提前做下预分区,这样真正有数据写入时,就不会产生热点了。

不过我测试起来,貌似并没有限制每个region的大小

mysql> select * from test.`add_column`;
+----+-------+----+-------+
| c1 | c2    | c3 | c4    |
+----+-------+----+-------+
|  1 | apple |  1 | apple |
|  2 | bob   |  2 | bob   |
|  3 | cat   |  3 | cat   |
+----+-------+----+-------+
3 rows in set (0.07 sec)

mysql> split table test.`add_column` between (1, 'apple') and (1000, 'xx') regions 100;
+--------------------+----------------------+
| TOTAL_SPLIT_REGION | SCATTER_FINISH_RATIO |
+--------------------+----------------------+
|                 99 |                    1 |
+--------------------+----------------------+
1 row in set (0.54 sec)

mysql> select count(1) from information_schema.TIKV_REGION_STATUS where DB_NAME='test' and TABLE_NAME='add_column';
+----------+
| count(1) |
+----------+
|      101 |
+----------+
1 row in set (0.02 sec)

可能版本不一样


可能是只针对int类型来判断的,加1000的限制确实还算可以理解,不过报错提示可以更明显一些