AUTO_RANDOM 从 v3.1.0 版本开始引入

警告:

当前 AUTO_RANDOM 属性为实验功能,不建议在生产环境中使用。在后续版本中,AUTO_RANDOM 的语法或语义可能会变化。

使用 AUTO_RANDOM 功能前,须在 TiDB 配置文件 experimental 部分设置 allow-auto-random = true。该参数详情可参见 allow-auto-random

使用场景

AUTO_RANDOM 用于解决大批量写数据入 TiDB 时因含有整型自增主键列的表而产生的热点问题。详情参阅 TiDB 高并发写入场景最佳实践

以下面语句建立的表为例:

  1. create table t (a int primary key auto_increment, b varchar(255))

在以上语句所建的表上执行大量未指定主键值的 INSERT 语句,示例如下:

  1. insert into t(b) values ('a'), ('b'), ('c')

如以上语句,由于未指定主键列的值(a 列),TiDB 会使用连续自增的行值作为行 ID,可能导致单个 TiKV 节点上产生写入热点,进而影响对外提供服务的性能。要避免这种性能下降,可以在执行建表语句时为 a 列指定 AUTO_RANDOM 属性而不是 AUTO_INCREMENT 属性。示例如下:

  1. create table t (a int primary key auto_random, b varchar(255))

或者

  1. create table t (a int auto_random, b varchar(255), primary key (a))

此时再执行形如 INSERT INTO t(b) values...INSERT 语句。

  • 如果该 INSERT 语句没有指定整型主键列(a 列)的值,或者指定为 NULL,TiDB 会为该列自动分配值。该值不保证自增,不保证连续,只保证唯一,避免了连续的行 ID 带来的热点问题。
  • 如果该 INSERT 语句显式指定了整型主键列的值,和 AUTO_INCREMENT 属性类似,TiDB 会保存该值。注意,如果未在系统变量 @@sql_mode 中设置 NO_AUTO_VALUE_ON_ZERO, 即使显式指定整型主键列的值为 0,TiDB 也会为该列自动分配值。

自动分配值的计算方式如下:

该行值在二进制形式下,除去最高位(无论是 unsigned 还是 signed)的次高五位(称为 shard bits)由当前事务的开始时间决定,剩下的位数按照自增的顺序分配。

若要使用一个不同的 shard bits 的数量,可以在 AUTO_RANDOM 后面加一对括号,并在括号中指定想要的 shard bits 数量。示例如下:

  1. create table t (a int primary key auto_random(3), b varchar(255))

以上建表语句中,shard bits 的数量为 3。shard bits 的数量的取值范围是 [1, field_max_bits),其中 field_max_bits 为整型主键列类型占用的位长度。

创建完表后,使用 SHOW WARNINGS 可以查看当前表可支持的最大隐式分配的次数:

  1. show warnings
  1. +-------+------+------------------------------------------------+
  2. | Level | Code | Message |
  3. +-------+------+------------------------------------------------+
  4. | Note | 1105 | Available implicit allocation times: 268435455 |
  5. +-------+------+------------------------------------------------+

另外,含有 AUTO_RANDOM 属性的表在系统表 information_schema.tablesTIDB_ROW_ID_SHARDING_INFO 一列的值为 PK_AUTO_RANDOM_BITS=x,其中 x 为 shard bits 的数量。

要获取上一次 TiDB 隐式分配的 ID,可以使用 select last_insert_id() 查看,例如:

  1. insert into t (b) values ("b")
  2. select * from t;
  3. select last_insert_id()

可能得到的结果如下:

  1. +------------+---+
  2. | a | b |
  3. +------------+---+
  4. | 1073741825 | b |
  5. +------------+---+
  6. +------------------+
  7. | last_insert_id() |
  8. +------------------+
  9. | 1073741825 |
  10. +------------------+

兼容性

TiDB 支持解析版本注释语法。示例如下:

  1. create table t (a int primary key /*T!30100 auto_random */)
  1. create table t (a int primary key auto_random)

以上两个语句含义相同。

show create table 的结果中,AUTO_RANDOM 属性会被注释掉。注释会附带一个版本号,例如 /*T!30100 auto_random */。其中 30100 表示 v3.1.0 引入该功能,低版本的 TiDB 能够忽略带有上述注释的 AUTO_RANDOM 属性。

该功能支持向前兼容,即降级兼容。v3.1.0 以前的 TiDB 会忽略表(带有上述注释)的 AUTO_RANDOM 属性,因此能够使用含有该属性的表。

使用限制

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

  • 该属性必须指定在整数类型的主键列上,否则会报错。例外情况见关于 alter-primary-key 配置项的说明
  • 不支持使用 ALTER TABLE 来修改 AUTO_RANDOM 属性,包括添加或移除该属性。
  • 不支持修改含有 AUTO_RANDOM 属性的主键列的列类型。
  • 不支持与 AUTO_INCREMENT 同时指定在同一列上。
  • 不支持与列的默认值 DEFAULT 同时指定在同一列上。
  • 插入数据时,不建议自行显式指定含有 AUTO_RANDOM 列的值。不恰当地显式赋值,可能会导致该表提前耗尽用于自动分配的数值。

关于 alter-primary-key 配置项的说明

  • alter-primary-key = true 时,即使是整型主键列,也不支持使用 AUTO_RANDOM
  • 配置文件中的 alter-primary-keyallow-auto-random 两个配置项的值不允许同时为 true