首页 > MySQL 水平拆分之后,自动增长的ID有什么好的解决办法?

MySQL 水平拆分之后,自动增长的ID有什么好的解决办法?

当单表的数据量过大时,会采用MySQL进行水平拆分,请问原先的自动增长的ID有什么好的解决办法?


水平拆分后,同一张表的数据放在不同的库上,无法再依赖数据库本身的auto_increment实现ID的唯一性,多个库之间产生的ID会造成冲突。
因此ID不应该由数据库来分配,那么应该由什么来分配,我觉得要分两种情况:

但无论是应用还是中间件,应用肯定会是多个的(多个客户端),而中间件,中间件一般也不会部署一个单实例,这样会有单点问题(single point of failure), 中间件在生产环境下,是集群部署的。

那么问题就清晰明了得多了,无论是上面哪一种情况,实际上你需要的是一个全局的,global的ID生成器

全局的global生成器有很多种方式可以实现

基本的策略就是这样了。还有一点小细节。

全局ID最好以来划分,一个表对应一个全局ID上下文,不同的表去不同的全局ID上下文取。

另外一个,无论是中间件也好,应用也好,取全局ID时不要每次只取一个,那样性能太低了,更好的方式是每次取一段ID,比如应用1取到了1-50这段ID,那么它就可以在这50个ID用完之前,不再需要去取ID;应用2也去取ID,那么它会取到51-100这段ID,这个思想有点像储存食物过冬一样。


目前我这已知的方法:
1.修改原有的自增列,变为不自增主键。自己维护主键

2.水平拆分为拆分已有数据,也就是说拆分出去的表的数据不会再做变化。新增的数据依然自增。(注意不能设置自增填充空白id)

3.做个统一算法。自增id需要计算后写入,而不是自动维护


我这边之前也有这样的需求。
我是这么处理的:把主键列去掉自增长,通过redis的incr产生自增序列值,插入的时候指定id的值


分表后主键要自己生成最好,很多开源的主键生成策略算法,比如说twitter的snowflake等
如果不想改动程序的话,设置每个集群中自增 ID 起始点(auto_increment_offset)以及 ID 自增步长(auto_increment_increment),让目前每个集群的起始点错开,达到将 ID 相对分段的效果来满足全局唯一的效果。优点是实现简单,对应用透明,缺点就是,以后如果根据id做路由的话不好扩展


1.把自增ID这个功能,用一张表与一个存储过程做成一个小模块。

2.被拆分的表,当有数据INSERT时,就调用这个存储过程来申请一个新ID。

【热门文章】
【热门文章】