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

MYSQL 存储引擎 和 日志

存储引擎

  • InnoDB 支持行级别的锁粒度,MyISAM 不支持,只支持表级别的锁粒度。
  • MyISAM 不提供事务支持。InnoDB 提供事务支持,实现了 SQL 标准定义了四个隔离级别。
  • MyISAM 不支持外键,而 InnoDB 支持。
  • MyISAM 不支持 MVCC,而 InnoDB 支持。
  • 虽然 MyISAM 引擎和 InnoDB 引擎都是使用 B+Tree 作为索引结构,但是两者的实现方式不太一样。InnoDB 使用缓冲池(Buffer Pool)缓存数据页和索引页,MyISAM 使用键缓存(Key Cache)仅缓存索引页而不缓存数据页。
  • MyISAM 不支持数据库异常崩溃后的安全恢复,而 InnoDB 支持。
  • InnoDB 的性能比 MyISAM 更强大。

 

慢查询日志有什么用?

  • 性能优化:通过分析慢查询日志,可以发现执行时间长的 SQL,优化索引、调整查询语句或数据库配置。
  • 资源监控:识别占用大量 CPU、内存或 I/O 的查询,避免影响其他业务。
  • 故障排查:定位导致数据库响应延迟的异常 SQL。

binlog 主要记录了什么?

Binlog(二进制日志) 是 MySQL 记录数据库变更的逻辑日志,主要用于:

  • 主从复制:将主库的变更同步到从库。
  • 数据恢复:通过回放 Binlog 恢复数据。
  • 审计:记录所有数据修改操作。

记录内容

  • 记录 SQL 语句本身(如 UPDATE user SET age=20 WHERE id=1)。
  • 记录具体行的变更(如 id=1 的 age 字段从 18 改为 20)。

特点

  • 逻辑日志:记录的是 SQL 语义,而非物理数据页。
  • 依赖事务:Binlog 按事务提交顺序记录,保证主从一致性。

写入机制

  • 事务执行过程中,先把日志写到binlog cache,事务提交的时候,再把binlog cache写到 binlog 文件中。
  • 因为一个事务的 binlog 不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache
  • 我们可以通过binlog_cache_size参数控制单个线程 binlog cache 大小,如果存储内容超过了这个参数,就要暂存到磁盘(Swap)。

 

  • write 和 fsync 由参数sync_binlog控制,默认是1
  • write,是指把日志写入到文件系统的 page cache,并没有把数据持久化到磁盘,所以速度比较快
  • fsync,才是将数据持久化到磁盘的操作

redo log 如何保证事务的持久性?    

Redo Log(重做日志) 是 InnoDB 的物理日志,用于保证事务的持久性(Durability)。其核心机制是 Write-Ahead Logging (WAL)

  1. 写日志先于写数据
    • 事务修改数据时,先将操作记录到 Redo Log 缓冲区(InnoDB 的 ib_logfile 文件)。
    • Redo Log 缓冲区满或检查点触发时,才会将日志刷盘。
    • 数据页的修改先暂存在 Buffer Pool,再异步刷盘到磁盘。
  2. 崩溃恢复
    • 如果数据库崩溃,重启时通过 Redo Log 重做(Redo)未完成的事务,确保数据一致性。

如何保证持久性?

  • 事务提交时:必须确保 Redo Log 已写入磁盘(fsync),才能返回成功。
  • 检查点(Checkpoint):定期将内存中的脏页(已修改的页)刷盘,并记录检查点位置,减少崩溃恢复时需要重做的日志量。

页修改之后为什么不直接刷盘呢?刷盘时机

  • MySQL 中数据是以页为单位,查询一条记录,会从硬盘把一页的数据加载出来,加载出来的数据叫数据页,会放入到 Buffer Pool 中。
  • 后续的查询都是先从 Buffer Pool 中找,没有命中再去硬盘加载,减少硬盘 IO 开销,提升性能。
  • 更新表数据的时候,也是如此,发现 Buffer Pool 里存在要更新的数据,就直接在 Buffer Pool 里更新。
  • 然后会把“在某个数据页上做了什么修改”记录到重做日志缓存(redo log buffer)里,接着刷盘到 redo log 文件里。每条 redo 记录由“表空间号+数据页号+偏移量+修改数据长度+具体修改的数据”组成。

                 

 

原因

  1. 性能问题
    • 直接刷盘会导致频繁的磁盘 I/O,显著降低写入性能。
  2. 缓冲池(Buffer Pool)的作用
    • 数据页的修改首先暂存在内存中的 Buffer Pool。
    • 通过批量刷盘(如组提交 Group Commit)减少 I/O 开销。
  3. Redo Log 的保障
    • 即使系统崩溃,Redo Log 可以重做未持久化的修改,确保数据不丢失。

