MySQL执行Update字段值未变,存储引擎去重更新流是否记录日志?
- 内容介绍
- 文章标签
- 相关推荐
本文共计804个文字,预计阅读时间需要4分钟。
不会写binlog(默认配置下)。在执行UPDATE时,MySQL会先读取原始值,再比较新旧值;如果所有被更新的字段值与原值完全一致(类型、NULL属性、字节级内容均相同),则Server层会跳过实际更新操作,自然也不会触发binlog写入。但这个行为会受到存储引擎和SQL模式的影响,不能一概而论。
InnoDB 对“无变化更新”的处理:不修改页、不刷脏、不记 undo log
InnoDB 在执行 UPDATE 前会调用 row_upd_changes_to_persistent() 判断是否真有变更。关键点如下:
- 比较基于字段的内部存储格式(例如
TIMESTAMP会转为秒级整数再比,VARCHAR区分尾部空格与否取决于collation) - 即使 SQL 写了
SET name = name,只要该列值未变,InnoDB 不会标记记录为“已修改”,对应的数据页不会变脏,innodb_buffer_pool_pages_dirty不增 - 不生成新的 undo log 版本,MVCC 快照不受影响
- 但会加 X 锁(或意向锁)并立即释放——锁开销仍在,只是没持久化动作
binlog 写入时机由 server 层控制,但受 storage engine 返回结果驱动
MySQL Server 层在调用 handler::update_row() 后,检查返回值:HA_ERR_RECORD_IS_THE_SAME 表示引擎明确告知“没变”,此时 Query_log_event 不生成。
本文共计804个文字,预计阅读时间需要4分钟。
不会写binlog(默认配置下)。在执行UPDATE时,MySQL会先读取原始值,再比较新旧值;如果所有被更新的字段值与原值完全一致(类型、NULL属性、字节级内容均相同),则Server层会跳过实际更新操作,自然也不会触发binlog写入。但这个行为会受到存储引擎和SQL模式的影响,不能一概而论。
InnoDB 对“无变化更新”的处理:不修改页、不刷脏、不记 undo log
InnoDB 在执行 UPDATE 前会调用 row_upd_changes_to_persistent() 判断是否真有变更。关键点如下:
- 比较基于字段的内部存储格式(例如
TIMESTAMP会转为秒级整数再比,VARCHAR区分尾部空格与否取决于collation) - 即使 SQL 写了
SET name = name,只要该列值未变,InnoDB 不会标记记录为“已修改”,对应的数据页不会变脏,innodb_buffer_pool_pages_dirty不增 - 不生成新的 undo log 版本,MVCC 快照不受影响
- 但会加 X 锁(或意向锁)并立即释放——锁开销仍在,只是没持久化动作
binlog 写入时机由 server 层控制,但受 storage engine 返回结果驱动
MySQL Server 层在调用 handler::update_row() 后,检查返回值:HA_ERR_RECORD_IS_THE_SAME 表示引擎明确告知“没变”,此时 Query_log_event 不生成。

