当前位置: 首页 > news >正文

MySQL UPDATE语句执行链路解析

文章目录

    • 引言
    • 1. 总览:UPDATE语句的执行链路
    • 2. 客户端发起请求
      • 2.1 SQL请求的形成
      • 2.2 MySQL通信协议
    • 3. 连接器模块
      • 3.1 连接管
      • 3.2 会话上下文
    • 4. SQL解析器
      • 4.1 语法解析
      • 4.2 语法错误处理
    • 5. 查询优化器
      • 5.1 查询优化的核心概念
      • 5.2 优化器生成执行计划的步骤
      • 5.3 优化器常见挑战
    • 6. 权限校验模块
      • 6.1 权限校验的流程
      • 6.2 权限管理机制
      • 6.3 权限校验失败的处理
      • 6.4 性能与权限校验的关系
    • 7. 执行器与存储引擎交互
      • 7.1 判断数据页位置
        • Buffer Pool简介
        • 数据页的查找逻辑
        • 性能优化
      • 7.2 记录修改前的快照:Undo Log
        • Undo Log的作用
        • Undo Log的生成与写入
        • Undo Log的结构
        • 性能优化
      • 7.3 修改数据页
        • 数据页的修改逻辑
        • 脏页管理
      • 7.4 Redo Log的生成与两阶段提交
        • Redo Log的作用
        • Redo Log的写入流程
        • 性能优化
    • 8. Binlog的生成与组提交
      • 8.1 Binlog与Redo Log的区别
      • 8.2 Binlog的写入流程
      • 8.3 Binlog组提交的实现
        • 组提交的优点
        • 参数调优
    • 9. 数据页的最终写入与Double Write机制
      • 9.1 脏页刷盘的触发机制
      • 9.2 Double Write机制
        • 工作原理
        • 优点
        • 性能优化
      • 9.3 崩溃恢复机制
    • 10. 崩溃恢复机制的原理与过程
      • 10.1 崩溃恢复的核心目标
      • 10.2 崩溃恢复的主要阶段
        • 第一阶段:Redo Log重放
        • 第二阶段:Undo Log回滚
      • 10.3 Redo Log和Undo Log的协同工作
      • 10.4 影响崩溃恢复性能的因素
      • 10.5 参数调优建议
    • 11. 性能调优建议
      • 11.1 查询优化
      • 11.2 日志相关优化
      • 11.3 Buffer Pool配置
    • 12. 常见问题与解决方案
      • 12.1 长事务导致Undo Log积压
      • 12.2 查询优化器选择了非最优索引
      • 12.3 脏页刷盘导致性能波动
    • 13. 总结


引言

在现代应用中,数据库不仅需要支持高并发的读写操作,还需要在提供数据一致性保障的同时实现高性能。UPDATE语句作为修改数据库中现有数据的主要工具,其执行过程涵盖了从SQL解析、权限校验、事务管理到数据持久化的多个关键环节。本文将深入剖析MySQL中UPDATE语句的执行链路,结合流程图,逐步拆解各模块的职责和实现细节,帮助读者全面掌握这一过程的底层逻辑和优化方向。


1. 总览:UPDATE语句的执行链路

UPDATE语句的执行是一个复杂的过程,涉及多个核心模块和操作步骤。从客户端发起SQL请求,到最终完成数据页的修改并返回执行结果,整个链路可以分为以下几部分:

1.发送UPDATE请求
2.解析SQL语句
3.生成执行计划
4.表权限校验
5.请求执行
6.判断数据页是否在Buffer Pool中
7.记录修改前的快照到Undo Log
8.将Undo Log写入Undo Tablespace
9.修改Buffer Pool中的数据页
10.生成Redo Log并写入Redo Log Buffer
11.触发两阶段提交 阶段1 Prepare
12.将Redo Log从Buffer写入磁盘
13.记录逻辑更新到Binlog Cache
14.进入组提交队列
15.将Binlog写入文件系统缓存
16.将Binlog从文件系统缓存写入磁盘
17.阶段2 Commit 将Redo Log标记为Commit状态
18.后台线程异步将数据页刷新到磁盘
19.Double Write保护机制
客户端
连接器
查询解析器
查询优化器
权限校验模块
执行器
Buffer Pool
从Buffer Pool读取数据页
从磁盘加载数据页到Buffer Pool
Undo Log
磁盘中的Undo Tablespace
更新数据页
Redo Log Buffer
Redo Log标记Prepare状态
磁盘的Redo Log文件
Binlog Cache
组提交等待队列
Page Cache
磁盘的Binlog文件
磁盘中的数据页
写入临时空间后再写入真正数据页
返回客户端更新结果
崩溃恢复 根据Redo Log恢复提交事务,Undo Log回滚未提交事务

这一流程由客户端请求到事务提交再到最终数据写入磁盘的多个关键步骤组成。接下来,我们将逐步拆解每一个阶段的工作原理和关键细节。


2. 客户端发起请求

2.1 SQL请求的形成

在MySQL的使用场景中,客户端通常通过API或驱动程序(如MySQL Connector/J、MySQL Connector/Python)发起SQL请求。典型的UPDATE语句结构如下:

UPDATE table_name 
SET column_name = new_value 
WHERE condition;

SQL请求的结构决定了MySQL后续的执行路径:

  • table_name:确定需要操作的目标表。
  • SET column_name = new_value:定义需要更新的数据。
  • WHERE condition:限制更新范围。通常,条件会涉及索引优化和行定位。

2.2 MySQL通信协议

MySQL的通信基于客户端-服务端模型,通过TCP/IP协议进行数据传输。关键过程如下:

  • 连接建立:客户端通过MySQL驱动程序向服务端发送连接请求。MySQL服务端验证用户身份后,建立连接。
  • 数据传输:MySQL通信协议采用二进制格式,在客户端与服务端之间进行SQL请求和响应的数据交换。
  • 优化机制:MySQL支持数据压缩与SSL加密,以提高传输效率和安全性。

3. 连接器模块

