news 2026/6/15 17:16:49

UPDATE users SET name=‘John‘ WHERE id=100000000000000的庖丁解牛

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UPDATE users SET name=‘John‘ WHERE id=100000000000000的庖丁解牛

UPDATE users SET name='John' WHERE id=100000000000000看似简单,但其执行过程涉及索引查找、行锁、Redo/Undo 生成、Buffer Pool 修改等多层机制。


一、整体执行链路

Yes

No

SQL

Parser

Optimizer

Executor

InnoDB: 主键查找

找到记录?

加行锁

生成 Undo Log

修改 Buffer Pool

生成 Redo Log

COMMIT 刷 Redo

直接返回

核心原则
即使 UPDATE 未命中任何行,仍会走完整执行流程(含锁和日志)


二、分阶段深度拆解

阶段 1:SQL 解析与优化
  • Parser
    生成 AST,识别UPDATE、表名、SET 子句、WHERE 条件
  • Resolver
    • 验证users表存在
    • 检查nameid列是否存在
    • 验证用户有UPDATE权限
  • Optimizer
    • 分析WHERE id=...选择主键索引(聚簇索引)
    • 估算行数:1 行(主键唯一)

⚠️关键点
主键查询是 InnoDB 最高效的路径(O(log n) B+ 树搜索)


阶段 2:存储引擎执行(InnoDB)
步骤 1:主键查找
  • 定位数据页
    • 从根节点开始遍历聚簇索引 B+ 树
    • 目标页 = 包含id=100000000000000的 16KB 页
  • 加载到 Buffer Pool
    • 若页已在内存 → 直接使用
    • 若不在 → 触发同步 I/O从磁盘读取
步骤 2:检查记录是否存在
  • 在页内二分查找id=100000000000000
  • 结果
    • 存在→ 继续更新
    • 不存在→ 返回Affected rows: 0

💡为什么仍需锁
即使记录不存在,InnoDB 可能加间隙锁(Gap Lock)防止幻读(取决于隔离级别)。


阶段 3:事务与锁机制
场景 A:记录存在
  • 加行锁(Record Lock)
    • 锁类型:X 锁(排他锁)
    • 锁对象:主键id=100000000000000对应的记录
  • 隔离级别影响
    • READ COMMITTED:仅锁记录
    • REPEATABLE READ:锁记录 + 间隙(防幻读)
