AUTO_RANDOM 从 v3.1.0 版本开始引入

    关于如何在高并发写入场景下调优 TiDB,请参阅 。

    AUTO_RANDOM 是应用在 BIGINT 类型列的属性,用于列值的自动分配。其自动分配的值满足随机性唯一性

    以下语句均可创建包含 AUTO_RANDOM 列的表,其中 AUTO_RANDOM 列必须被包含在主键中,并且是主键的第一列。

    在用户执行 INSERT 语句时:

    • 如果语句中显式指定了 AUTO_RANDOM 列的值,则该值会被正常插入到表中。
    • 如果语句中没有显式指定 AUTO_RANDOM 列的值,TiDB 会自动生成一个随机的值插入到表中。

    TiDB 自动分配的 AUTO_RANDOM(S, R) 列值共有 64 位:

    • S 表示分片位的数量,取值范围是 115。默认为 5
    • R 表示自动分配值域的总长度,取值范围是 3264。默认为 64

    AUTO_RANDOM 列值的具体结构如下:

    • 保留位的长度为 64-R,保留位的内容始终为 0
    • 分片位的内容通过计算当前事务的开始时间的哈希值而得。要使用不同的分片位数量(例如 10),可以在建表时指定 AUTO_RANDOM(10)
    • 自增位的值保存在存储引擎中,按顺序分配,每次分配完值后会自增 1。自增位保证了 AUTO_RANDOM 列值全局唯一。当自增位耗尽后,再次自动分配时会报 Failed to read auto-increment value from storage engine 的错误。

    分片位长度 (S) 的选取:

    • 由于总位数固定为 64 位,分片位的数量会影响到自增位的数量:当分片位数增加时,自增位数会减少,反之亦然。因此,你需要权衡“自动分配值的随机性”以及“可用空间”。
    • 最佳实践是将分片位设置为 log(2, x),其中 x 为当前集群存储引擎的数量。例如,一个 TiDB 集群中存在 16 个 TiKV,分片位可以设置为 log(2, 16),即 4。在所有 Region 被均匀调度到各个 TiKV 上以后,此时大批量写入的负载可被均匀分布到不同 TiKV 节点,以实现资源最大化利用。

    值域长度 (R) 的选取:

    • 通常,在应用程序的数值类型无法表示完整的 64 位整数时需要设置 R 参数。
    • 例如:JSON number 类型的取值范围为 [-(2^53)+1, (2^53)-1],而 TiDB 很容易会为 AUTO_RANDOM(5) 的列分配超出该范围的整数,导致应用程序读取该列的值时出现异常。此时,你可以用 AUTO_RANDOM(5, 54) 代替 AUTO_RANDOM(5),使得 TiDB 不会分配出大于 9007199254740991 (2^53-1) 的整数。

    AUTO RANDOM 列隐式分配的值会影响 last_insert_id()。可以使用 SELECT last_insert_id() 获取上一次 TiDB 隐式分配的 ID。

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

    • 该属性必须指定在 BIGINT 类型的主键列上,否则会报错。此外,当主键属性为 NONCLUSTERED 时,即使是整型主键列,也不支持使用 AUTO_RANDOM。要了解关于 CLUSTERED 主键的详细信息,请参考聚簇索引
    • 不支持使用 ALTER TABLE 来修改 AUTO_RANDOM 属性,包括添加或移除该属性。
    • 支持将 AUTO_INCREMENT 属性改为 AUTO_RANDOM 属性。但在 AUTO_INCREMENT 的列数据最大值已接近 BIGINT 类型最大值的情况下,修改可能会失败。
    • 不支持修改含有 AUTO_RANDOM 属性的主键列的列类型。
    • 不支持与 AUTO_INCREMENT 同时指定在同一列上。
    • 不支持与列的默认值 DEFAULT 同时指定在同一列上。
    • AUTO_RANDOM 列的数据很难迁移到 AUTO_INCREMENT 列上,因为 AUTO_RANDOM 列自动分配的值通常都很大。