3.1 连接管

连接器是MySQL服务器的入口模块,负责建立和维护与客户端的连接。在客户端成功发送UPDATE请求后,连接器的主要工作包括:

  1. 认证

    • 验证用户身份,校验用户名和密码。
    • 检查用户是否允许从当前IP地址访问数据库。
    • 设置用户会话上下文(包括权限、SQL模式等)。
  2. 连接生命周期管理

    • 为每个客户端分配独立的连接ID。
    • 维持连接心跳检测,检测客户端连接是否正常。
  3. 连接池优化

    • 通过复用连接减少频繁建立和销毁连接的开销。
    • 高并发情况下,连接池是数据库性能的关键优化点。

3.2 会话上下文

每个连接会话都包含一组上下文信息,包括:

  • 当前数据库名称(USE database_name)。
  • 事务隔离级别(如READ COMMITTED)。
  • 用户的权限及当前可用资源限制。

4. SQL解析器

4.1 语法解析

连接器接收到SQL请求后,将其传递给SQL解析器。解析器的职责是:

  1. 语法分析
  • 检查SQL语句是否符合MySQL的语法规则。
  • 将SQL文本转换为抽象语法树(AST)。

示例
对于以下SQL语句:

UPDATE users SET name = 'John' WHERE id = 1;

抽象语法树可能包含以下信息:

  • 操作类型:UPDATE
  • 目标表:users
  • 修改字段:name
  • 条件:id = 1

图示

UPDATE SQL语句
抽象语法树
操作类型: UPDATE
目标表: users
修改字段: name
条件: id = 1
  1. 语义分析
    • 校验表、字段、条件是否存在。
    • 校验数据类型的合法性。

4.2 语法错误处理

解析器在发现语法错误时,会立即终止执行并向客户端返回错误信息。例如:

Error Code: 1064. You have an error in your SQL syntax.

5. 查询优化器

在SQL语句经过解析器生成抽象语法树后,会进入查询优化器阶段。优化器的主要任务是基于语法树生成执行计划,并选择出最低成本的执行路径。对于UPDATE语句而言,这一步至关重要,因为它直接影响到性能,特别是在涉及大表或复杂条件时。


5.1 查询优化的核心概念

查询优化器的主要目标是以最低的成本完成数据修改。为了达成这一目标,优化器会考虑以下因素:

  1. 访问路径
    • 使用主键索引或二级索引快速定位目标行。
    • 全表扫描:在无法利用索引时直接遍历整个表。
  2. 执行顺序
    • 如果UPDATE涉及多表联合查询,优化器会确定表的连接顺序。
  3. 代价模型
    • 每种执行路径的代价(Cost)会被估算,优化器选择代价最低的方案。

5.2 优化器生成执行计划的步骤

  1. 初始计划生成

    • 基于解析器生成的抽象语法树,构建初始执行计划。
    • 这一步可能包括对WHERE条件的解析,将逻辑表达式拆解为可计算的条件。
  2. 索引选择

    • 优化器基于统计信息,判断使用哪一个索引能够最优地执行UPDATE语句。
    • 如果目标表没有合适的索引,优化器可能选择全表扫描。
    • 统计信息
      • 行数、列的分布、索引的选择性(选择性越高,索引越优)。
    • 索引优化图示
WHERE条件: id=1 AND name='John'
索引1: id索引
索引2: name索引
全表扫描
估算成本: 低
估算成本: 中
估算成本: 高
选择索引1执行
  1. 执行顺序优化

    • 当多个表参与更新操作时,优化器会重新排列表的连接顺序,以减少数据扫描的次数。
  2. 最终计划选择

    • 在评估多个可能的执行计划后,选择最优的计划作为最终执行方案。

5.3 优化器常见挑战

  1. 统计信息过期

    • 如果表的统计信息未及时更新,可能导致错误的索引选择。
    • 解决方案:定期执行ANALYZE TABLE更新统计信息。
  2. 复杂查询

    • 子查询和嵌套查询可能使优化器的代价估算不准确。
    • 解决方案:将复杂查询改写为更易优化的形式。
  3. 索引设计不合理

    • 如果缺少覆盖索引或复合索引,可能导致较高的执行代价。
    • 解决方案:设计合适的索引策略。

6. 权限校验模块

在执行计划生成之后,MySQL会进入权限校验阶段。权限校验是UPDATE语句执行过程中重要的安全环节,用于确保用户具备执行当前操作的权限。


6.1 权限校验的流程

  1. 校验用户级权限
    • 首先检查用户是否具备全局级权限(如UPDATE权限)。
  2. 校验数据库级权限
    • 如果没有全局权限,则校验用户对目标数据库的权限。
  3. 校验表级权限
    • 确保用户对目标表具备UPDATE权限。
  4. 校验字段级权限
    • 如果UPDATE涉及特定字段(如SET column=value),还需检查用户是否具备对这些字段的修改权限。

6.2 权限管理机制

MySQL的权限管理基于系统表mysql.usermysql.dbmysql.tables_priv,每个表存储不同层级的权限信息。例如:

  • 全局权限(存储在mysql.user中):适用于所有数据库和表。
  • 数据库权限(存储在mysql.db中):针对特定数据库的操作。
  • 表和列权限(存储在mysql.tables_privmysql.columns_priv中):对特定表和列的操作权限。

6.3 权限校验失败的处理

如果用户权限不足,MySQL会立即终止执行并返回错误消息,例如:

Error Code: 1142. UPDATE command denied to user 'user'@'localhost' for table 'table_name'

6.4 性能与权限校验的关系

权限校验通常不会对性能产生显著影响,但高并发场景下,权限校验可能成为瓶颈。这时可以采取以下优化措施:

  1. 减少权限层级校验
    • 在用户账户设计时,尽量赋予合适的全局或数据库级权限,避免过多的表级和字段级校验。
  2. 优化权限表查询
    • 确保权限相关系统表不被频繁锁定,支持快速读取。

7. 执行器与存储引擎交互

