分布式数据库 30 讲
王磊
光大银行首席数据架构师
29144 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 34 讲
结束语 (1讲)
分布式数据库 30 讲
15
15
1.0x
00:00/00:00
登录|注册

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

尾部热点问题
使用单调递增主键的问题
产生自增主键的难点
高并发场景下的瓶颈
计数器和事务绑定
事务冲突导致跳跃
连续递增
单调递增
唯一性
CockroachDB
随机主键是否能避免热点问题
外置Snowflake
内置Random ID
内置UUID
分布式数据库中的问题
无法单调递增
无法连续递增
期待的特性
Oracle中的序列
MySQL中的自增主键定义
学习资料
思考题
随机主键方案
自增主键的问题
单体数据库的自增主键
自增主键的特性
为什么不建议使用自增主键

该思维导图由 AI 生成,仅供参考

你好,我是王磊,你也可以叫我 Ivan。
有经验的数据库开发人员一定知道,数据库除了事务处理、查询引擎这些核心功能外,还会提供一些小特性。它们看上去不起眼,却对简化开发工作很有帮助。
不过,这些特性的设计往往是以单体数据库架构和适度的并发压力为前提的。随着业务规模扩大,在真正的海量并发下,这些特性就可能被削弱或者失效。在分布式架构下,是否要延续这些特性也存在不确定性,我们今天要聊的自增主键就是这样的小特性。
虽然,我对自增主键的态度和第 16 讲提到的存储过程一样,都不推荐你使用,但是原因各有不同。存储过程主要是工程方面的原因,而自增主键则是架构上的因素。好了,让我们进入正题吧。

自增主键的特性

自增主键在不同的数据库中的存在形式稍有差异。在 MySQL 中,你可以在建表时直接通过关键字 auto_increment 来定义自增主键,例如这样:
create table ‘test’ (
‘id’ int(16) NOT NULL AUTO_INCREMENT,
‘name’ char(10) DEFAULT NULL,
PRIMARY KEY(‘id’)
) ENGINE = InnoDB;
而在 Oracle 中则是先声明一个连续的序列,也就是 sequence,而后在 insert 语句中可以直接引用 sequence,例如下面这样:
create sequence test_seq increment by 1 start with 1;
insert into test(id, name) values(test_seq.nextval, ' An example ');
自增主键给开发人员提供了很大的便利。因为,主键必须要保证唯一,而且多数设计规范都会要求,主键不要带有业务属性,所以如果数据库没有内置这个特性,应用开发人员就必须自己设计一套主键的生成逻辑。数据库原生提供的自增主键免去了这些工作量,而且似乎还能满足开发人员的更多的期待。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

在分布式数据库中,自增主键存在一些问题,如无法保证连续递增、可能成为性能瓶颈以及难以实现单调递增等。因此,随机主键方案如UUID和Snowflake被提出作为替代方案。TiDB提供了AutoRandom关键字用于生成随机ID填充指定列,而Snowflake算法则是Twitter公司采用的ID生成算法,支持高并发和分布式环境。文章还提到了分布式数据库中使用随机主键是否一定能避免出现“热点”问题的思考题。总的来说,文章介绍了自增主键存在的问题以及随机主键方案的应用,为读者提供了对分布式架构下如何设计主键的思考和解决方案。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《分布式数据库 30 讲》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(16)

  • 最新
  • 精选
  • 麋鹿在泛舟
    看起来使用自增主键帶来的好外很有限,坏处却很明显,是一种偷懒的行为了。

    作者回复: 还是看性能要求,普通场景,自增主键还是很便捷的;高并发场景还是要谨慎使用。

    2021-09-11
    1
  • 三石
    课程的最后,我们来看看今天的思考题。我们说如果分布式数据库使用 Range 分片的情况下,单调递增的主键会造成写入压力集中在单个节点上,出现“尾部热点”问题------分布式数据库为啥还用递增主键当分片的路由字段?数据库系统设计没这么考虑的吧,根据主业务来权衡用哪些业务字段做分片路由吧

    作者回复: 建议先看下第六讲分片机制

    2020-10-20
  • 三石
    怎么确保每个主键都被使用呢?那就要等待使用主键的事务都提交成功。这意味着,必须前一个事务提交后,计数器才能为后一个事务提供新的主键,这个计数器就变成了一个表级锁。-----mysql的自增主键本身就带锁而且是表锁吧?

    作者回复: 必须不能是表锁呀,捂脸

    2020-10-20
    3
  • Jxin
    课后题 1.第一次听说尾部热点,长见识。 2.不好说一定能避免出现“热点”。首先,随机主键替换自增主键,确实能分散写入热点。但如果这个写入"热点"超过db分配集群的容量,那么再怎么分散也没有意义。其次,既然是随机,那么脸也很重要,非酋手全落到一个rang分片内,那么热点还是会出现。 个人疑问: 对于db的单机性能瓶颈,到底是自增主键先到还是db连接数(并行任务数)先到呢?从栏主的描述,感觉是自增主键会先到。(从自增主键的产生环节的描述来看)
    2020-09-16
    3
  • 慎独明强
    对于uuid生成方式,在insert和delete是否会考虑到数据页分裂对性能的影响呢?
    2021-02-07
    1
    1
  • 游弋云端
    个人认为自增主键本身在单体数据库中不是一个良好的设计,应该定义自己的主键或者流水号规则。分布式系统中,需要一个流水号分配中心,类似于Oracle的解决方案,分配一个号段先持久化,然后对外发放,异常后+X来避免重复分配,保障流水号唯一。
    2020-09-16
    1
  • nobug
    雪花算法生成的id也是单调有序的吧,单调有序的话,还可以避免尾部热点吗?
    2022-05-20
    2
  • 尔冬橙
    不使用自增主键插入更新数据索引的问题怎么解决
    2022-05-10
  • leslie
    自增主键其实老师少提了一个问题:可能在事务并发时造成死锁-这是UUID的一个坑,这是最近在RMDB圈子里出现的一个意外,之前都以为是Index的问题,可是通过查看日志发现死锁的源头就是UUID的计算错误,甚至为此特意提交了云厂商Bug。 通过今天的课程其实就发现就是由于事务的高并发,引发了UUID的计算错误,导致了数据库的死锁且直接计算出现一堆超级延时和潜在问题。 看RMDB不能只看表层和日志,透过现象看本质,源码中肯定有坑,只是触发条件特殊才导致了我们以为天下无贼而已。
    2021-07-03
  • Dr. Wong
    单体数据库自增主键的优势在于数据类型为4-8个字节的整形,加上主键列排列方式的特点,可以让数据存的更为紧凑,从而提升检索速度和减少表及索引的大小。不绑定业务,不是海量并发,用着也没问题。
    2021-04-04
收起评论
显示
设置
留言
16
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部