SQL自增ID本质是单机单表的顺序计数器,依赖数据库锁或缓存保证递增不重复;在分布式多实例、分库分表、主从多写等场景下会因各自独立生成而导致ID冲突或不唯一。

SQL数据库的自增ID(如 MySQL 的 AUTO_INCREMENT、PostgreSQL 的 SERIAL)本质是单机、单表维度的顺序计数器,依赖数据库内部锁或缓存机制保证递增不重复。但在分布式系统中,多个数据库实例或分库分表场景下,这种本地自增机制会直接失效,导致ID冲突或全局不唯一。
自增ID在单库下的工作原理
以 MySQL 为例:每张含 AUTO_INCREMENT 主键的表维护一个内存中的“当前最大值”,插入新行时加1并写入;重启后会通过扫描表中最大ID重新初始化该值(InnoDB 在 8.0+ 改为持久化到重做日志,避免重启回退)。整个过程由引擎层加表级或意向锁控制,并发插入仍能保证连续、递增、不重复——但仅限于**同一张表、同一个实例**。
分布式环境下自增ID为何失效
-
多实例独立生成:不同MySQL实例各自维护自己的
AUTO_INCREMENT值,比如实例A生成1,2,3,实例B也生成1,2,3,ID全局重复 - 分库分表后主键非全局唯一:订单库按用户ID哈希拆成4个库,每个库的order表都从1开始自增,不同库产生的order_id=1001会撞车
- 主从延迟或双写场景下无法协调:主库和从库同时接受写入(如多活架构),自增步长配置不当会导致主从ID交叉覆盖
- 迁移/合并数据时ID重叠:将多个旧库合并到新库,各源库的自增ID天然存在大量重合
替代方案:如何生成全局唯一分布式ID
核心思路是脱离数据库自增,改用应用层或中间件统一发放,常见方案有:
采用 php+mysql 数据库方式运行的强大网上商店系统,执行效率高速度快,支持多语言,模板和代码分离,轻松创建属于自己的个性化用户界面 v3.5更新: 1).进一步静态化了活动商品. 2).提供了一些重要UFT-8转换文件 3).修复了除了网银在线支付其它支付显示错误的问题. 4).修改了LOGO广告管理,增加LOGO链接后主页LOGO路径错误的问题 5).修改了公告无法发布的问题,可能是打压
- UUID / UUIDv4:本地生成,无中心依赖,但长度长(32位十六进制)、无序、索引效率低,不适合高频写入主键
- Twitter Snowflake(及变种如百度UidGenerator、美团Leaf):64位整数,含时间戳+机器ID+序列号,趋势递增、全局唯一、高性能;需自行部署ID服务或集成SDK
- 数据库号段模式:ID服务批量向DB申请一段可用ID(如1–1000),缓存在内存中分发,用完再取;减少DB交互,兼顾性能与可靠性
-
Redis INCR 原子计数器:利用 Redis 单线程原子性,
INCR生成递增ID;需注意Redis高可用和网络分区影响,适合中小规模系统
实际选型建议
不必强求“完美方案”,应结合业务特点权衡:









