Mysql-日志篇

一.日志篇

该篇所提到的日志用途实际上用于数据更新方面(insert、update、delete)

  • undo log(回滚日志):Innodb存储引擎生成的日志,用于事务回滚
  • redo log(重做日志):Inoodb存储引擎生成的日志,用于掉电等故障恢复
  • binlog(归档日志):Service层生成的日志,用于数据备份和主从复制

1.1 为什么需要undo log?

以下提到数据更新完是指事务已经提交成功

在进行事务执行后,存储引擎会将更新前的数据记录到undo log中。

当事务回滚时,insert事务会将新增的数据删除,delete事务会将删除的数据恢复,update事务会将数据更新为旧值。

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

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

image-20230308124330718

回滚时需要的数据旧样就是通过这个指针来定位的。

1.2 为什么需要binlog?

binlog文件记录了所有数据库的表结构变更表数据修改的日志,但其不会记录查询类的操作。

MySQL的binlog是逻辑日志,其记录是对应的SQL语句

在完成一条sql更新操作后,Server层会生成一条对应操作的binlog,等到事务提交后将所有binlog统一写入binlog文件。

主从复制的具体详细过程如下:

  • MySQL 主库在收到客户端提交事务的请求之后,会先写入 binlog,再提交事务,更新存储引擎中的数据,事务提交完成后,返回给客户端“操作成功”的响应。
  • 从库会创建一个专门的 I/O 线程,连接主库的 log dump 线程,来接收主库的 binlog 日志,再把 binlog 信息写入 relay log 的中继日志里,再返回给主库“复制成功”的响应。
  • 从库会创建一个用于回放 binlog 的线程,去读 relay log 中继日志,然后回放 binlog 更新存储引擎中的数据,最终实现主从的数据一致性。

1.3 为什么需要 redo log ?

在了解redo log之前我们需要先了解什么时WAL技术?

WAL (WriteAhead Logging)技术指的是, MySQL 的写操作并不是立刻写到磁盘上,而是先写日志,然后在合适的时间再写到磁盘上。

不然数据量一大,每次写操作都需要先在数据海中查找到需要修改的数据,这未免太消耗性能了。

redo物理日志,保存了数据库中的值,每当执行一个事务就会产生一条或者多条物理日志。

当系统崩溃时, redo log 已经持久化,接着 MySQL 重启后,可以根据 redo log 的内容,将所有数据恢复到最新的状态。

但需要注意的是,redo log的大小是固定的,通过循环写入,也就是说,在写入到内存不够时,会将前面写入数据刷掉重写新的数据。而binlog是追加写,写到一定大小后会切换到下一个,并不会覆盖以前的日志。

redo log 和 undo log 区别在哪?

这两种日志是属于 InnoDB 存储引擎的日志,它们的区别在于:

  • redo log 记录了此次事务「完成后」的数据状态,记录的是更新之后的值;
  • undo log 记录了此次事务「开始前」的数据状态,记录的是更新之前的值;

事务提交之前发生了崩溃,重启后会通过 undo log 回滚事务,事务提交之后发生了崩溃,重启后会通过 redo log 恢复事务

1.4 为什么需要两阶段提交?

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

MySQL 为了避免出现两份日志之间的逻辑不一致的问题,使用了「两阶段提交」来解决,两阶段提交其实是分布式事务一致性协议,它可以保证多个逻辑操作要不全部成功,要不全部失败,不会出现半成功的状态。

以下是两阶段的过程:

  • prepare 阶段:将 XID(内部 XA 事务的 ID) 写入到 redo log,同时将 redo log 对应的事务状态设置为 prepare,然后将 redo log 持久化到磁盘(innodb_flush_log_at_trx_commit = 1 的作用);
  • commit 阶段:把 XID 写入到 binlog,然后将 binlog 持久化到磁盘(sync_binlog = 1 的作用),接着调用引擎的提交事务接口,将 redo log 状态设置为 commit,此时该状态并不需要持久化到磁盘,只需要 write 到文件系统的 page cache 中就够了,因为只要 binlog 写磁盘成功,就算 redo log 的状态还是 prepare 也没有关系,一样会被认为事务已经执行成功;

1.5 为什么有了binlog还要redo log?

前面也提到了binlog文件存储是所有执行过的sql语句,主要用来主从复制,实现的一个数据库的备份。

redo log记录了事务提交后的数据(在某个数据页上进行了什么样的修改),用于mysql崩溃后能够恢复到崩溃前的状态,也就是crash-safe(崩溃恢复)能力。

最开始MySQL里并没有InnoDB引擎。MySQL自带的引擎是MyISAM,但是MyISAM没有 crash-safe的能力,binlog日志只能用于归档。而InnoDB是另一个公司以插件形式引入MySQL 的,既然只依靠binlog是没有crash-safe能力的,所以InnoDB使用另外一套日志系统— — 也就是 redo log来实现crash-safe能力。


  转载请注明: 流浪秃球计划 Mysql-日志篇

 上一篇
输入网址到显示网页的过程 输入网址到显示网页的过程
1.HTTP输入一个网址,网址首先会被浏览器解析,得到该网址的网络协议(如http、https)、域名(www.baidu,com)、请求路径(../dir/index.html) 对网址解析后,就会生成对应的请求报文 请求行:包括res
2023-03-21
下一篇 
JVM JVM
一.JVM内存结构1.程序计数器 (Program Counter Register) 作用:记录下一条JVM指令的地址 Java源代码进行编译会被转化为二进制字节码(JVM指令) 虚拟机中的解释器负责把从程序计数器中得到的JVM指令
2023-01-30
  目录