执行器负责根据优化器生成的执行计划,与存储引擎交互来完成具体的数据操作。在UPDATE语句中,执行器的任务是按照计划定位目标行,记录必要的日志,并更新对应的数据页。以下是执行器与存储引擎交互的详细拆解。


7.1 判断数据页位置

执行器的第一步是确定UPDATE目标数据是否已经加载到内存中的Buffer Pool。

Buffer Pool简介

Buffer Pool是InnoDB存储引擎中的核心组件,用于缓存最近访问的数据页,以减少磁盘IO操作。它是一个内存区域,包含以下主要结构:

  • 数据页:实际存储表的数据。
  • 索引页:存储表的索引结构。
  • Undo页:记录修改前的快照,用于事务回滚。
  • Redo日志页:为崩溃恢复提供支持。
数据页的查找逻辑

执行器通过查询优化器生成的路径(如索引扫描)定位目标数据页:

  1. 在Buffer Pool中查找数据页
    • 如果数据页已经存在于Buffer Pool,则直接读取。
  2. 从磁盘加载数据页
    • 如果数据页不在Buffer Pool中,则从磁盘加载。
    • 加载时可能触发页替换机制(如LRU算法)。

以下是判断数据页位置的流程图:

目标数据页
Buffer Pool中是否存在?
直接读取数据页
从磁盘加载数据页
写入Buffer Pool
性能优化
  1. 提高Buffer Pool命中率
    • 通过增加Buffer Pool大小(innodb_buffer_pool_size)。
    • 定期优化查询以减少不必要的数据扫描。
  2. 减少磁盘IO
    • 使用固态硬盘(SSD)提升磁盘读取速度。
    • 配置预读(Read Ahead)策略,批量加载相关数据页。

7.2 记录修改前的快照:Undo Log

在数据修改前,执行器会将目标数据的快照记录到Undo Log。Undo Log的存在使得事务能够实现回滚,并支持一致性读。

Undo Log的作用
  1. 事务回滚
    • 如果事务未提交,Undo Log可用于撤销已进行的修改。
  2. 一致性读
    • 在MVCC(多版本并发控制)中,读取未提交事务的历史快照依赖Undo Log。
Undo Log的生成与写入
  1. 快照生成
    • 在执行器确定需要修改的数据后,先将其原始数据复制到Undo Log。
  2. 写入Undo Tablespace
    • Undo Log初始存储于内存中,随后定期刷写到磁盘中的Undo Tablespace。
Undo Log的结构

Undo Log通常存储为逻辑日志,而非物理页数据。其格式包含以下内容:

  • 事务ID:记录该Undo Log属于哪个事务。
  • 操作类型INSERTUPDATEDELETE
  • 原始数据:修改前的数据值。

以下是Undo Log写入流程的简化图示:

目标数据页
记录原始数据快照
生成Undo Log
写入内存中的Undo Log Buffer
定期写入Undo Tablespace
性能优化
  1. 优化Undo Tablespace的配置
    • 增加Undo Tablespace的数量,避免日志写入竞争。
    • 使用SSD提升写入性能。
  2. 事务合并优化
    • 尽量减少长事务,避免Undo Log积压。

7.3 修改数据页

在Undo Log记录完成后,执行器正式对目标数据页进行修改。

数据页的修改逻辑
  1. 数据定位
    • 根据主键或索引确定目标行的位置。
  2. 页内更新
    • 在Buffer Pool中的数据页上直接进行修改。
    • 数据修改时标记该页为“脏页”(Dirty Page)。
脏页管理
  • 脏页的含义
    • 数据页被修改但尚未写入磁盘的状态。
  • 脏页列表
    • InnoDB会维护一个脏页列表,以跟踪所有尚未刷盘的页。
  • 延迟刷盘
    • 脏页不会立即写入磁盘,而是在事务提交或Buffer Pool满时触发刷盘。

7.4 Redo Log的生成与两阶段提交

Redo Log的作用

Redo Log记录了数据修改的物理操作,用于崩溃恢复。其主要功能包括:

  1. 保障事务的持久性
    • 即使在崩溃后,已提交的事务仍能通过Redo Log恢复。
  2. 支持事务提交
    • 与Binlog协同完成两阶段提交,确保数据一致性。
Redo Log的写入流程
  1. 写入Redo Log Buffer
    • 修改数据页后,生成Redo Log并存储于Redo Log Buffer。
  2. Prepare阶段
    • 在事务提交前,先将Redo Log标记为Prepare状态。
  3. 刷入磁盘
    • 将Redo Log从Buffer写入磁盘上的Redo Log文件。
  4. Commit阶段
    • 最终将Redo Log标记为Commit状态,完成事务提交。

以下是Redo Log两阶段提交的流程图:

生成Redo Log
写入Redo Log Buffer
Prepare阶段: 标记Prepare状态
刷入Redo Log文件
Commit阶段: 标记Commit状态
事务提交完成
性能优化
  1. Redo Log组提交
    • 多个事务的Redo Log可以合并写入磁盘,减少IO操作。
  2. 调整Redo Log Buffer大小
    • 增大innodb_log_buffer_size,减少Redo Log写盘的频率。

8. Binlog的生成与组提交

Binlog(Binary Log,二进制日志)是MySQL中用于记录逻辑操作的日志,主要作用是支持数据恢复和主从复制。与Redo Log的物理操作记录不同,Binlog以逻辑方式描述事务的修改。


8.1 Binlog与Redo Log的区别

  1. 记录内容
    • Redo Log:记录物理层面的“修改页”操作,用于崩溃恢复。
    • Binlog:记录逻辑层面的“事务操作”,如UPDATE table_name SET column=value WHERE condition
  2. 写入时机
    • Redo Log:事务在执行过程中实时写入。
    • Binlog:事务提交时才写入。
  3. 用途
    • Redo Log:用于数据库的崩溃恢复。
    • Binlog:支持主从复制和基于时间点的恢复。

8.2 Binlog的写入流程

