自增主键无法单调递增

自增主键无法单调递增

Content #

对于单体数据库自身来说,自增主键确实是单调递增的。但使用自增主键也是有前提的,那就是主键生成的速度要能够满足应用系统的并发需求。而在高并发量场景下,每个事务都要去申请主键,数据库如果无法及时处理,自增主键就会成为瓶颈。那么,这时只用自增主键已经不能解决问题了,往往还要在应用系统上做些优化。

比如,对于 Oracle 数据库,常见的优化方式就是由 Sequence 负责生成主键的高位,由应用服务器负责生成低位数字,拼接起来形成完整的主键。

图中展示这样的例子,数据库的 Sequence 是一个 5 位的整型数字,范围从 10001 到 99999。每个应用系统实例先拿到一个号,比如 10001,应用系统在使用这 5 位为作为高位,自己再去拼接 5 位的低位,这样得到一个 10 位长度的主键。这样,每个节点访问一次 Sequence 就可以处理 99999 次请求,处理过程是基于应用系统内存中的数据计算主键,没有磁盘 I/O 开销,而相对的 Sequence 递增时是要记录日志的,所以方案改进后性能有大幅度提升。

这个方案虽然使用了 Sequence,但也只能保证全局唯一,数据表中最终保存的主键不再是单调递增的了。

因为,几乎所有数据库中的自增字段或者自增序列都是要记录日志的,也就都会产生磁盘 I/O,也就都会面临这个性能瓶颈的问题。所以,我们可以得出一个结论:在一个海量并发场景下,即使借助单体数据库的自增主键特性,也不能实现单调递增的主键。

Viewpoints #

From #

17 | 为什么不建议你使用自增主键?