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

MySQL数据库的日志

一、概论

日志(log)是一种记录系统运行时各种状态和事件的文件。
它通常用于系统监控、故障排查、安全审计和性能分析。日志文件可以记录用户操作、系统错误、应用程序行为等信息。日志文件通常包含时间戳、事件类型、事件描述等关键信息,以便于事后分析和追踪。

MySQL日志是MySQL数据库管理系统中用于记录数据库操作和系统状态的一系列日志文件。这些日志对于数据库的维护、监控、故障排查、数据恢复和性能优化等方面都非常重要。以下是MySQL中一些关键的日志类型:

  1. 错误日志(Error Log):记录MySQL服务器启动、运行和关闭过程中的错误信息。

  2. 查询日志(General Query Log):记录客户端发送给MySQL服务器的所有请求,但不包括响应结果。

  3. 慢查询日志(Slow Query Log):记录执行时间超过指定阈值的查询,用于性能分析和优化。

  4. 二进制日志(Binary Log):记录所有更改数据库数据的操作,用于数据复制和恢复。

  5. 事务日志(Transaction Log):在支持事务的存储引擎(如InnoDB)中,记录事务的变更,以确保事务的原子性、一致性、隔离性和持久性。

  6. 重做日志(Redo Log):InnoDB存储引擎特有的日志,用于在发生故障时恢复未提交的事务。

  7. 回滚日志(Undo Log):InnoDB存储引擎中用于处理事务回滚的日志。

本文主要介绍MySQL的二进制日志(Binary Log)、重做日志(Redo Log)、回滚日志(Undo Log)

二、回滚日志(Undo Log)

1. 回滚日志的概念与作用

在MySQL中,即使没有显式地使用 BEGIN 和 COMMIT 来开启和提交事务,在执行“增删改”操作时,数据库也会自动开启并提交事务,这样可以确保我们及时在数据库表看到操作”的结果了。

如果事务在未提交前数据库发生崩溃,那么就需要回滚到事务之前的状态。

为了实现事务的回滚,MySQL会在事务执行过程中记录所有必要的回滚信息到回滚日志中。这样,一旦数据库在事务中途崩溃,系统就可以利用这些日志信息将数据恢复到事务开始前的状态,确保数据的一致性和完整性

回滚日志(Undo Log) 是数据库系统中,特别是支持事务的数据库系统中,用于处理事务失败时的回滚操作以及保持事务隔离性的一种日志。

2. 回滚日志回滚的流程

回滚日志记录了事务进行的修改前的数据。当一个事务需要被回滚时,数据库系统可以利用这些日志来回滚到事务开始前的状态。
在这里插入图片描述

在事务回滚过程中,数据库会利用undo log中的信息来执行相反的操作。

对于DELETE操作,undo log会保存被删除记录的原始数据,回滚时则通过这些数据执行INSERT操作以恢复记录。
而对于UPDATE操作,undo log会记录变更前后的数据差异,回滚时则应用这些差异的逆向变化,以撤销更新

一条记录的每一次更新操作产生的 undo log 格式都有一个 roll_pointer 指针 和一个 trx_id 事务id

  • 通过 trx id 可以知道该记录是被哪个事务修改的;
  • 通过 roll_pointer 指针可以将这些 undo log 串成一个链表,这个链表就被称为版本链。

在这里插入图片描述

三、重做日志(Redo Log)

1. 缓冲池(Buffer Pool)

为了提高数据库系统的读写性能,Innodb提供了缓冲池(Buffer Pool)。
缓冲池(Buffer Pool)通过在内存中缓存频繁访问的数据页,减少了对磁盘的直接I/O操作,从而加快了数据的访问速度。

通过Buffer Pool后操作数据的流程:

  • 当读取数据时,如果数据存在于 Buffer Pool 中,客户端就会直接读取 Buffer Pool 中的数据,否则再去磁盘中读取。
  • 当修改数据时,如果数据存在于 Buffer Pool中,那直接修改 Buffer Pool 中数据所在的页,然后将其页设置为脏页(该页的内存数据和磁盘上的数据已经不一致),为了减少磁盘I/O,不会立即将脏页写入磁盘,后续由后台线程选择一个合适的时机将脏页写入到磁盘。

2. 重做日志

Buffer Pool 是基于内存的,为了防止Buffer Pool 中的数据断电后丢失,InnoDB 需要对Buffer Pool的数据做一些处理。

重做日志(Redo Log)是一种记录数据库中所有修改操作的日志,它记录了事务中对数据页的修改。当事务提交时,这些修改操作首先被写入重做日志中,然后才被写入到数据文件中。

重做日志(Redo Log)确保事务即使在数据库崩溃后也能被恢复,保证了数据的完整性。

3. 重做日志持久化的流程

(1)重做日志的工作流程

当InnoDB存储引擎需要更新一条记录时,它会先将这条记录的数据加载到 Buffer Pool 中。紧接着,InnoDB会将这次更新操作记录到重做日志(Redo Log)中,以确保事务的持久性和在系统崩溃时能够恢复数据。

