当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL 8.4 自增主键并发写入实战:AUTO_INCREMENT 锁模式别再凭感觉调

MySQL 8.4 自增主键并发写入实战:AUTO_INCREMENT 锁模式别再凭感觉调

来源:17golang 原创 2026-06-05 10:34:25 0浏览 收藏

有一次订单库凌晨扩容,业务侧把写入线程数从 80 提到 240,CPU 没先满,磁盘也没先满,最早冒出来的是一串看起来很委屈的 INSERT 慢日志。表结构很普通:id BIGINT AUTO_INCREMENT PRIMARY KEY,大家第一反应是“自增主键不是最快的吗”。这句话只说对了一半:自增主键确实让聚簇索引写入更顺,但 AUTO_INCREMENT 值怎么分配、批量插入怎么拿号、复制格式能不能接受交错编号,都会影响高并发写入。

这篇只讲 MySQL 8.4 / InnoDB 场景。它不是劝你盲目把 innodb_autoinc_lock_mode 改成 2,而是给一套能在生产落地的判断路径:先看业务写入形态,再看复制格式,最后压测和灰度。

MySQL 自增主键并发治理脑图
先把模式、业务现象、诊断入口和上线策略拆开看。

一、事故复现:单行写不慢,批量写一来全库抖

假设有一张交易流水表,平时在线请求都是单行写,夜间又有补偿任务批量导入历史订单:

CREATE TABLE trade_bill (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  tenant_id BIGINT NOT NULL,
  order_no VARCHAR(64) NOT NULL,
  amount DECIMAL(12,2) NOT NULL,
  created_at DATETIME NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY uk_tenant_order (tenant_id, order_no),
  KEY idx_created_at (created_at)
) ENGINE=InnoDB;

-- 在线请求
INSERT INTO trade_bill(tenant_id, order_no, amount, created_at)
VALUES (1001, 'O202606050001', 89.90, NOW());

-- 夜间补偿
INSERT INTO trade_bill(tenant_id, order_no, amount, created_at)
SELECT tenant_id, order_no, amount, created_at
FROM trade_bill_stage
WHERE batch_id = 20260605;

白天单行 INSERT 很稳,补偿任务一上来就开始抖。这里不要急着怪索引,也不要只盯 redo 或 buffer pool。先把自增锁模式、语句类型和复制格式摆在一起看。

二、先把三个锁模式说成人话

InnoDB 的 innodb_autoinc_lock_mode 用来控制 AUTO_INCREMENT 值分配时的锁策略。不同版本和配置默认值可能不一样,线上必须以实际变量为准:

SHOW VARIABLES LIKE 'innodb_autoinc_lock_mode';
SHOW VARIABLES LIKE 'binlog_format';

我在排障时通常这样理解:

  • 0 traditional:传统表级自增锁,兼容性强,但高并发写入吞吐最吃亏。
  • 1 consecutive:尽量保证批量语句拿到连续自增值,很多老系统会见到这个模式。
  • 2 interleaved:交错分配自增值,并发性能更好,但如果你还依赖 statement-based replication 或业务假设连续编号,就要非常谨慎。
AUTO_INCREMENT 锁模式排查流程
不要只看变量值,要把语句类型、复制格式和业务假设一起纳入决策。

三、踩坑根因:业务把 id 当业务序号,DBA 把模式当性能开关

我见过两类事故最常见。第一类是业务把自增 id 当“连续流水号”,后来改成更高并发的模式后发现编号有空洞或交错,就认为数据库错了。其实自增主键只适合作为技术主键,不应该承诺连续、无缺口、可审计含义。流水号要单独设计。

第二类是 DBA 看到 INSERT 等待,直接把模式改成 2,却没检查复制格式、导入 SQL、下游订阅和回放工具。结果线上写入确实快了,但某个依赖 statement 回放的链路开始不一致。这种锅很难背,因为它不是参数本身错,而是上线前没有把链路盘全。

四、诊断步骤:先证明等待在哪里

我会按下面顺序查,尽量少猜:

SHOW VARIABLES LIKE 'innodb_autoinc_lock_mode';
SHOW VARIABLES LIKE 'binlog_format';
SHOW GLOBAL STATUS LIKE 'Innodb_row_lock%';
SHOW ENGINE INNODB STATUS\G

