MySQL中update修改数据与原数据相同会再次执行吗?

本文探讨MySQL在不同binlog格式下执行update语句的行为,特别是在数据未改变时的处理方式。通过实验证明,当binlog_format为ROW时,MySQL会避免重复执行相同的数据更新;而当binlog_format为STATEMENT时,即使数据不变,MySQL也会完整执行update流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

本文主要测试MySQL执行update语句时,针对与原数据(即未修改)相同的update语句会在MySQL内部重新执行吗?

测试环境

  • MySQL5.7.25
  • Centos 7.4

binlog_format为ROW

  1. 参数
    在这里插入图片描述
  2. 测试步骤
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  3. 总结

在binlog_format=row和binlog_row_image=FULL时,由于MySQL 需要在 binlog 里面记录所有的字段,所以在读数据的时候就会把所有数据都读出来,那么重复数据的update不会执行。即MySQL 调用了 InnoDB 引擎提供的“修改为 (1,55)”这个接口,但是引擎发现值与原来相同,不更新,直接返回。

binlog_format为STATEMENT

  1. 参数
    在这里插入图片描述
  2. 测试步骤
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  3. 总结

在binlog_format=statement和binlog_row_image=FULL时,InnoDB内部认真执行了update语句,即“把这个值修改成 (1,999)“这个操作,该加锁的加锁,该更新的更新。

