这是小小的第五篇,本篇将会着重说明MySql的三大基本日志。
MySql中的日志是MySql数据的重要组成部分,将会记录着数据库运行期间的各种信息,MySql的日志主要分为错误日志,查询日志,慢查询日志,事物日志,二进制日志。小小将会着重介绍二进制日志和事物日志这三种日志。
二进制日志用于记录数据库执行的写入的查询,不包括查询的信息,以二进制的形式保存在磁盘中,其中binlog是MySql的逻辑日志,由Server层记录,任何存储引擎都会记录二进制日志。二进制日志记录的是以下的内容
逻辑日志:可以简单的理解为记录的就是SQL语句。
物理日志:因为MySql 数据最终保存在数据页中,物理日志记录的就是数据页的变更。
其中二进制日志是通过追加的形式进行写入的,通过一个参数可以设置每个二进制日志的文件的大小,达到给定的值以后,生成新的文件,继续保存日志。
输入命令
show variables like 'log_bin';
输入命令
show master logs;
show master status;
在实际应用中,二进制日志主要有两个场景,分别是主从复制和数据恢复。主从复制:再Master端开启Binlog然后再Binlog发送到各个Slave端,Slave端重放binlog达到主从数据的一致性。数据恢复:通过使用mysqlbinlog工具达到数据的恢复。
对于innoDB存储引擎来说,只有在事物提交的时候才会记录biglog此时记录还在内存中,那么biglog什么时候刷到磁盘中呢,这里,通过mysql的sync_binlog参数设置
这个参数设置如下
0:不去强制要求,由系统自行判断何时写入磁盘;
1:每次commit的时候都要将binlog写入磁盘;
N:每N个事务,才会将binlog写入磁盘。
其日志格式有三种,分别为语句的,行的,混合模式的。
每一条都将会忠实的记录。
所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容。它不记录sql语句上下文相关信息,仅保存哪条记录被修改。
两者相互搅在一起。
show binlog events
输出日志的详细信息
show binlog events in 'mysql-bin.000003';
此为Mysql日志中的事物日志,为物理日志,用于记录对数据页的物理修改,二不是某一行,或者是怎么样的,主要用来恢复提交后的物理数据页。
在存储引擎上产生,二进制日志优先记录。
二进制日志本质上是sql语句,而erdo log 是数据库中页的修改。
二进制日志只在每次事物提交的时候一次性写入缓存中的文件,redo log 在数据修改的时候,提交的时候,修改的时候,发生事物的时候,都会进行提交。
二进制日志记录的是事物的提交。
事物日志记录的是物理页的情况,具有相关的幂等性。
这里在操作数据库的时候,按照如下的约定记录日志。
1. 事务开始时,记录START T
2. 事务修改时,记录(T,x,v),说明事务T操作对象x,x的值为v
3. 事务结束时,记录COMMIT T
undo log 是把所有没有commit的事物回滚到事物开始前的状态,当系统崩溃的时候,可以借助undo log 进行回滚。使用undo log 如下
1. 记录修改日志时,(T,x,v)中v为x修改前的值,这样才能借助这条日志来回滚;
2. 事务提交后,必须在事务的所有修改(包括记录的修改日志)都持久化后才能写COMMIT T日志;这样才能保证,宕机恢复时,已经COMMIT的事务的所有修改都已经持久化,不需要回滚。
使用undo log 的时事物执行顺序如下
1. 记录START T
2. 记录需要修改的记录的旧值(要求持久化)
3. 根据事务的需要更新数据库(要求持久化)
4. 记录COMMIT T
进行宕机回滚的操作
1. 扫描日志,找出所有已经START,还没有COMMIT的事务。
2. 针对所有未COMMIT的日志,根据undo log来进行回滚。
redo log是指在回放日志的时候把已经COMMIT的事务重做一遍,对于没有commit的事务按照abort处理,不进行任何操作。
使用redo log时,要求:
1. 记录redo log时,(T,x,v)中的v必须是x修改后的值,否则不能通过redo log来恢复已经COMMIT的事务。
2. 写COMMIT T日志之前,事务的修改不能进行持久化,否则恢复时,对于未COMMIT的操作,可能有数据已经修改,但重放redo log不会对该事务做任何处理,从而不能保证事务的原子性。
使用redo log时事务执行顺序
1. 记录START T
2. 记录事务需要修改记录的新值(要求持久化)
3. 记录COMMIT T(要求持久化)
4. 将事务相关的修改写入数据库
使用redo log重做事务
1. 扫描日志,找到所有已经commit的事物。
2. 对于已经commit的事物,根据redo log重做事物。
在日志中使用checkpoint
1. 在日志中记录checkpoint_start (T1,T2...Tn) (Tx代表做checkpoint时,正在进行还未COMMIT的日志)
2. 将所有已提交的事务的更改进行持久化;
3. 在日志中记录checkpoint_end
根据checkpoint来加速恢复
从后往前,扫描redo log
1. 如果先遇到checkpoint_start,则把T1~Tn以及checkpoint_start之后的所有已经COMMIT的事务进行重做;
2. 如果先遇到checkpoint_end, 则T1~Tn以及前一个checkpoint_start之后所有已经COMMIT的事务进行重做;
这里进行具体的操作顺序为
1. 记录START T
2. 记录修改日志(T,x,v,w)(要求持久化,其中v用于undo,w用于redo)
3. 更新数据库
4. 记录 COMMIT T
处理方式如上
小明菜市场
推荐阅读
● 实战 | GitLab + Docker 实现多环境部署
● 明晰 | Java序列化与反序列化
● 理论 | 三天两夜,万字长文,吃透TCP/IP
● 应用 | Redis实现 主从,单例,集群,哨兵,配置应用
● 实战 | 后端日志的前世今生