在事务修改完成并生成Redo Log后,MySQL会将修改的逻辑操作记录到Binlog中。Binlog写入过程如下:

  1. Binlog Cache生成

    • 每个事务单独维护一个Binlog Cache,临时存储其修改的操作逻辑。
    • SET binlog_cache_size 参数控制每个事务的Binlog Cache大小。
  2. 组提交队列

    • 事务提交时,Binlog Cache内容被加入组提交队列,等待统一写入。
    • 组提交是Binlog写入性能优化的核心机制。
  3. 写入文件系统缓存

    • 组提交队列中的内容被批量写入文件系统的Page Cache。
    • 这个阶段是高效的,因为涉及的是内存操作。
  4. 刷盘

    • 文件系统缓存中的数据被写入磁盘,生成Binlog文件。

以下是Binlog写入流程的图示:

事务生成Binlog Cache
组提交队列
写入文件系统缓存
刷入磁盘生成Binlog文件

8.3 Binlog组提交的实现

组提交是优化Binlog写入性能的关键,它能够将多个事务的Binlog写入操作合并为一次磁盘IO。其工作原理如下:

  1. 事务提交排队
    • 事务进入提交队列,等待组提交的触发。
  2. 批量写入
    • 多个事务的Binlog Cache合并写入文件系统缓存。
  3. 批量刷盘
    • 将合并后的内容一次性写入磁盘。
组提交的优点
  • 减少磁盘写入操作,提高事务提交性能。
  • 对高并发场景尤为有效。
参数调优
  1. sync_binlog
    • 控制Binlog的刷盘频率。
    • 设置为0表示由操作系统控制,性能高但可能丢日志。
    • 设置为1确保每次提交后都刷盘,数据安全但性能低。
  2. binlog_cache_size
    • 增大缓存大小,减少事务生成Binlog Cache时的内存分配开销。

9. 数据页的最终写入与Double Write机制

在事务提交完成后,数据页需要最终写入磁盘以确保数据持久化。此过程由后台线程完成,结合Double Write机制提供数据写入的安全性。


9.1 脏页刷盘的触发机制

脏页的刷盘通常由以下几种情况触发:

  1. Buffer Pool满
    • 当Buffer Pool的可用空间不足时,会主动触发脏页刷盘。
  2. 事务提交
    • 提交的事务可能触发脏页的同步写入。
  3. 后台线程定时刷盘
    • InnoDB后台线程会定期将脏页写入磁盘。

9.2 Double Write机制

Double Write是InnoDB的一项安全机制,用于防止由于写入中断(如宕机)导致的数据页损坏。

工作原理
  1. 临时空间写入
    • 在将数据页写入实际表空间之前,先将其写入Double Write Buffer(一个专用的磁盘区域)。
  2. 正式写入
    • 如果临时写入成功,再将数据页写入实际表空间。
  3. 崩溃恢复
    • 如果在写入表空间时发生宕机,InnoDB可以从Double Write Buffer中恢复数据。

以下是Double Write流程图:

脏页
写入Double Write Buffer
写入成功?
写入表空间
从Buffer恢复数据
优点
  • 防止部分写入导致的数据页损坏。
  • 提供额外的写入保护机制。
性能优化
  1. 配置独立存储
    • 将Double Write Buffer存储在独立的磁盘上,减少写入竞争。
  2. 优化刷盘频率
    • 调整后台线程的刷新策略,避免频繁触发。

9.3 崩溃恢复机制

在数据库崩溃后,InnoDB会结合Redo Log和Undo Log实现数据恢复:

  1. Redo Log重放
    • 已提交事务的修改通过Redo Log重做。
  2. Undo Log回滚
    • 未提交事务的操作通过Undo Log回滚。

恢复过程结合Binlog,可以实现精确到某一时间点的数据还原,进一步增强数据的可靠性。


10. 崩溃恢复机制的原理与过程

在数据库系统中,崩溃可能因多种原因发生,例如宕机、硬件故障或进程异常终止。为了在崩溃后仍然能够保证数据的一致性和完整性,MySQL 的 InnoDB 存储引擎设计了高效的崩溃恢复机制,主要依赖 Redo LogUndo Log。本节将详细解析崩溃恢复的原理及其执行过程。


10.1 崩溃恢复的核心目标

  1. 保证数据一致性

    • 已提交的事务,必须确保数据持久化。
    • 未提交的事务,所有更改必须回滚,恢复到事务开始前的状态。
  2. 高效恢复

    • 恢复过程需尽量减少时间,确保服务快速重启。
  3. 保护机制的协作

    • Redo Log:用于重做已提交事务的操作。
    • Undo Log:用于回滚未提交事务的更改。

10.2 崩溃恢复的主要阶段

第一阶段:Redo Log重放

目标:通过Redo Log,将已提交的事务重做到磁盘上,恢复事务的持久化修改。

  1. Redo Log的特性

    • Redo Log记录的是物理层面的页修改信息(如“在某页某偏移量写入某数据”)。
    • 使用WAL(Write-Ahead Logging)技术,日志先行,事务的修改只有在Redo Log写入磁盘后才算完成。
  2. Redo Log重放流程

    • 扫描Redo Log文件
      • 从日志头部开始扫描,找到所有处于PrepareCommit状态的日志。
    • 按顺序重放
      • 对每条日志执行重做操作,将页的修改写入表空间。
    • 日志位置标记
      • 更新日志头,标记已处理的日志位置,防止重复重放。

以下为Redo Log重放的流程图:

读取Redo Log
找到Prepare和Commit日志
按顺序重放日志
写入表空间
更新日志头
  1. 关键优化
    • Redo Log按顺序写入,顺序读性能高。
    • 可利用多个线程并行重做,以加速恢复。

第二阶段:Undo Log回滚

目标:回滚未提交事务,将数据恢复到事务开始前的状态。

  1. Undo Log的特性

    • Undo Log记录逻辑层面的修改前数据,支持回滚操作。
    • 事务提交后,相关Undo Log可以被回收。
  2. Undo Log回滚流程

    • 扫描事务表
      • 在事务系统中找到所有未提交的事务。
    • 回滚每个事务
      • 根据Undo Log依次撤销每个未提交事务的修改。
    • 清理回滚记录
      • 回滚完成后,将对应的Undo Log标记为可回收。

