mysql日志

MySQL 日志 主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其中,比较重要的还要属二进制日志 binlog(归档日志)和事务日志 redo log(重做日志)和 undo log(回滚日志)

一、redo log

1、用法

innodb独有的日志,一旦mysql主节点发生重启,innodb就会根据redo log来恢复数据,保证数据的持久性与完整性。

从节点或备节点是通过同步主节点的binlog来完成数据恢复的。

MySQL 中数据是以页为单位,在有缓存机制的mysql版本中,查询是会从磁盘中读取一个数据页放入buffer pool中,命中就直接返回

在写入数据时,先更新buffer pool,再把“在某个数据页上做了什么修改”写入redo log,然后刷盘到redolog文件中,这与redis的AOF日志简直一模一样

2、刷盘时机

(1)事务提交时

(2)log buffer 空间不足时

(3)事务日志缓冲区满:InnoDB 使用一个事务日志缓冲区(transaction log buffer)来暂时存储事务的重做日志条目。当缓冲区满时,会触发日志的刷新,将日志写入磁盘。

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

(5)后台刷新线程:InnoDB 启动了一个后台线程,负责周期性(每隔 1 秒)地将脏页(已修改但尚未写入磁盘的数据页)刷新到磁盘,并将相关的重做日志一同刷新。

(6)正常关闭服务器:MySQL 关闭的时候,redo log 都会刷入到磁盘里去。

可以通过参数innodb_flush_log_at_trx_commit来设置刷盘时机

(1)innodb_flush_log_at_trx_commit=0:表示每次事务提交时不进行刷盘操作。这种方式性能最高,但是也最不安全,因为如果 MySQL 挂了或宕机了,可能会丢失最近 1 秒内的事务(因为后台线程每1秒刷新一次)。

(2)innodb_flush_log_at_trx_commit=1(默认):表示每次事务提交时都将进行刷盘操作。这种方式性能最低,但是也最安全,因为只要事务提交成功,redo log 记录就一定在磁盘里,不会有任何数据丢失。

(3)innodb_flush_log_at_trx_commit=2:表示每次事务提交时都只把 log buffer 里的 redo log 内容写入 page cache(文件系统缓存)。page cache 是专门用来缓存文件的,这里被缓存的文件就是 redo log 文件。这种方式的性能和安全性都介于前两者中间。

image.png

3、日志文件组

redo log 日志文件不只一个,而是以一个日志文件组的形式出现的,每个的redo日志文件大小都是一样的。

假设有4个日志文件,每个文件1G,

它采用的是环形数组形式,从头开始写,写到末尾又回到头循环写

image.png

两个重要参数:

write pos 是当前记录的位置,一边写一边后移

checkpoint 是当前要擦除的位置,也是往后推移

每次刷盘 redo log 记录到日志文件组中,write pos 位置就会后移更新。

每次 MySQL 加载日志文件组恢复数据时,会清空加载过的 redo log 记录,并把 checkpoint 后移更新。

write pos 追上 checkpoint时,表示日志文件组满了,这时候不能再写入新的 redo log 记录,MySQL 会清空一些记录,把 checkpoint 推进一下

MySQL 8.0.30 之前可以通过 innodb_log_files_in_group 和 innodb_log_file_size 配置日志文件组的文件数和文件大小,之后就是固定的32个文件,这两个参数相乘得到文件组总容量innodb_redo_log_capacity,每个文件容量就是innodb_redo_log_capacity/32

二、binlog

1、作用

redo log 它是物理日志,记录内容是“在某个数据页上做了什么修改”,属于 InnoDB 存储引擎。

而 binlog 是逻辑日志,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”,属于MySQL Server 层。

MySQL 数据库的数据备份、主备、主主、主从都离不开 binlog,需要依靠 binlog 来同步数据,保证数据一致性

image.png

2、记录格式

binlog_format参数指定三种记录格式:statement、row、mixed

指定statement,记录的内容是SQL语句原文,比如执行一条update T set update_time=now() where id=1,记录的内容如下

image.png

同步数据时,会执行记录的SQL语句,但是有个问题,update_time=now()这里会获取当前系统时间,直接执行会导致与原库的数据不一致

