• 主页
  • 架构
  • 编程语言
  • 数据存储
  • 网络
  • VMware
  • 服务器
  • 组网
  • AI
  • 算法系列
  • 设计模式
  • 读书笔记
  • 思考
  • 工具
  • 其它技术

  • 主页
  • 架构
  • 编程语言
  • 数据存储
  • 网络
  • VMware
  • 服务器
  • 组网
  • AI
  • 算法系列
  • 设计模式
  • 读书笔记
  • 思考
  • 工具
  • 其它技术

如何更换MySQL表的自增主键

2025-11-16

一、问题

怎么将MySQL表的自增主键更改为分布式ID?解决这个问题的核心在于上线时间段,会有两种id的生成方式。

为什么需要替换?数据同步的时候。假设A机房要迁移到B机房,两个机房都有流量。这里我们只讨论B机房是新机房,存量数据不会有冲突,只有增量数据才有冲突的情况。

image-20251116195647917

二、技术点

MySQL主键值的设置有不同的方案。

2.1MySQL自增主键

MySQL自增主键的核心逻辑是通过内存计数器分配唯一递增ID,但不同版本在计数器持久化和锁策略上存在关键差异,直接影响ID连续性和并发性能。

基础生成逻辑(各版本通用)

自增主键依赖表级内存计数器,分配规则如下:

  1. 自动分配:插入时未指定ID/指定为0/null,则用当前计数器值,分配后计数器+1(步长默认1,可通过auto_increment_increment调整)。
  2. 手动指定:若指定ID>当前计数器,计数器更新为ID+1;若ID≤计数器且未冲突,计数器不变。
  3. 不连续场景:事务回滚、唯一键冲突、批量插入失败会导致ID“浪费”(分配后未使用,不会回滚)。

版本差异核心对比

不同版本的关键区别集中在计数器持久化和锁模式,直接影响重启后ID连续性和并发插入性能:

特性 MySQL 5.7及更早 MySQL 8.0及以后
计数器存储 仅内存,重启后重置为max(id)+1 持久化到redo log,重启后恢复原值
默认锁模式 innodb_autoinc_lock_mode=1(连续模式) innodb_autoinc_lock_mode=2(交错模式)
批量插入锁策略 表级锁(语句结束释放) 轻量互斥锁(分配ID后立即释放)
ID连续性 批量插入保证连续,简单插入可能不连续 所有插入可能不连续,但并发性能最优

关键机制:锁模式

锁模式决定并发插入时ID的分配效率和连续性,各模式适用于不同场景:

锁模式值 名称 适用场景 并发性能 ID连续性
0 传统模式 基于语句的复制(SBR) 差 严格连续
1 连续模式 混合复制(默认,平衡性能) 中 批量连续
2 交错模式 基于行的复制(RBR/GTID) 优 不保证

2.2分布式ID生成方案

雪花算法

在分布式系统中,生成全局唯一且有序的ID是关键挑战。雪花算法(Snowflake)作为Twitter开源的经典方案,通过巧妙的位结构设计,平衡了唯一性、有序性和性能需求,成为分布式ID生成的事实标准。

核心原理:64位ID的精妙结构

雪花算法将64位长整型ID划分为4个部分,每部分承担特定职责:

位数 名称 作用
1位 符号位 固定为0(确保ID为正数)
41位 时间戳 记录当前时间-起始时间的毫秒差,支持约69年(2^41/1000/365/24/60/60)
10位 机器ID 含5位数据中心ID+5位节点ID,支持最多1024台机器(2^10)
12位 序列号 同一毫秒内自增,支持每节点每毫秒生成4096个ID(2^12)

生成流程:

  1. 时间戳:以自定义起始时间(如2020-01-01)为基准,计算当前时间偏移量;
  2. 时钟回拨处理:若当前时间 < 上次生成时间,抛出异常或等待时钟同步;
  3. 序列号生成:同一毫秒内序列号自增,溢出则等待下一毫秒;
  4. 组合ID:通过位运算拼接时间戳、机器ID和序列号,生成64位整数。
核心优势:为何成为分布式首选?

1.全局唯一性:时间戳+机器ID+序列号的三重组合,确保分布式环境下ID无重复,即使多节点并发也不会冲突。

2.高性能与低延迟:纯内存计算,无需数据库或中心节点,单机每秒可生成 400万+ ID(1000ms × 4096序列号),适合高并发场景(如秒杀、订单系统)。

3.趋势有序性:时间戳位于高位,ID天然按生成时间递增,适合作为数据库主键(减少索引碎片)或排序字段。

4.无中心依赖:去中心化设计,避免单点故障风险,支持集群横向扩展。

NT ID

公司自研的Non-Timestamp ID,非基于时间戳生成的全球唯一 ID。算是号段模式的一种,从数据库批量预分配ID段(如 [1001, 2000]),缓存在内存中逐个分配,用完后再申请新号段[4001,5000]。

三、方案

对于上面的具体场景,有两种方案可以选择:

方案1:仍然使用自增主键,不同机房使用不同的数据范围 方案2:使用NT ID
图示 image-20251116224916055 image-20251116232100497Q:为什么需要这么多操作?
A:代码发布过程中,如果NTID生成的值有落库,自增主键会在此数值之上增加,可能和NTID生成的只有冲突
优点 1. 开发量:无需任何改造解决主键冲突问题,可在创建表或者通过ALTER TABLE 表名 AUTO_INCREMENT = 1000;修改自增主键值 1. 完美的支持双向同步
缺点 1. 同步方式:该方案只支持单向同步
2. 风险:需要确保A中的表自增主键不会迅速增长到B的值、确保A表中不会设置较大主键
3.全面性:除非A机房后续废弃不用,否则增量同步的数据终会出问题
1. 开发量:需要对表的创建操作设置主键值
2. 主键类型是不是bigint,防止越界
3. 通过接口提供的主键值,过长是否会有问题。如js对int64会丢失精度

扫一扫,分享到微信

微信分享二维码
论语第十篇-乡党
Redis过期策略与内存淘汰策略
© 2025 John Doe
Hexo Theme Yilia by Litten