以下为Undo Log回滚的流程图:

扫描未提交事务
读取对应Undo Log
回滚修改
清理Undo Log记录
完成回滚
  1. 回滚中的一致性读
    • 在回滚期间,其他事务仍可通过MVCC读取一致性快照。

10.3 Redo Log和Undo Log的协同工作

崩溃恢复中,Redo Log和Undo Log分工明确:

  1. Redo Log确保持久性
    • Redo Log重做已提交事务,保证修改不会丢失。
  2. Undo Log确保一致性
    • Undo Log回滚未提交事务,恢复数据原始状态。

以下为二者协作的示意图:

已提交
未提交
崩溃恢复开始
事务状态?
重放Redo Log
回滚Undo Log
完成Redo Log恢复
完成Undo Log回滚
恢复完成

10.4 影响崩溃恢复性能的因素

  1. Redo Log文件大小

    • 较大的Redo Log文件需要更长时间扫描。
    • 适当调整innodb_log_file_size以平衡性能和恢复时间。
  2. 事务提交频率

    • 长事务可能导致Redo Log和Undo Log积压。
    • 避免长时间持有锁的事务。
  3. 磁盘性能

    • 使用SSD可显著提升日志的写入和恢复效率。

10.5 参数调优建议

  1. Redo Log相关参数

    • innodb_log_file_size:设置适当大小,避免日志频繁切换。
    • innodb_log_buffer_size:增加缓冲区,减少写盘频率。
  2. Undo Log相关参数

    • innodb_undo_tablespaces:增加Undo表空间数量,降低竞争。
    • innodb_max_undo_log_size:限制单个Undo Log文件大小。
  3. 事务配置

    • 设置合理的autocommit行为,减少事务持锁时间。

11. 性能调优建议

基于MySQL的UPDATE语句执行链路和底层原理,以下是一些关键的性能调优方向:


11.1 查询优化

  1. 索引设计

    • 为常用的查询条件设计复合索引,避免全表扫描。
    • 删除未被使用的冗余索引,降低写操作开销。
  2. SQL语句优化

    • 尽量使用简单且明确的WHERE条件。
    • 避免在查询条件中对列进行函数操作(如WHERE YEAR(date_column) = 2024),这会阻止索引的使用。

11.2 日志相关优化

  1. Redo Log优化

    • 增大Redo Log文件大小(innodb_log_file_size),减少切换日志的频率。
    • 增加Redo Log缓冲区大小(innodb_log_buffer_size),减少磁盘写入次数。
  2. Binlog优化

    • 根据数据恢复需求设置sync_binlog
      • 对数据安全要求高:sync_binlog = 1
      • 性能优先:sync_binlog = 0sync_binlog = N

11.3 Buffer Pool配置

  1. 增大Buffer Pool大小

    • 提高命中率,减少磁盘IO。
    • 参数:innodb_buffer_pool_size
  2. 启用Buffer Pool实例化

    • 在多核环境下启用多个Buffer Pool实例,避免单实例锁竞争。
    • 参数:innodb_buffer_pool_instances

12. 常见问题与解决方案

12.1 长事务导致Undo Log积压

问题描述:长时间未提交的事务会导致Undo Log不断增长,占用大量磁盘空间,同时阻碍MVCC的版本清理。
解决方案

  1. 定期检查并终止长时间运行的事务:
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(TIMEDIFF(NOW(),trx_started)) > 60;
  1. 优化事务逻辑,确保及时提交。

12.2 查询优化器选择了非最优索引

问题描述:统计信息不准确时,优化器可能选择了全表扫描或低效索引。
解决方案

  1. 更新统计信息:
ANALYZE TABLE table_name;
  1. 手动提示优化器使用合适的索引:
SELECT * FROM table_name FORCE INDEX(index_name) WHERE condition;

12.3 脏页刷盘导致性能波动

问题描述:Buffer Pool中的脏页积压,后台线程集中刷盘时可能导致性能抖动。
解决方案

  1. 调整后台刷盘频率:
SET GLOBAL innodb_flush_neighbors = 0;
  1. 增大Buffer Pool大小,减少刷盘次数。

13. 总结

MySQL UPDATE语句的执行过程是一个涉及多个模块和复杂机制的系统工程。通过深入理解其执行链路,我们可以在不同场景下采取优化措施,从而显著提升数据库的性能和可靠性。

  1. 模块职责清晰:连接器、优化器、执行器、存储引擎各司其职,共同保障高效执行。
  2. 日志机制协同:Redo Log、Undo Log和Binlog协同工作,确保数据的一致性和持久性。
  3. 调优策略丰富:从查询优化到存储引擎配置,调优点覆盖内存、磁盘、事务等多个层面。

关注我

相关文章:

MySQL UPDATE语句执行链路解析

文章目录 引言1. 总览:UPDATE语句的执行链路2. 客户端发起请求2.1 SQL请求的形成2.2 MySQL通信协议 3. 连接器模块3.1 连接管3.2 会话上下文 4. SQL解析器4.1 语法解析4.2 语法错误处理 5. 查询优化器5.1 查询优化的核心概念5.2 优化器生成执行计划的步骤5.3 优化器…...

大语言模型通用能力排行榜(2024年11月8日更新)

数据来源SuperCLUE 榜单数据为通用能力排行榜 排名 模型名称 机构 总分 理科 文科 Hard 使用方式 发布日期 - o1-preview OpenAI 75.85 86.07 76.6 64.89 API 2024年11月8日 - Claude 3.5 Sonnet(20241022) Anthropic 70.88 82.4…...

java远程服务器调试

1远程debug -agentlib:jdwptransportdt_socket,servery,suspendn,address服务器ip:port 2.jmx JAVA_OPT“${JAVA_OPT} -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.portport -Dcom.sun.management.jmxremote.local.onlyfalse -Dcom.sun.management.jmxr…...