刷盘时机

  • Buffer Pool 中的脏页达到阈值(如 innodb_max_dirty_pages_pct)。

  • 检查点触发 ,因为InnoDB 定期会执行检查点操作,将内存中的脏数据(已修改但尚未写入磁盘的数据)刷新到磁盘,并且会将相应的重做日志一同刷新,以确保数据的一致性。

  • 服务器正常关闭时。

  • 当事务提交时,log buffer 里的 redo log 会被刷新到磁盘(可以通过innodb_flush_log_at_trx_commit参数控制)默认 1,提交时刷盘。

    innodb_flush_log_at_trx_commit 的值有 3 种,也就是共有 3 种刷盘策略:

  1. 0:设置为 0 的时候,表示每次事务提交时不进行刷盘操作。这种方式性能最高,但是也最不安全,因为如果 MySQL 挂了或宕机了,可能会丢失最近 1 秒内的事务。
  2. 1:设置为 1 的时候,表示每次事务提交时都将进行刷盘操作。这种方式性能最低,但是也最安全,因为只要事务提交成功,redo log 记录就一定在磁盘里,不会有任何数据丢失。
  3. 2:设置为 2 的时候,表示每次事务提交时都只把 log buffer 里的 redo log 内容写入 page cache(文件系统缓存)。page cache 是专门用来缓存文件的,这里被缓存的文件就是 redo log 文件。这种方式的性能和安全性都介于前两者中间。

binlog 和 redolog 有什么区别?

  • 写入时机不同:redo log 在事务执行过程中可以不断写入,而 binlog 只有在提交事务时才写入。
  • Binlog 是逻辑日志,数据恢复,保证数据一致性Redo Log 是物理日志,崩溃恢复,保证事务持久性

两阶段提交

  • 两阶段提交是解决两份日志之间的逻辑一致问题:比如 执行过程中写完 redo log 日志后,binlog 日志写期间发生了异常,由于 binlog 没写完就异常,这时候 binlog 里面没有对应的修改记录。因此,之后用 binlog 日志恢复数据时,就会少这一次更新,而原库因为 redo log 日志崩溃恢复,恢复出来的数据不一致。
  • 解决方案:将 redo log 的写入拆成了两个步骤preparecommit,这就是两阶段提交
  • 使用两阶段提交后,写入 binlog 时发生异常,但是因为 MySQL 根据 redo log 日志崩溃恢复时,发现 redo log 还处于prepare阶段,并且没有对应 binlog 日志,就会回滚该事务。

Undo log (回滚日志)

每一个事务对数据的修改都会被记录到 undo log ,当执行事务过程中出现错误或者需要执行回滚操作的话,MySQL 可以利用 undo log 将数据恢复到事务开始之前的状态。

MySQL InnoDB 引擎使用 undo log(回滚日志) 来保证事务的原子性

undo log 属于逻辑日志,记录的是 SQL 语句

比如说事务执行一条 DELETE 语句,那 undo log 就会记录一条相对应的 INSERT 语句。同时,undo log 的信息也会被记录到 redo log 中,因为 undo log 也要实现持久性保护

并且,undo-log 本身是会被删除清理的,例如 INSERT 操作,在事务提交之后就可以清除掉了;UPDATE/DELETE 操作在事务提交不会立即删除,会加入 history list,由后台线程 purge 进行清理。

undo log 如何保证事务的原子性?

Undo Log 记录数据修改前的旧值,用于事务回滚和 MVCC:

  1. 事务回滚
    • 当事务执行 ROLLBACK 或因错误终止时,通过 Undo Log 将数据恢复到修改前的状态。
  2. MVCC 读一致性
    • 读操作通过 Undo Log 访问历史版本数据,避免读到未提交或已回滚的修改。
  3. 原子性保证
    • 如果事务未提交,其他事务无法看到其修改(通过 Undo Log 的版本控制)。
    • 事务回滚时,通过 Undo Log 撤销所有已做的修改。
http://www.dtcms.com/a/113390.html

相关文章:

  • 论文阅读笔记:Denoising Diffusion Implicit Models (5)
  • 英伟达Blackwell架构深度拆解:新一代GPU如何突破算力瓶颈?
  • DHCP Snooping 主要作用
  • 【Redis】通用命令
  • 聊聊Spring AI的ChromaVectorStore
  • #SVA语法滴水穿石# (007)关于 $past 的用法
  • P10587 「ALFR Round 2」C 小 Y 的数 Solution
  • Python 如何高效实现 PDF 内容差异对比
  • 房地产之后:探寻可持续扩张的产业与 GDP 新思
  • 在线编辑数学公式
  • NDK开发:音视频处理基础
  • 解释观察者模式,如何实现观察者模式?
  • 单域名 vs 通配符:如何选择最适合你的 SSL 证书?
  • API 类别 - 方法重载
  • JVM虚拟机篇(五):深入理解Java类加载器与类加载机制
  • 纯css实现环形进度条
  • React 零基础学习计划(10节课小项目)
  • STM32定时器通道1-4(CH1-CH4)的引脚映射关系
  • 信创国产化项目验收的标准与流程
  • HBase的安装与简单操作
  • 14.1linux中platform设备驱动实验(知识点)_csdn
  • 关于Linux系统安装和优化的教程
  • Three.js 系列专题 1:入门与基础
  • JetBrains插件市场(附官网地址)
  • [巴黎高师课程] 同步反应式系统第二课 - 同步数据流语言 Lustre v4, Lustre v6, Scade 6, Heptagon
  • Centos7 上 卸载 docker
  • 强化学习课程:stanford_cs234 学习笔记(3)introduction to RL
  • 经典算法 约数之和
  • 发布的React 19.1提供了什么新能力?
  • getpagesize