场景 B:记录不存在
  • 加间隙锁(Gap Lock)(仅 REPEATABLE READ):
    • 锁范围:(前一个id, 后一个id)
      (例如(99999999999999, 100000000000001)
    • 目的:阻止其他事务插入id=100000000000000

⚠️死锁风险
高并发下,间隙锁可能引发死锁(需应用层重试)。


阶段 4:生成 Undo Log(用于回滚和 MVCC)
  • Undo 记录内容
    • 旧值:name='OldName'
    • 事务 ID、回滚指针
  • 存储位置
    • Undo 页(独立于数据页)
    • 通过回滚段(Rollback Segment)管理
  • 作用
    • 回滚ROLLBACK时恢复旧值
    • MVCC:其他事务可读取旧版本

💡即使 name 未变
InnoDB 仍会生成 Undo(因无法预知值是否相同)。


阶段 5:修改 Buffer Pool
  • 操作
    • 在内存中定位目标记录
    • name字段从旧值改为'John'
    • 更新记录的事务 ID回滚指针
  • 标记脏页
    • 所在 16KB 页标记为Dirty Page
    • 后台线程异步刷盘(Checkpoint)

阶段 6:生成 Redo Log(WAL 机制)
  • Redo 记录内容
    // 聚簇索引变更MLOG_REC_UPDATE_IN_PLACE:page_id=12345,offset=200,data="John"// Undo Log 变更MLOG_WRITE_STRING:undo_page=67890,offset=100,data="OldName"
  • 写入 Redo Log Buffer(内存)
  • COMMIT 时刷盘
    • fsync()确保 Redo 落盘
    • 此时事务已持久化(即使数据页未刷盘)

⚠️Double Write Buffer
脏页刷盘时,先写双写区 → 防页断裂。


三、性能关键点

环节潜在瓶颈优化方向
主键查找Buffer Pool 未命中 → 磁盘 I/O增大innodb_buffer_pool_size
行锁竞争高并发更新同一行应用层队列化
Redo 刷盘fsync延迟高使用 NVMe SSD
Undo 积累长事务阻塞 Purge避免大事务

四、特殊场景分析

场景 1:id 不存在
  • 仍会
    • 遍历 B+ 树到叶子页
    • 加间隙锁(REPEATABLE READ)
    • 生成空 Redo(仅事务提交记录)
  • 性能影响
    比命中记录略快(无数据修改),但仍有 I/O 和锁开销。
场景 2:name 值未变
UPDATEusersSETname='John'WHEREid=100ANDname='John';
  • InnoDB 仍会
    • 加锁
    • 生成 Undo/Redo
  • 优化建议
    应用层先SELECT判断,避免无效 UPDATE。

五、监控与诊断

1.查看锁信息
-- 当前锁等待SELECT*FROMinformation_schema.INNODB_LOCKS;-- 事务状态SELECT*FROMinformation_schema.INNODB_TRX;
2.分析执行计划
EXPLAINUPDATEusersSETname='John'WHEREid=100000000000000;-- 输出: type=const, key=PRIMARY
3.Redo 生成量
SHOWGLOBALSTATUSLIKE'Innodb_os_log_written';-- 对比 UPDATE 前后增量

六、工程最佳实践

  1. 确保主键高效

    • 使用自增 ID 或 UUID 有序化
    • 避免超大主键(如 100 字节 VARCHAR)
  2. 减少无效更新

    // 应用层判断if($oldName!=='John'){$db->update('users',['name'=>'John'],['id'=>$id]);}
  3. 批量更新替代单条

    UPDATEusersSETname=CASEidWHEN1THEN'A'WHEN2THEN'B'ENDWHEREidIN(1,2);
  4. 监控长事务

    -- 查找运行超过 60 秒的事务SELECT*FROMinformation_schema.INNODB_TRXWHERETIME_TO_SEC(TIMEDIFF(NOW(),trx_started))>60;

七、总结:UPDATE 的本质

  • 不是“直接改数据”,而是“加锁 → 记录旧值 → 改内存 → 写日志”
  • 持久化 = Redo 落盘,与数据页刷盘无关。
  • 性能 = 减少 I/O + 减少锁竞争 + 减少日志量
  • 终极心法
    “每一次 UPDATE,都是对 ACID 的庄严承诺——
    要么全部成功,要么全部回滚,绝不半途而废。”

💡一句话
主键 UPDATE 是 InnoDB 的拿手好戏,
但再快的操作,也快不过“不操作”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 12:37:52

FreeKill终极指南:开启你的桌游创作革命

FreeKill终极指南:开启你的桌游创作革命 【免费下载链接】FreeKill Sanguosha (a.k.a. Legend of Three Kingdoms, LTK) written in Qt and Lua. 项目地址: https://gitcode.com/gh_mirrors/fr/FreeKill 你是否曾经梦想过亲手设计属于自己的桌游?…

作者头像 李华
网站建设 2026/6/13 17:41:39

深入解析Linux PCIe热插拔:从内核实现到生产实践

深入解析Linux PCIe热插拔:从内核实现到生产实践 【免费下载链接】linux Linux kernel source tree 项目地址: https://gitcode.com/GitHub_Trending/li/linux 在企业级服务器和云计算环境中,PCIe设备的热插拔能力已成为现代数据中心的核心需求。…

作者头像 李华
网站建设 2026/6/15 15:19:59

5分钟搭建跨平台直播聚合中心:开源神器完整使用指南

5分钟搭建跨平台直播聚合中心:开源神器完整使用指南 【免费下载链接】pure_live 纯粹直播:哔哩哔哩/虎牙/斗鱼/快手/抖音/网易cc/M38自定义源应有尽有。 项目地址: https://gitcode.com/gh_mirrors/pur/pure_live 想要在一个应用中观看全网热门直播&#xff…

作者头像 李华
网站建设 2026/6/12 22:14:44

AI如何赋能TRADINGAGENTS开发?5个实战技巧

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个基于AI的TRADINGAGENT原型系统,要求包含以下功能:1. 实时市场数据分析模块,使用机器学习识别趋势;2. 自动化交易策略生成器…

作者头像 李华
网站建设 2026/6/15 13:14:18

StructBERT零样本分类实战:金融报告自动归类

StructBERT零样本分类实战:金融报告自动归类 1. 引言:AI 万能分类器的崛起 在金融行业,每天都会产生海量的非结构化文本数据——年报、季报、投资分析、监管文件、市场评论等。传统上,这些文档的归类依赖人工阅读和标注&#xf…

作者头像 李华
网站建设 2026/6/15 15:17:52

零样本分类技术应用:智能问答系统分类模块搭建

零样本分类技术应用:智能问答系统分类模块搭建 1. 引言:AI 万能分类器的崛起 在智能客服、工单处理、舆情监控等场景中,文本分类是构建自动化系统的基石。传统方法依赖大量标注数据进行监督训练,成本高、周期长,难以…

作者头像 李华