如何使用 Vivado 从源码构建 Infinite-ISP FPGA 项目

如约介绍源码构建 Infinite-ISP 项目,其实大家等的是源码,所以中间过程简洁略过,可以直接翻到文末获取链接。 开源ISP(Infinite-ISP)介绍 构建工程 第一步,从文末或者下面链接获取源码 https://github.com/…...

全志T113双核异构处理器的使用基于Tina Linux5.0——RTOS系统定制开发

8、RTOS系统定制开发 此处以在rtos/components/aw目录下创建一个简单的软件包为例,帮助客户了解RTOS环境,为RTOS系统定制开发提供基础。 RTOS环境下的软件包主要由三部分组成,源文件,Makefile,Kconfig,如下…...

A045-基于spring boot的个人博客系统的设计与实现

🙊作者简介:在校研究生,拥有计算机专业的研究生开发团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹 赠送计算机毕业设计600…...

SpringBoot集成ES(ElasticSearch)

1.导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>导入依赖后&#xff0c;注意在依赖中查看对应的版本是否与本机ES对应 2.创建配置并…...

使用docker快速部署Nginx、Redis、MySQL、Tomcat以及制作镜像

文章目录 应用快速部署NginxRedisMySQLTomcat 制作镜像镜像原理基于已有容器创建使用 Dockerfile 创建镜像指令说明构建应用创建 Dockerfile 文件创建镜像 应用快速部署 Nginx docker run -d -p 80:80 nginx使用浏览器访问虚拟机地址 Redis docker pull redis docker run --…...

实验四:构建园区网(OSPF 动态路由)

目录 一、实验简介 二、实验目的 三、实验需求 四、实验拓扑 五、实验步骤 1、在 eNSP 中部署网络 2、设计全网 IP 地址 3、配置二层交换机 4、配置路由交换机并测试通信 5、配置路由接口地址 6、配置 OSPF 动态路由&#xff0c;实现全网互通 一、实验简介 使用路由…...

【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-31

文件下载与邀请翻译者 学习英特尔开发手册&#xff0c;最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册&#xff0c;会是一件耗时费力的工作。如果有愿意和我一起来做这件事的&#xff0c;那么&#xff…...

debian 如何进入root

debian root默认密码, 在Debian系统中&#xff0c;安装完成后&#xff0c;默认情况下root账户是没有密码的。 你可以通过以下步骤来设置或更改root密码&#xff1a; 1.打开终端。 2.输入 sudo passwd root 命令。 3.当提示输入新的root密码时&#xff0c;输入你想要的密码…...

极坐标气泡图:医学数据分析的可视化新视角

在医学研究中&#xff0c;数据的可视化是至关重要的。它不仅能帮助我们更直观地理解数据&#xff0c;还能揭示数据中隐藏的模式和趋势。今天&#xff0c;我们要介绍一种独特的数据可视化工具——极坐标气泡图&#xff0c;以及它在医学中的重要作用。 什么是极坐标气泡图&#…...

【随手笔记】电脑端上位机初涉(一)

实现电脑端上位机的方式及其学习难度和知识点 在嵌入式开发中&#xff0c;电脑端上位机程序用于与嵌入式设备进行通信和控制。以下是几种常见的实现方式&#xff0c;以及它们的学习难度和所需的知识点&#xff1a; Python PySerial 学习难度&#xff1a;低知识点&#xff1a;…...

对抗样本存在的原因

对抗样本存在的原因与深度学习模型的结构和训练机制密切相关&#xff0c;主要包括以下几个方面&#xff1a; 1. 模型的高维性和线性化行为 高维性&#xff1a;深度学习模型通常在高维空间中运行&#xff0c;而高维空间中的数据分布非常稀疏。微小的扰动在高维空间可能被放大&a…...

Python编程整理汇总(基础汇总版)

1. 基础语法 1.1 变量与数据类型 整数&#xff1a;a 10 浮点数&#xff1a;b 3.14 字符串&#xff1a;c "Hello, World!" 布尔值&#xff1a;d True 列表&#xff1a;e [1, 2, 3, 4, 5] 元组&#xff1a;f (1, 2, 3) 字典&#xff1a;g {"name&qu…...

24软专 数据结构

1、A[n]&#xff0c;k&#xff0c;将数组向右循环移动k位。要求时间复杂度O(n)&#xff0c;空间O(1)。 思路&#xff1a;采用三次反转数组的操作&#xff0c;可以实现时间复杂度为O(n)&#xff0c;空间复杂度为O(1)的算法。 void moveElem(int array[],int k,int length){//a…...

如何更改手机GPS定位

你是否曾想过更改手机GPS位置以保护隐私、玩游戏或访问受地理限制的内容&#xff1f;接下来我将向你展示如何使用 MagFone Location Changer 更改手机GPS 位置&#xff01;无论是在玩Pokmon GO游戏、发布社媒贴子&#xff0c;这种方法都快速、简单且有效。 第一步&#xff1a;下…...

java Queue 详解

Java Queue 详解 Queue 是 Java 集合框架中用于实现 队列 数据结构的接口&#xff0c;位于 java.util 包中。队列是一种 先进先出&#xff08;FIFO&#xff09; 的数据结构&#xff0c;元素按照插入的顺序依次出队。 1. Queue 的基本特性 FIFO&#xff08;First-In-First-Out&…...

贪心算法 -- 递增子序列

目录 最长递增子序列 题解&#xff1a; 代码&#xff1a; 递增的三元子序列 题解&#xff1a; 代码&#xff1a; 简易版&#xff1a; 最长连续递增序列 题解&#xff1a; 代码&#xff1a; 最长递增子序列 300. 最长递增子序列 - 力扣&#xff08;LeetCode&#xf…...

MySQL:表的增删查改

