在前面的章节提到过,TiDB 的每一行数据都包含一个隐式的 。_tidb_rowid 会被编码到存储引擎的 Key 上,在 TiKV 中,这决定了数据在 TiKV 中的 Region 位置。

    如果表的主键为整数类型,则 TiDB 会把表的主键映射为 _tidb_rowid,即使用“主键聚簇索引”。在这种情况下,如果表使用了 AUTO_INCREMENT 就会造成主键的热点问题,并无法使用 SHARD_ROW_ID_BITS 来打散热点。

    针对上述热点问题,如果使用 AUTO_INCREMENT 仅仅只是用来保证主键唯一性(不需要连续或递增),那么我们可以将 改为 AUTO_RANDOM,插入数据时让 TiDB 自动为整型主键列分配一个值,消除行 ID 的连续性,从而达到打散热点的目的。

    AutoRandom 提供以下的功能:

    • 唯一性:TiDB 始终保持填充数据在表范围内的唯一性。
    • 高性能:TiDB 能够以较高的吞吐分配数据,并保证数据的随机分布以配合 PRE_SPLIT_REGION 语法共同使用,避免大量写入时的写热点问题。
    • 支持隐式分配和显式写入:类似列的 AutoIncrement 属性,列的值既可以由 TiDB Server 自动分配,也可以由客户端直接指定写入。该需求来自于使用 Binlog 进行集群间同步时,保证上下游数据始终一致。

    在建表时,AUTO_RANDOM 关键字可以作为列属性,指定在 TiDB 主键列上。TiDB 4.0 中,列属性语法定义被更新为:

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

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

    此时再执行形如 INSERT INTO t(b) values… 的 INSERT 语句,示例如下:

    注意:

    • 如果该 INSERT 语句显式指定了整型主键列的值,和 AutoIncrement 属性类似,TiDB 会保存该值。
    • 若在单条 INSERT 语句中写入多个值,AutoRandom 属性会保证分配 ID 的连续性,同时 LAST_INSERT_ID() 返回第一个分配的值,这使得可以通过 LAST_INSERT_ID() 结果推断出所有被分配的 ID。

    与 AutoRandom 相比,TiDB 还可以通过其他的方式避免主键自动分配时的写热点问题:

    • 在这种方式下,主键索引被当做普通的唯一索引处理,使得数据的写入可以由 SHARD_ROW_ID_BITS 语法打散避免热点,但缺点在于,主键仍然存在索引写入的热点,同时在查询时,由于关闭了聚簇索引,针对主键的查询需要进行一次额外的回表。

    参考文献:

    参阅 AUTO_RANDOM 的详细说明