<think>嗯,我现在要理解MySQL查询数据的完整行流程。首先,我应该回忆一下之前学过的MySQL相关知识。记得MySQL是基于客户端-服务器模型的,所以当用户发起一个查询请求时,客户端会发送SQL语句到服务器端处理。那服务器端处理的过程具体是怎样的呢? 首先,连接管理应该是一个步骤。客户端需要先连接到MySQL服务器,这可能涉及到建立TCP连接,验证用户名密码,还有权限检查。这部分可能由连接器(Connector)处理。连接建立后,连接器会管理这个连接,保持其活跃状态,或者在空闲一段时间后断开。 接下来,当SQL查询语句到达服务器后,分析器(Parser)应该会进行词法分析和语法分析。词法分析是把SQL语句拆分成各种关键字,比如SELECT、FROM、WHERE这些,还有表名、列名等。语法分析则是检查这些拆分后的元素是否符合SQL语法规则,如果语法错误,比如少了个逗号或者关键字顺序不对,这时候就会报错。 然后,优化器(Optimizer)会起作用。优化器的任务是对查询进行优化,选择最有效的行计划。比如,当有多个索引可用时,优化器会决定使用哪个索引,或者决定表的连接顺序,以减少查询时间。这里可能涉及到成本估算,选择成本最低的行方式。 接下来是行器(Executor)行查询的阶段。行器会根据优化器生成的行计划,调用存储引擎的接口来获取数据行器在操作之前会先检查用户是否有对相关表的行权限,如果没有权限,就会返回错误。如果有权限,就会开始行。 存储引擎(Storage Engine)负责实际的数据存储和提取。比如InnoDB会从磁盘中读取数据,处理事务,锁等。行器通过存储引擎提供的接口,逐行获取符合条件的数据,然后返回给客户端。 在返回结果的时候,如果查询缓存(Query Cache)是开启的,MySQL可能会在分析查询之前检查缓存,如果缓存中存在完全相同的查询语句及其结果,就直接返回缓存中的数据,而不需要行后续步骤。不过,由于查询缓存容易失效,尤其是在写操作频繁的情况下,MySQL 8.0之后已经移除了查询缓存功能。 另外,行过程中可能还涉及到日志模块,比如redo log、undo log和binlog,但这些可能更多是在写操作(如UPDATE、INSERT)时使用,查询的话可能影响不大,除非涉及到事务的读取一致性。 不过,可能有一些细节我还不清楚。比如,预处理阶段是否在分析器之后?行器在调用存储引擎时,是如何处理索引扫描和全表扫描的?还有,优化器具体是如何选择行计划的,是基于统计信息吗? 再想想,连接管理阶段,线程的处理是怎样的?每个连接是否对应一个线程?是的,MySQL通常使用线程池来处理多个连接,每个连接在一个线程中处理。 还有,权限验证是在哪个阶段进行的?可能是在连接建立的时候检查全局权限,而在行查询的时候,行器会再次检查表级别的权限,比如是否有权限查询某个表。 关于存储引擎,不同的存储引擎处理方式不同,比如MyISAM和InnoDB在数据读取时的差异。比如,MyISAM不支持事务,而InnoDB支持,所以在处理查询时,InnoDB可能需要考虑MVCC(多版本并发控制)来保证读取的一致性,特别是在可重复读隔离级别下。 总结一下,整个流程应该是这样的: 1. 客户端发起连接,连接器管理连接,验证权限。 2. 查询先检查查询缓存(如果开启),命中则直接返回。 3. 分析器进行词法和语法分析,生成解析树。 4. 优化器生成行计划,选择最优路径。 5. 行器检查权限,调用存储引擎接口获取数据。 6. 存储引擎读取数据,返回给行器,再返回给客户端。 不过,需要确认这些步骤是否正确。比如,查询缓存在MySQL 8.0已经被移除了,所以现在可能不存在第二步。另外,预处理阶段是否在分析器之后,比如处理一些变量绑定或者语句重写? 可能还有预处理阶段,比如处理变量,或者检查表是否存在,列是否存在等语义分析,这部分可能在分析器中完成,或者是在优化器之前的一个阶段。 另外,行器在调用存储引擎的时候,是如何进行操作的?比如,行器可能根据行计划,调用存储引擎的索引扫描接口,逐行获取数据,然后根据WHERE条件过滤,或者存储引擎自己处理条件过滤? 比如,如果使用了索引条件下推(Index Condition Pushdown),存储引擎会在索引扫描时就进行部分条件过滤,减少回表次数。 可能行器会生成一个行计划,然后存储引擎按照这个计划去读取数据,比如全表扫描或者索引扫描,然后将结果返回给行器,行器可能再进行进一步的过滤、排序、分组等操作。 总之,整个流程大致分为连接管理、解析优化、数据获取这几个阶段。每个阶段的具体细节需要进一步确认。</think>MySQL查询数据的完整行流程可分为六个核心阶段,按顺序如下: --- ### 一、连接管理(Connector) 1. **建立连接** - 客户端通过TCP三次握手服务器建立连接 - 连接器验证用户名、密码、主机权限 - 成功后分配线程并维护连接状态(`show processlist`可见) 2. **连接保持** - 默认闲置8小时自动断开(`wait_timeout`参数控制) - 建议生产环境使用连接池管理 --- ### 二、查询缓存(Query Cache)※注:MySQL 8.0已移除 1. **缓存检查** - 以SQL语句为Key,结果集为Value的键值存储 - 要求语句**完全一致**(包括空格、大小写) 2. **缓存失效** - 任何数据修改操作(INSERT/UPDATE/DELETE)都会使相关表缓存失效 --- ### 三、解析预处理(Parser) 1. **词法分析** - 拆分SQL为关键字(如SELECT)、表名、列名等Token ```sql SELECT id,name FROM users WHERE age > 18 → 拆分为 [SELECT], [id], [,], [name], [FROM], [users], [WHERE], [age], [>], [18] ``` 2. **语法分析** - 生成抽象语法树(AST) - 校验基础语法错误(如缺少WHERE关键字) 3. **语义检查** - 验证表/列是否存在 - 检查数据类型兼容性 --- ### 四、查询优化(Optimizer) 1. **生成行计划** - 基于成本模型(Cost-Based Optimization)选择方案: ```sql -- 示例查询 SELECT * FROM t1 JOIN t2 USING(id) WHERE t1.c=10 AND t2.d=20; ``` 可能方案: - 方案1:先读取t1.c=10的记录,再关联t2 - 方案2:先读取t2.d=20的记录,再关联t1 2. **优化策略** - 索引选择(覆盖索引 vs 回表) - JOIN顺序调整 - 条件下推(Index Condition Pushdown) - 使用`EXPLAIN`可查看最终行计划 --- ### 五、行阶段(Executor) 1. **权限验证** - 检查用户对目标表的SELECT权限 2. **调用存储引擎** ```plaintext 行器 → 存储引擎接口 → 数据读取 ``` - 按行计划逐行获取数据 - 典型案例: - 使用索引:`index_read` - 全表扫描:`read_first_row` + `read_next_row` 3. **结果暂存** - 使用内存临时表处理GROUP BY/ORDER BY - 超过`tmp_table_size`则转为磁盘临时表 --- ### 六、结果返回 1. **增量返回机制** - 边行边发送(避免内存爆增) - 网络包大小受`max_allowed_packet`限制 2. **结果格式化** - 按协议封装数据(文本协议或二进制协议) - 字符集转换(如utf8mb4 → client编码) --- ### 流程图解 ```mermaid sequenceDiagram participant Client participant Connector participant Parser participant Optimizer participant Executor participant Storage_Engine Client->>Connector: TCP连接请求 Connector->>Client: 认证结果 Client->>Connector: 发送SQL查询 Connector->>Parser: 转交查询 Parser->>Optimizer: 解析后的AST Optimizer->>Executor: 行计划 Executor->>Storage_Engine: 数据请求 Storage_Engine->>Executor: 返回数据页 Executor->>Client: 流式返回结果 ``` --- ### 关键性能优化点 1. **连接池** - 减少频繁建立连接开销(推荐使用HikariCP等) 2. **索引设计** - 联合索引注意最左前缀则 - 避免过度索引影响写入性能 3. **行计划分析** - 定期使用`ANALYZE TABLE`更新统计信息 - 关注`EXPLAIN`中的type列: - const > ref > range > index > ALL 4. **存储引擎选择** - InnoDB:事务/高并发写入 - MyISAM:只读分析场景(已逐渐淘汰) 通过理解整个行流程,可以更精准地定位查询性能瓶颈并进行针对性优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值