目录 一. Create 1.1 单行数据全列插入 1.2 多行数据全列插入 1.3 插入否则更新 1.3.1 要插入的值与原数据有冲突则更新 1.3.2 要插入的值与原数据没有冲突则正常插入 1.3.3 要插入的值与原数据有冲突但是连续更新了两次 1.4 替换 二. Retrieve 2.…...

Python操作neo4j库py2neo使用之创建和查询(二)

Python操作neo4j库py2neo使用之创建和查询&#xff08;二&#xff09; py2neo 创建操作 1、连接数据库 from py2neo import Graph graph Graph("bolt://100.100.20.55:7687", auth(user, pwd), nameneo4j)2、创建Node from py2neo import Node, Subgraph # 创建…...

【pytorch-04】:线性回归案例(手动构建)

文章目录 1 构建数据集2 构建假设函数3 损失函数4 优化方法5 训练函数6.总结 1 构建数据集 为什么构建数据加载器&#xff1f; 在进行训练的时候都是采用的不是全部的数据&#xff0c;而是采用一个batch_size的数据进行训练&#xff0c;每次向模型当中送入batch_size数据&#…...

外包干了3年,技术退步明显...

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01; 而我已经在一个企业干了四年的功能…...

React Native 全栈开发实战班 -原生功能集成之相机与图片

在移动应用中&#xff0c;相机功能 和 图片选择 是非常常见的需求&#xff0c;用户可以通过相机拍照或从相册中选择图片。React Native 提供了多种方式来实现相机和图片选择功能&#xff0c;包括使用第三方库&#xff08;如 react-native-image-picker&#xff09;和调用原生模…...

以太坊交易处理全流程:数据采集、价格查询与问题解决

一、背景 在开发交易记录处理系统时,涉及从以太坊链上获取交易记录、将其存储到数据库、根据交易时间查询历史价格,并计算交易的美元价值。在这一过程中,涉及多个技术环节及工具的综合使用,例如区块链 API 调用、数据库操作、时间戳处理和外部数据接口整合。 本文涉及的内…...

css数据不固定情况下,循环加不同背景颜色

