0

0

INSERT ... ON DUPLICATE KEY UPDATE 在 MySQL 中的锁粒度分析

冷炫風刃

冷炫風刃

发布时间:2026-01-28 17:27:10

|

705人浏览过

|

来源于php中文网

原创

ON DUPLICATE KEY UPDATE 仅锁定可能触发冲突的唯一键对应行:存在则加X行锁,不存在则加X临键锁;不锁全表,也不锁所有涉及行。

insert ... on duplicate key update 在 mysql 中的锁粒度分析

ON DUPLICATE KEY UPDATE 会锁哪些行

它只锁定「可能触发冲突检查」的唯一键对应行,不是全表锁,也不是语句涉及的所有行都锁。核心逻辑是:MySQL 先按 INSERT 的值去查找唯一索引(PRIMARY 或 UNIQUE),找到则加 record lock(行锁),没找到则加 next-key lock(间隙锁 + 行锁)防止幻读插入。哪怕最终走的是 UPDATE 分支,锁也是在 INSERT 查找阶段就加上的。

常见错误现象:Deadlock found when trying to get lock,往往是因为两个事务并发插入相同唯一键值,各自先持有了对同一行的 X 锁,又试图获取对方已持有的锁。

  • 如果插入值在唯一索引中已存在 → 加 X record lock 到该行(等同于 SELECT ... FOR UPDATE 该行)
  • 如果插入值在唯一索引中不存在 → 加 X next-key lock 到「该值应插入的位置」(即覆盖间隙 + 虚拟记录)
  • 若唯一索引是联合索引,锁范围由匹配的最左前缀决定;未用到的后缀列不影响锁定位

INSERT IGNORE 和 REPLACE INTO 的锁行为差异

INSERT IGNOREON DUPLICATE KEY UPDATE 在锁类型和范围上基本一致——都是先查再锁,冲突时跳过而非报错。但 REPLACE INTO 是「删 + 插」语义:先 DELETE 匹配行(加 X record lock),再 INSERT 新行(加 X next-key lock)。这意味着它会多一次 delete 操作的锁开销,且可能触发外键级联、触发器、自增 ID 跳变等问题。

使用场景建议:仅当明确需要替换整行(包括非唯一字段)且能接受 delete 语义时才用 REPLACE INTO;日常 upsert 场景优先选 ON DUPLICATE KEY UPDATE

  • INSERT IGNORE:冲突时静默忽略,不更新,锁行为与 ON DUPLICATE KEY UPDATE 相同
  • REPLACE INTO:冲突时先 delete 原行(触发 delete 锁 + binlog event),再 insert 新行
  • 三者都不支持对多个唯一键冲突做不同处理(比如 A 键冲突 update,B 键冲突 ignore)

唯一索引缺失或失效导致的锁扩大

如果表中没有定义任何 PRIMARY KEY 或 UNIQUE 索引,ON DUPLICATE KEY UPDATE 会直接报错 ERROR 1062 (23000): Duplicate entry '...' for key 'PRIMARY' —— 因为它根本找不到可判断冲突的索引。但更隐蔽的问题是:当唯一索引存在但查询条件未命中索引(比如 WHERE 子句用了函数、类型隐式转换、或前导通配符 like),MySQL 可能无法准确定位冲突行,被迫升级为更宽泛的锁策略,甚至退化为表级意向锁等待。

PNG Maker
PNG Maker

利用 PNG Maker AI 将文本转换为 PNG 图像。

下载

性能影响明显:本该只锁 1 行的操作,因索引失效而扫描并锁住整个索引范围,极大增加死锁概率和并发阻塞。

  • 务必确保 INSERT 中用于冲突判断的列(如 user_id)上有有效 UNIQUE / PRIMARY 索引
  • 避免在 ON DUPLICATE KEY UPDATE 的 INSERT VALUES 中对唯一列做函数操作(如 UPPER(email)
  • EXPLAIN FORMAT=TRADITIONAL 检查 INSERT 语句是否走了唯一索引

批量 INSERT ... ON DUPLICATE KEY UPDATE 的锁粒度

批量写入时,MySQL 会对每一行独立执行「查找 → 加锁 → 冲突判断 → 更新/插入」流程,不是一次性锁住所有目标行。这意味着:即使你一次插入 1000 行,只要其中某几行的唯一键值相同或落在同一间隙内,它们仍可能相互阻塞或引发死锁。

容易被忽略的一点:批量语句中各行之间的锁顺序取决于 MySQL 内部的索引遍历顺序(通常是 B+ 树升序),而非 SQL 中 VALUES 的书写顺序。因此,并发执行两个结构相同的批量 upsert,若涉及重叠的唯一键值,死锁风险比单条语句更高。

  • 批量操作不会合并锁,每行独立加锁;总锁持有时间 ≈ 单行 × 行数(串行化倾向)
  • 若批量中含重复唯一键(如两条都插 id=123),第二条会等待第一条释放锁,而非立即失败
  • 高并发下建议控制批量大小(如 100 行以内),并确保应用层对唯一键值预先去重

真正难处理的不是锁本身,而是锁的「不可见性」:它不显式出现在语句里,却在唯一索引查找那一刻就已落下。线上遇到慢查询或死锁,别只盯着 UPDATE 部分,先看 INSERT 的值有没有撞上热点唯一键、索引是否真的被用了、批量 size 是否无意中放大了锁竞争。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

727

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

327

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

350

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1242

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

360

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

820

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

581

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

423

2024.04.29

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.9万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 812人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号