最终InnoDB并不会立即将Buffer Pool中的修改同步到磁盘上,而是通过后台线程,在合适的时机将Buffer Pool中标记为“脏”(即已修改)的数据页刷新回磁盘,这个过程称为刷盘

这种将日志写入作为数据写入的先决条件的做法,就是WAL(Write-Ahead Logging)技术。
WAL是一种日志先行的策略,它要求在数据实际写入磁盘之前先写入相关的日志。通过这种方式,当系统发生故障时,重做日志可以用于恢复那些已经记录在日志中但尚未写入磁盘的数据,从而保证确保即使在系统发生故障时,数据也不会丢失,维护数据的完整性和一致性。

使用 redo log 相比于直接写入磁盘的优势:
写入 redo log 的方式使用了追加操作, 所以磁盘操作是顺序写,而写入数据需要先找到写入位置,然后才写到磁盘,所以磁盘操作是随机写。磁盘的顺序写比随机写高效,因此 redo log 写入磁盘的开销更小。

在事务执行过程中生成的重做日志(redo log)并不会直接写入磁盘,因为频繁的磁盘 I/O 操作会大大降低性能。重做日志使用重做日志缓冲区(redo log buffer) 作为自己的缓冲区。

每当事务产生新的重做日志条目时,这些条目会首先被存储到重做日志缓冲区中。随后,这些日志条目会在适当的时机被批量写入到磁盘上的重做日志文件中,这个过程称为持久化。
在这里插入图片描述
InnoDB存储引擎通过这种方式有效减少了对磁盘的直接写入次数,从而提高了整体的性能。

(2)刷盘

InnoDB存储引擎在处理事务时,会将重做日志(redo log)写入到redo log buffer中,然后根据特定的时机和策略将这些日志持久化到磁盘。

刷盘时机:

  1. MySQL正常关闭:当MySQL服务器正常关闭时,会触发将redo log buffer中的内容刷写到磁盘的操作。
  2. redo log buffer写入量:如果redo log buffer中的记录量超过其内存空间的一半,系统会自动触发刷盘操作。
  3. 后台线程周期性刷盘:InnoDB的后台线程会每隔1秒钟将redo log buffer中的内容持久化到磁盘,以确保数据的安全性。
  4. 事务提交:每次事务提交时都将缓存在 redo log buffer 里的 redo log 直接持久化到磁盘(3种策略)

刷盘策略:
InnoDB提供了三种不同的刷盘策略,这些策略由innodb_flush_log_at_trx_commit参数控制,默认值为1。以下是三种策略的具体描述:

  1. 参数值为0:在此设置下,事务提交时不会将redo log buffer中的内容主动写入磁盘。随后操作系统通过调用通过调用 write() 后台线程写到操作系统的 Page Cache ,在通过 fsync() 后台线程,将缓存在操作系统中 Page Cache 里的 redo log 持久化到磁盘。
    这种模式下,系统会减少磁盘I/O操作,但牺牲了数据的持久性,因为如果发生异常重启,可能会丢失最近提交的事务数据。

  2. 参数值为1:这是默认设置,表示每次事务提交时,都会将redo log buffer中的内容直接持久化到磁盘。
    这种策略确保了即使在MySQL异常重启后,数据也不会丢失,因为它保证了事务日志的持久性。

  3. 参数值为2:在此设置下,每次事务提交时,只是将redo log buffer中的内容写入到redo log文件中,但并不保证这些内容立即写入磁盘。操作系统的文件系统可能会将这些数据缓存在page cache中。随后操作系统通过调用 fsync() 后台线程,将缓存在操作系统中 Page Cache 里的 redo log 持久化到磁盘。
    这种策略数据的持久性不如参数值为1的设置,但可以减少磁盘I/O操作,提高性能。

通过调整innodb_flush_log_at_trx_commit参数,可以根据实际需求在数据安全性和性能之间做出权衡。

四、二进制日志(Binary Log)

1. 二进制日志的概念与作用

二进制日志(Binary Log,bin log)文件是记录了所有数据库表结构变更和表数据修改的日志,并以二进制形式存储在磁盘上。二进制日志不会记录查询类的操作,比如 SELECT 和 SHOW 操作。

binlog 用于备份恢复与主从复制等操作。

2. 二进制日志主从复制的流程

MySQL的主从复制机制依赖于binlog,这是一种记录数据库所有变更并以二进制形式存储在磁盘上的日志。复制过程本质上是将binlog中的数据从主服务器传输到从服务器。