所以需要指定为row,记录的内容不再是简单的SQL语句了,还包含操作的具体数据,记录内容如下

image.png

row格式记录的内容看不到详细信息,要通过mysqlbinlog工具解析出来

但是这种格式,需要更大的容量来记录,比较占用空间,恢复与同步时会更消耗 IO 资源,影响执行速度。所以就有了一种折中的方案,指定为mixed,记录的内容是前两者的混合。MySQL 会判断这条SQL语句是否可能引起数据不一致,如果是,就用row格式,否则就用statement格式。

3、写入时机

事务执行过程中,先把日志写到binlog cache,事务提交的时候,再把binlog cache写到 binlog 文件中

刷盘时机也和redo log差不多,只是最后2可以改为N,表示N个事务执行完后,一把刷盘

4、两阶段提交事务

在执行更新语句过程,会记录 redo log 与 binlog 两块日志,以基本的事务为单位,redo log 在事务执行过程中可以不断写入,而 binlog 只有在提交事务时才写入,所以 redo log 与 binlog 的写入时机不一样。

image.png

写入binlog时发生异常,redo log的数据和binlog的数据就会不一致

image.png

为了解决两份日志之间的逻辑一致问题,InnoDB 存储引擎使用两阶段提交方案。

原理很简单,将 redo log 的写入拆成了两个步骤prepare和commit,这就是两阶段提交。

image.png

使用两阶段提交后,写入 binlog 时发生异常也不会有影响,因为 MySQL 根据 redo log 日志恢复数据时,redo log有数据,binlog没数据,但redo log还处于prepare阶段,就会回滚该事务。

即便redolog在提交阶段出现问题,MySQL 根据 redo log 日志恢复数据时,redo log有数据,binlog也有数据,那不管redo log时prepare还是commit,都会恢复该数据

三、undo log

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

### 配置和查看 MySQL 日志文件 #### 一、配置 MySQL 日志输出方式 为了控制日志记录的位置,可以通过设置`log_output`参数来决定是将日志存储于文件还是表格内。当设定为`FILE`时,默认会把日志保存成物理文件形式;而如果指定为`TABLE`,则意味着慢查询等类型的日志会被录入至特定的数据表中,比如`mysql.general_log`或是`mysql.slow_log`[^2]。 ```sql SET GLOBAL log_output = 'TABLE'; -- 或者 SET GLOBAL log_output = 'FILE'; ``` #### 二、启用不同种类的日志功能 对于想要开启诸如错误日志(Error Log),通用查询日志(General Query Log), 慢查询日志(Slow Query Log)等功能来说,在my.cnf(my.ini Windows环境下)这样的全局配置文档里添加相应的指令即可实现目的。例如要激活慢查询日志并定义其阈值时间: ```ini slow_query_log=ON long_query_time=2 ``` 上述配置使得超过两秒未完成的操作才会被视作“缓慢”,进而触发记录过程。 #### 三、定位及读取日志数据 一旦完成了必要的前期准备工作之后,就可以着手去访问这些宝贵的诊断资料了。如果是基于文件系统的日志,则可以直接利用Linux自带工具如cat,tail,follow等方式实时监控最新动态变化情况: ```bash tail -f /path/to/mysql/error.log ``` 而对于那些已经转化为关系型结构体存在的历史档案而言,借助SQL语句同样可以轻松获取所需信息片段: ```sql SELECT * FROM mysql.slow_log WHERE start_time >= NOW() - INTERVAL 1 DAY; ``` 此命令能够筛选出过去一天内的所有低效请求实例。 #### 四、管理日志文件大小 考虑到长期积累下来可能会占用过多磁盘空间资源的问题,适时清理不再需要的历史版本就显得尤为重要。针对Binlog这类特殊的复制机制专属产物,可通过如下操作达到瘦身效果——即移除编号低于某个给定数值之前的全部条目集合[^3]: ```sql PURGE BINARY LOGS TO 'mysql-bin.000003'; ``` 另外一种更为激进的做法就是直接重置整个序列号计数器回到起点位置: ```sql RESET MASTER; ``` 这将会使所有的旧有变更记录彻底消失不见,只保留当前时刻作为新的起始点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值