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

来源:这里教程网 时间:2026-02-28 20:41:05 作者:

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 UPDATE
LOCK IN SHARE MODE
)只读取快照版本,不加锁、不写任何 log

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

没索引的 UPDATE 是灾难性的。它会导致全表扫描 + 全表加锁(在 RR 隔离级别下是

gap lock
next-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 即使没索引,最多慢一点,不会锁表或拖垮并发。

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

比如

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

真正要复用查询逻辑做更新时,优先考虑

UPDATE ... JOIN
或子查询形式,让优化器在服务端完成关联判断,而不是靠应用层协调。

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

相关推荐