mysql执行更新语句和查询语句流程一样吗_mysql差异分析

MySQL的UPDATE与SELECT执行流程本质不同:UPDATE需加行锁、写undo log和redo log以保证原子性,而SELECT(默认)仅读快照、不加锁不写日志;无索引WHERE会导致全表锁,引发死锁;优化器可能将INSERT ON DUPLICATE KEY UPDATE等改写为单次引擎操作,避免应用层竞态。

mysql执行更新语句和查询语句流程一样吗_mysql差异分析

MySQL 更新语句和查询语句的执行流程本质不同

不一样。虽然都走「连接→解析→优化→执行」的大框架,但 UPDATE 和 SELECT 在优化器决策、存储引擎交互、锁机制、日志写入等关键环节存在根本性差异。不能简单认为“只是 SQL 类型不同”。

UPDATE 会触发行锁、redo log 和 undo log,SELECT(默认)不会

这是最常被忽略的性能与一致性根源。UPDATE 必须保证原子性和可回滚性,因此 InnoDB 会:

  • 对匹配的每一行加 X 锁(或 next-key 锁,取决于隔离级别和索引),阻塞其他事务的写和部分读
  • 先写 undo log,用于 rollback 或 MVCC 版本链构建
  • 再修改内存中的数据页,并写入 redo log buffer(刷盘策略由 innodb_flush_log_at_trx_commit 控制)
  • 而普通 SELECT(非 SELECT ... FOR UPDATELOCK IN SHARE MODE)只读取快照版本,不加锁、不写任何 log

UPDATE 的 WHERE 条件是否命中索引,直接影响锁范围和性能

没索引的 UPDATE 是灾难性的。它会导致全表扫描 + 全表加锁(在 RR 隔离级别下是 gap locknext-key lock),极易引发死锁和长事务阻塞。

UPDATE users SET status = 'done' WHERE create_time < '2023-01-01'; -- 如果 create_time 无索引,危险!
UPDATE users SET status = 'done' WHERE id = 123; -- id 是主键,仅锁该行,安全

对比之下,SELECT 即使没索引,最多慢一点,不会锁表或拖垮并发。

EasySub – AI字幕生成翻译工具

EasySub – AI字幕生成翻译工具

EasySub 是一款在线 AI 字幕生成器。 它提供AI语音识别、AI字幕生成、AI字幕翻译,本来就很简单的视频剪辑。

下载

UPDATE 可能被优化器改写为“先查后更”,但不是 SELECT + INSERT 的简单组合

比如 INSERT ... ON DUPLICATE KEY UPDATEREPLACE INTO,表面像“查+更”,实际由存储引擎在一次操作中完成唯一键检查与行变更,避免了用户态的两次网络往返和中间状态暴露。而手动拆成 SELECTUPDATE,不仅慢,还会因并发导致竞态(如 A 查到存在,B 同时删掉该行,A 接着 UPDATE 就失效)。

真正要复用查询逻辑做更新时,优先考虑 UPDATE ... JOIN 或子查询形式,让优化器在服务端完成关联判断,而不是靠应用层协调。

UPDATE 流程里藏着太多隐式动作:锁、日志、唯一性校验、外键检查……这些都不是 SELECT 要操心的。别因为语法结构相似,就低估 UPDATE 的重量级行为。

https://www.php.cn/faq/1996198.html

发表回复

Your email address will not be published. Required fields are marked *