<template><div><p v-for"(item, index) in items" :key"index" :class"getBackgroundClass(index)">{{ item }}</p></div> </template><script> export default {data() {return {items: [学不会1, …...

【Node.js】Node.js 和浏览器之间的差异

Node.js 是一个强大的运行时环境&#xff0c;它在现代 JavaScript 开发中扮演着重要角色。然而&#xff0c;许多开发者在使用 Node.js 时常常会感到困惑&#xff0c;尤其是与浏览器环境的对比。本文将深入探讨 Node.js 和浏览器之间的差异&#xff0c;帮助你全面理解两者的设计…...

算法【最长递增子序列问题与扩展】

本文讲解最长递增子序列以及最长不下降子序列的最优解&#xff0c;以及一些扩展题目。本文中讲述的是最优解&#xff0c;时间复杂度是O(n*logn)&#xff0c;空间复杂度O(n)&#xff0c;好实现、理解难度不大。这个问题也可以用线段树来求解&#xff0c;时间和空间复杂度和本节讲…...

【论文速读】| RobustKV:通过键值对驱逐防御大语言模型免受越狱攻击

基本信息 原文标题&#xff1a;ROBUSTKV: DEFENDING LARGE LANGUAGE MODELS AGAINST JAILBREAK ATTACKS VIA KV EVICTION 原文作者&#xff1a;Tanqiu Jiang, Zian Wang, Jiacheng Liang, Changjiang Li, Yuhui Wang, Ting Wang 作者单位&#xff1a;Stony Brook University…...

查询Mysql中被锁住的表以及如何解锁

当MySQL中的表被锁住时&#xff0c;可能会导致查询变慢或完全无法访问该表。处理这种情况的方法取决于锁的原因以及你想要达到的目标。以下是一些常见的步骤和技巧&#xff0c;可以帮助你解决被锁住的表的问题&#xff1a; 1. 识别锁的情况 首先&#xff0c;你需要确定哪些表…...

【Mac】未能完成该操作 Unable to locate a Java Runtime

重生之我做完产品经理之后回来学习Data Mining Mac打开weka.jar报错"未能完成该操作 Unable to locate a Java Runtime" 1. 打开终端执行 java -version 指令&#xff0c;原来是没安装 JDK 环境 yyzccnn-mac ~ % java -version The operation couldn’t be comple…...

RT_Thread内核源码分析(三)——线程

目录 1. 线程结构 2. 线程创建 2.1 静态线程创建 2.2 动态线程创建 2.3 源码分析 2.4 线程内存结构 3. 线程状态 3.1 线程状态分类 3.2 就绪状态和运行态 3.3 阻塞/挂起状态 3.3.1 阻塞工况 3.4 关闭状态 3.4.1 线程关闭接口 3.4.2 静态线程关闭 3.4.3 动态线程关…...

淘宝 NPM 镜像源

npm i vant/weapp -S --production npm config set registry https://registry.npmmirror.com 要在淘宝 NPM 镜像站下载项目或依赖&#xff0c;你可以按照以下步骤操作&#xff1a; 1. 设置淘宝 NPM 镜像源 首先&#xff0c;你需要设置淘宝 NPM 镜像源以加速下载。可以通过…...

机器学习—学习曲线

学习曲线是帮助理解学习算法如何工作的一种方法&#xff0c;作为它所拥有的经验的函数。 绘制一个符合二阶模型的学习曲线&#xff0c;多项式或二次函数&#xff0c;画出交叉验证错误Jcv&#xff0c;以及Jtrain训练错误&#xff0c;所以在这个曲线中&#xff0c;横轴将是Mtrai…...

Rust 智能指针

Rust 智能指针 引言 Rust 是一种系统编程语言,以其内存安全性、并发性和高性能而闻名。Rust 的核心特性之一是其独特的所有权模型,它确保了内存安全,同时避免了垃圾收集。在 Rust 中,智能指针是一种特殊的数据结构,它们不仅存储数据,还负责管理数据的生命周期。智能指针…...

云原生周刊:Kubernetes v1.32 要来了

开源项目推荐 Woodpecker Woodpecker 是一款轻量级且功能强大的 CI/CD 引擎&#xff0c;以其高度可扩展性和易用性著称。它支持多种版本控制系统与编程语言&#xff0c;能够灵活适配不同开发流程&#xff0c;帮助团队实现高效的持续集成与交付。无论是个人项目还是大型团队&a…...

Easyexcel(3-文件导出)

相关文章链接 Easyexcel&#xff08;1-注解使用&#xff09;Easyexcel&#xff08;2-文件读取&#xff09;Easyexcel&#xff08;3-文件导出&#xff09; 响应头设置 通过设置文件导出的响应头&#xff0c;可以自定义文件导出的名字信息等 //编码格式为UTF-8 response.setC…...

php:使用socket函数创建WebSocket服务

一、前言 闲来无事&#xff0c;最近捣鼓了下websocket&#xff0c;但是不希望安装第三方类库&#xff0c;所以打算用socket基础函数创建个服务。 二、构建websocket服务端 <?phpclass SocketService {// 默认的监听地址和端口private $address 0.0.0.0;private $port 8…...

ubuntu20.04中编译安装gcc 9.2.0

ubuntu20.04中编译安装gcc 9.2.0,步骤如下&#xff1a; #install compile dependence libraries 1&#xff1a;$ sudo apt install libgmp-dev libisl-dev libmpc-dev libmpfr-dev # install gcc 9.2.0 # download source code 2&#xff1a;$ wget http://ftp.gnu.org/gn…...

ssm158企业人事管理系统的设计与实现+jsp(论文+源码)_kaic

设计题目&#xff1a;企业人事管理系统的设计与实现 摘 要 进入信息时代以来&#xff0c;很多数据都需要配套软件协助处理&#xff0c;这样可以解决传统方式带来的管理困扰。比如耗时长&#xff0c;成本高&#xff0c;维护数据困难&#xff0c;数据易丢失等缺点。本次使用数据…...

OceanBase数据库产品与工具介绍

OceanBase&#xff1a;蚂蚁集团自主研发的分布式关系数据库 1、什么是 OceanBase&#xff1f; OceanBase 是由蚂蚁集团完全自主研发的企业级分布式关系数据库&#xff0c;始创于 2010 年。它具有以下核心特点&#xff1a; 数据强一致性&#xff1a;在分布式架构下确保数据强…...

PakePlus将任何网页免费打包为mac/windows跨平台软件程序教程,只需要一个Github token就可以了

PakePlus是一个开源免费的软件&#xff0c;支持 Mac、Windows 和 Linux&#xff0c;很快也将支持 Android 和 iOS。无需在本地安装复杂的依赖环境&#xff0c;只需要一个Github Token就可以了。查看 README 以获取热门包和自定义开发信息。欢迎在讨论区分享你的建议。开源地址&…...

Element UI 组件库详解【Vue】

文章目录 一、引言二、安装并使用1. 安装2. 使用 三、常见组件说明1. 基础组件2. 布局组件3. 布局容器4. 选择框组件5. 输入框组件6. 下拉框组件7. 日期选择器8. 上传组件9. 表单组件10. 警告组件11. 提示组件12. 表格组件 一、引言 官方网站&#xff0c;element.eleme.cn El…...

Android kotlin之配置kapt编译器插件

配置项目目录下的gradle/libs.versions.toml文件&#xff0c;添加kapt配置项&#xff1a; 在模块目录下build.gradle.kt中增加 plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)// 增加该行alias(libs.plugins.jetbrains.kotl…...

基于 MUSA 的大语言模型推理和服务框架vLLM

1. 引言​ vLLM是一个高性能且内存高效的大语言模型推理和服务框架&#xff0c;也是当前业界使用范围最广的大模型推理框架&#xff0c;截至目前github star数28.4k。该框架性能优秀&#xff0c;而且部署容易&#xff0c;使用CUDA/ROCm提供GPU加速能力。但vLLM目前不支持使用摩…...

k8s 集群安装

安装rockylinux https://www.jianshu.com/p/a5fe20318b8e https://www.cnblogs.com/haoee/p/18290506 配置VirtualBox双网卡 https://www.cnblogs.com/ShineLeBlog/p/17580311.html https://zhuanlan.zhihu.com/p/341328334 https://blog.csdn.net/qq_36544785/article/deta…...

Linux-服务器辨别实体机OR虚拟机

快速命令 ① lscpu(查看CPU信息) lscpu Hypervisor vendor: KVM (超管理器厂商&#xff1a;KVM。虚拟机&#xff1a;KVM / VMware) Virtualization: VT-x&#xff08;虚拟化&#xff1a;VT-x。实体机&#xff1a;VT-x / AMD-V&#xff09; ② systemd-detect-virt(检测当前系…...

堤防安全监测系统方案

一、背景情况 堤防是开发利用水资源和防治水灾害的重要工程措施之一&#xff0c;对防洪、供水、生态、发电、航运等至关重要。我国现有堤防9.8万多座&#xff0c;其中大中型堤防4700多座、小型堤防9.4万座&#xff0c;80%以上修建于上世纪50至70年代。由于堤防管护力量薄弱&am…...

Leetcode 求根节点到叶节点数字之和

使用深度优先搜索 DFS 来做 我提供的代码使用的是 深度优先搜索&#xff08;DFS&#xff0c;Depth-First Search&#xff09; 算法。以下是具体的算法思想和实现步骤的解释&#xff1a; 算法思想 树的路径代表数字&#xff1a; 树中每条从根节点到叶子节点的路径可以看作一个整…...

Git分布式版本控制系统

1. 版本控制系统 版本控制系统主要分为两类&#xff1a;集中式、分布式。 集中式&#xff1a;SVM(工作流程&#xff1a;所有的文件都保存在中央服务器上&#xff0c;每个电脑上只保存了一个副本&#xff0c;当需要修改时&#xff0c;先下载中央服务器上的最新版本文件&#xf…...