深入理解 auto_random 的几个关键知识点

网友投稿 585 2024-04-10



【是否原创】是

深入理解 auto_random 的几个关键知识点

【首发渠道】TiDB 社区

【首发渠道链接】其他平台首发请附上对应链接

【正文】

一.自动分配值的计算方式

测试:创建一个测试表,插入5行数据。

mysql> CREATE TABLE t (a BIGINT(20) auto_random PRIMARY KEY CLUSTERED, b VARCHAR(255)); Query OK, 0 rows affected, 1 warning (0.32 sec) mysql> insert into t(b) values(a); Query OK, 1 row affected (0.12 sec) mysql> insert into t(b) values(b); Query OK, 1 rowaffected(0.00 sec) mysql> insert into t(b) values(c); Query OK, 1 row affected (0.01 sec) mysql> insert into t(b) values(d); Query OK, 1 row affected (0.01 sec) mysql> insert into t(b) values(e); Query OK, 1 row affected (0.01 sec) mysql> select * from t; +---------------------+------+ | a | b | +---------------------+------+ | 576460752303423492 | d | | 2017612633061982209 | a | | 2017612633061982211 | c | | 3458764513820540933 | e | | 7493989779944505346 | b | +---------------------+------+ 5 rows in set (0.00 sec) keyvalue二进制a2017612633061982209 1110000000000000000000000000000000000000000000000000000000001b7493989779944505346110100000000000000000000000000000000000000000000000000000000010c2017612633061982211 1110000000000000000000000000000000000000000000000000000000011d576460752303423492 100000000000000000000000000000000000000000000000000000000100e345876451382054093311000000000000000000000000000000000000000000000000000000000101

根据官方文档该行值在二进制形式下,除去符号位的最高五位(称为 shard bits)由当前事务的开始时间决定,剩下的位数按照自增的顺序分配。从上表可以直观地看到二进制末尾由001-->010-->011-->100-->101依次递增1。转换成10进制之后就既不保证自增也不保证连续,只保证唯一,以此来解决自增主键带来的写入热点 。

二.关于auto_random的几个常见误区

以下是从官方文档copy的关于auto_randomde1使用限制:

目前在 TiDB 中使用 AUTO_RANDOM 有以下限制:

该属性必须指定在整数类型的主键列上,否则会报错。此外,当主键属性为 NONCLUSTERED 时,即使是整型主键列,也不支持使用 AUTO_RANDOM。要了解关于 CLUSTERED主键的详细信息,请参考聚簇索引

不支持使用 ALTER TABLE 来修改 AUTO_RANDOM 属性,包括添加或移除该属性。

不支持修改含有 AUTO_RANDOM 属性的主键列的列类型。

不支持与 AUTO_INCREMENT 同时指定在同一列上。

不支持与列的默认值 DEFAULT 同时指定在同一列上。

插入数据时,不建议自行显式指定含有 AUTO_RANDOM 列的值。不恰当地显式赋值,可能会导致该表提前耗尽用于自动分配的数值。

以下问题由asktug论坛帖子整理而来

1.官方文档说描述到插入数据时,不建议自行显式指定含有 AUTO_RANDOM 列的值。不恰当地显式赋值,可能会导致该表提前耗尽用于自动分配的数值。那么哪些情况是恰当的赋值呢?

首先,显式插入需要将系统参数allow_auto_random_explicit_insert打开。我们显式地插入一条包含auto_random字段的数据,给定一个很大的值例如11111111111111111111111111111111111111111111111111111111111110,转换为10进制为4611686018427387902。因为二进制末尾自增,猜测最多只能插入一次自动分配的值就将耗尽,实际测试看下。

mysql> set @@allow_auto_random_explicit_insert = true; Query OK, 0 rows affected (0.00 sec) mysql> insert into t values(4611686018427387902,f); Query OK, 1 row affected (0.04 sec) mysql> insert into t(b) values(g); Query OK, 1 row affected (0.01 sec) mysql> insert into t(b) values(h); ERROR 8059 (HY000): Failed to read auto-random value from storage engine

因此,我们手动插入一条由上一条auto_random转化为2进制末尾递增不多的值,可以不用担心耗尽的问题(生产环节强烈不建议这么做)。当然真实环境除了逻辑导入导出我也想不到需要去显式插入的场景。

2.AUTO_RANDOM 能限制生成的id长度吗

无法限制。为了为保证可隐式分配的次数最大,从 v4.0.3 开始,AUTO_RANDOM 列类型只能为 BIGINT。如果是程序兼容性问题建议用高兼容性schema,使用非聚簇表,用shard_row_id_bits和pre_split_regions来缓解写入热点问题。

3.AUTO_RANDOM 一定不是连续的吗

不一定,auto_random的值是由时间+递增值组成,当insert 多个value时 会是一段连续递增的值,实际测试看下。

mysql> truncate table t; Query OK, 0 rows affected (0.30 sec) mysql> insert into t(b) values(a),(b),(c),(d),(e); Query OK, 5 rows affected (0.09 sec) Records: 5 Duplicates: 0 Warnings: 0mysql> select * from t; +---------------------+------+ | a | b | +---------------------+------+ | 3458764513820540929 | a | | 3458764513820540930 | b | | 3458764513820540931 | c | | 3458764513820540932 | d | | 3458764513820540933 | e | +---------------------+------+ 5 rows in set (0.00 sec)

4.AUTO_INCRMENT可以改为AUTO_RANDOM 吗

不支持使用 ALTER TABLE 来修改 AUTO_RANDOM 属性,但是在开启参数tidb_allow_remove_auto_inc时可以由AUTO_INCRMENT改为AUTO_RANDOM,前提是表为聚簇表,非聚簇表无法修改。实际测试看下。

mysql> CREATE TABLE t3 (a BIGINT(20) auto_random PRIMARY KEY CLUSTERED, b VARCHAR(255)); Query OK, 0 rows affected, 1 warning (0.25 sec) mysql> alter table t10 modify a BIGINT(20) auto_increment; ERROR 8200 (HY000): Unsupported modify column: cant set auto_increment mysql> CREATE TABLE t4 (a BIGINT(20) auto_increment PRIMARY KEY CLUSTERED, b VARCHAR(255)); Query OK, 0 rows affected (0.10 sec) mysql> alter table t4 modify a BIGINT(20) auto_random; ERROR 1231 (42000): Variable tidb_allow_remove_auto_inc cant be set to the value of enabled mysql> set @@tidb_allow_remove_auto_inc=1; Query OK, 0 rows affected (0.00 sec) mysql> alter table t4 modify a BIGINT(20) auto_random; Query OK, 0 rows affected (0.20 sec) mysql> CREATE TABLE t5 (a BIGINT(20) auto_increment PRIMARY KEY NONCLUSTERED, b VARCHAR(255)); Query OK, 0 rows affected (0.17 sec) mysql> alter table t5 modify a BIGINT(20) auto_random; ERROR 8216 (HY000): Invalid auto random: auto_random can only be converted from auto_increment clustered primary key

5.AUTO_RANDOM 一定能解决写入热点问题吗

不一定,AUTO_RANDOM方式解决不了二级索引热点的问题。

以上,如果有不严谨或者纰漏的地方请见谅。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:深入浅出:TiDB 优化器逻辑优化与 OR 表达式条件消除
下一篇:深入理解 TiDB Placement Rules 功能的应用与优化
相关文章