如果你启用了 Performance Schema,可以继续看等待统计。不同小版本事件名会有差异,不要死背一条 SQL,要把它当入口:

SELECT event_name, count_star, sum_timer_wait
FROM performance_schema.events_waits_summary_global_by_event_name
WHERE event_name LIKE 'wait/synch/%/innodb/%'
ORDER BY sum_timer_wait DESC
LIMIT 20;
AUTO_INCREMENT 排查 SQL 和上线检查单
排障时保留 SQL 快照,方便复盘参数变化前后的差异。

五、SQL 改写:批量导入不要和在线写入硬挤一条路

如果你的问题主要来自 INSERT ... SELECTLOAD DATA,先不要急着改全局模式。更稳的做法是把批量任务限速、拆批,并避开在线高峰。

-- 每批只导入固定窗口,应用侧循环推进 last_id
INSERT INTO trade_bill(tenant_id, order_no, amount, created_at)
SELECT tenant_id, order_no, amount, created_at
FROM trade_bill_stage
WHERE batch_id = 20260605
  AND stage_id > ?
ORDER BY stage_id
LIMIT 5000;

如果业务允许,也可以让导入任务写入独立表,再用低峰合并;或者直接让业务生成雪花 ID、号段 ID,把主键分配压力从 InnoDB 自增机制里移出去。但这属于架构选择,不要在事故凌晨临时改。

六、什么时候考虑调 innodb_autoinc_lock_mode

我的经验是满足下面条件,才值得认真评估模式 2:

  • 复制格式是 ROW,或者你已经确认没有 statement-based 回放链路。
  • 业务不依赖 AUTO_INCREMENT 连续、无缺口或按提交顺序严格递增。
  • 主要瓶颈确实来自并发插入和批量插入交织,不是二级索引、唯一键冲突或磁盘刷脏。
  • 有完整压测脚本,能同时跑在线单行写和批量导入。
  • 准备了回滚方案,并知道参数变更对连接和实例重启策略的影响。
-- 示例:只在评估通过后执行,先在测试环境和灰度库验证
SET PERSIST innodb_autoinc_lock_mode = 2;

有些环境这个变量是否动态生效、是否需要重启,要以你的 MySQL 版本和实际输出为准。生产上我更倾向用变更单记录:当前值、目标值、复制格式、压测结果、回滚步骤。

七、上线检查单

  • 检查主库、从库、延迟从库的 binlog_format 和回放工具。
  • 压测单行 INSERT、批量 INSERT、唯一键冲突三种场景。
  • 观察写入 P95/P99、Innodb_row_lock_time、错误率和复制延迟。
  • 确认业务没有用自增 id 做连续流水号、分页游标以外的审计含义。
  • 导入任务保留限速开关,出现复制延迟或锁等待时能降速。

八、我的结论

AUTO_INCREMENT 问题最容易被低估,因为表结构看起来太普通了。真正的风险不在“自增主键能不能用”,而在你是否知道当前锁模式适合哪类 SQL、复制链路能不能接受交错分配、业务有没有偷偷依赖连续编号。MySQL 8.4 下做高并发写入治理,最稳的路径仍然是:先观测,后压测,再灰度;参数是最后一公里,不是第一反应。

版本声明
本文转载于:17golang 原创 如有侵犯,请联系study_golang@163.com删除
Python 日志实战:别让 request_id 在异步任务里丢了Python 日志实战:别让 request_id 在异步任务里丢了
上一篇
Python 日志实战:别让 request_id 在异步任务里丢了
Go rate.Limiter 实战:别让限流器写成摆设
下一篇
Go rate.Limiter 实战:别让限流器写成摆设
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ChatExcel酷表:告别Excel难题,北大团队AI助手助您轻松处理数据
    ChatExcel酷表
    ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
    6152次使用
  • Any绘本:开源免费AI绘本创作工具深度解析
    Any绘本
    探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
    6563次使用
  • 可赞AI:AI驱动办公可视化智能工具,一键高效生成文档图表脑图
    可赞AI
    可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
    6369次使用
  • 星月写作:AI网文创作神器,助力爆款小说速成
    星月写作
    星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
    8337次使用
  • MagicLight.ai:叙事驱动AI动画视频创作平台 | 高效生成专业级故事动画
    MagicLight
    MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
    6978次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码