以下是复制过程的具体步骤:

  1. 写入 bin log:当MySQL主服务器接收到客户端提交事务的请求时,它会首先将变更记录到 bin log 中,然后提交事务并更新存储引擎中的数据。一旦事务提交完成,主服务器就会向客户端返回“操作成功”的响应。

  2. 同步 bin log:从服务器会启动一个专门的 I/O 线程,该线程负责连接到主服务器的 log dump 线程,并接收主服务器的 bin log 日志。接收到的 bin log 日志随后被写入到 relay log 中继日志中,并发送“复制成功”的响应回主服务器。

  3. 回放 bin log:从服务器还会启动一个用于处理binlog的线程,这个线程负责读取 relay log 中继日志,并执行日志中的操作来更新存储引擎中的数据。这一步骤确保了主从服务器之间的数据一致性。

这个过程通常是异步进行的,意味着主服务器上执行事务操作的线程不会等待binlog复制线程完成同步。这样的设计允许主服务器继续处理新的事务请求,而不会因为复制操作而产生延迟。
在这里插入图片描述

五、两阶段提交(Two-Phase Commit)

1. 两阶段提交的作用

事务提交后,redo log 和 binlog 都要持久化到磁盘,但是这两个是独立的逻辑,可能出现半成功的状态,即两个日志持久化只要完成了其中一个,这样就造成两份日志之间的逻辑不一致。

如果更新某条记录时:

  • redo log 已经写入并持久化到磁盘,此时数据库发生故障,bin log 没有写入磁盘,进入了半成功的状态。数据库重启后,主库中的数据根据 redo log会恢复为更新后的状态,但由于bin log没有成功写入,从库在复制数据时会缺少这次更新,导致从库中的数据仍然是旧的状态。这就引起了主库和从库数据不一致的问题。
  • bin log 已经写入并持久化到磁盘,此时数据库发生故障,redo log 没有写入磁盘,进入了半成功的状态。数据库重启后,主库中的数据是旧的状态,但由于 bin log 已经写入,从库在复制数据时会变为更新后的数据。这就引起了主库和从库数据不一致的问题。

为了保证这两个日志之间的逻辑一致性,防止出现半成功的事务状态,MySQL采用了两阶段提交(Two-Phase Commit) 机制。这种机制确保了在事务提交过程中,redo log 和 bin log 要么都成功,要么都失败,从而避免了数据不一致的问题。

两阶段提交把单个事务的提交拆分成了2个阶段,分别是准备(Prepare)阶段提交(Commit)阶段,每个阶段都由协调者(Coordinator)参与者(Participant) 共同完成。

2. 两阶段提交的过程

在MySQL的InnoDB存储引擎中,当启用binlog功能时,系统会同时维护 bin log 日志和InnoDB的redo log以确保事务的持久性和数据的一致性。为了协调这两个日志,MySQL采用了内部XA事务模型,其中binlog扮演协调者的角色,而存储引擎则是参与者。

当客户端执行commit语句或在自动提交模式下,MySQL内部会启动一个XA事务,并分两个阶段完成提交:

  1. 准备(Prepare)阶段:MySQL会将内部XA事务的ID(XID)记录到 redo log 中,并将该事务的redo log状态标记为准备(prepared)。随后,系统会将 redo log 持久化到磁盘。

  2. 提交(Commit)阶段:MySQL 首先将XID写入到 bin log中,并将 bin log 持久化到磁盘。然后,MySQL 调用存储引擎的提交事务接口,将 redo log的状态从准备更改为提交(committed)。这一状态变更不需要再次持久化到磁盘,只需写入到文件系统的 page cache 中即可。这是因为只要 bin log 已经成功写入磁盘,即使 redo log 的状态仍显示为准备,事务也被认为是成功执行的。

通过这种两阶段提交协议,MySQL确保了在发生故障时,binlog和redo log能够保持一致,从而维护了数据的完整性和一致性。


http://www.kler.cn/a/463375.html

相关文章:

  • HTML——73.button按钮
  • 《计算机网络A》单选题-复习题库
  • DC-2 靶场渗透
  • AWS EMR基础知识
  • lec5-传输层原理与技术
  • OFDM学习-(二)长短序列和PPDU整体数据处理流程
  • typora+picgo core+minio自动上传图片
  • SqlSession的线程安全问题源码分析
  • 2025.01.01(IO模型分类,超时检测,抓包分析,机械臂客户端)
  • Python软体中在AWS Lambda上部署Python应用:一站式部署指南
  • QT---------QT框架功能概述
  • SQL Server详细使用教程(包含启动SQL server服务、建立数据库、建表的详细操作) 非常适合初学者
  • Go小技巧易错点100例(二十)
  • 解决Springboot整合Shiro+Redis退出登录后不清除缓存
  • 安卓入门八 常用网络协议一
  • ArkTs语法学习
  • ChatGPT 是通用人工智能吗
  • Linux Ubuntu24配置安装Java
  • 无人机丢失信号处理方式!
  • Transformer--Decoder
  • Mysql学习笔记之约束
  • 网络安全课程
  • JVM学习:CMS和G1收集器浅析
  • PHP Fatal error: Uncaught com_exception: Source:Kingsoft WPS Description:文档打开失败
  • 【AI日记】25.01.01 秦制两千年
  • ubuntu20.04 中文输入法安装