写点什么

关于 auto_random 的几个知识点

  • 2022 年 7 月 11 日
  • 本文字数:2674 字

    阅读完需:约 9 分钟

作者: 啦啦啦啦啦原文来源:https://tidb.net/blog/c8cda108


【是否原创】是


【首发渠道】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 row affected (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)
复制代码



根据官方文档该行值在二进制形式下,除去符号位的最高五位(称为 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: can't 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' can't 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 **** 方式解决不了二级索引热点的问题。


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


发布于: 刚刚阅读数: 3
用户头像

TiDB 社区官网:https://tidb.net/ 2021.12.15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
关于auto_random的几个知识点_管理与运维_TiDB 社区干货传送门_InfoQ写作社区