RedoLog是重要日志,是InnoDB用来做事务持久化的日志。他主要记录了事务在某个数据页上具体做了什么。它可以实现事务的crash-safe
他的大致结构:
show engine innodb status\G
---
LOG
---
Log sequence number 17680223 #代表系统中的lsn值,也就是当前系统已经写入的redo日志量
Log buffer assigned up to 17680223
Log buffer completed up to 17680223
Log written up to 17680223
Log flushed up to 17680223 #代表flushed_to_disk_lsn的值,也就是当前系统已经写入磁盘的redo日志量
Added dirty pages up to 17680223
Pages flushed up to 17680223 #代表flush链表中被最早修改的那个页面对应的oldest_modification属性值
Last checkpoint at 17680223 #checkpoint 的值
16 log i/o's done, 0.00 log i/o's/second
RedoLog Buffer的block由三部分组成:header(12字节),body(496字节),trailer(字节)。多个block组成了RedoLog Buffer。他的大小可以由innodb_log_buffer_size的大小来控制,默认时16M。
正常情况下,一个事务产生的RedoLog要先写入到RedoLog Buffer中,直到事务COMMIT才会被写入到磁盘中。多个事务产生的RedoLog也不是顺序存储的,而是随机存储的。他刷盘的策略有:
关于RedoLog的一些配置:
RedoLog并没有参与到正常流程下的数据落盘的过程。这个问题涉及到RedoLog究竟存了些什么。
实际上,数据最终落库是以一页数据为单位进行写入磁盘的,RedoLog本身并没有记录一页完整的数据,而是记录了一页上面的数据都发生了什么变化。因此不能实现写入磁盘的功能。
innodb_flush_logs_at_trx_commit 的作用
BinLog 是服务层的日志,相对而言实现起来比较简单,他不能提供crash-safe的功能。、
BinLog 的写入逻辑比较简单:事务执行过程中,先把日志写到 binlog cache,事务提交的时候,再把 binlog cache 写到 BinLog文件中。
一个事务的 BinLog是不能被拆开的,因此不论这个事务多大,也要确保一次性写入。
这就涉及到了 binlog cache 的保存问题:
参数 sync_binlog 控制的:
BinLog 落进文件分成两步:
回滚日志也是InnoDB实现的,目的是为了进行事务回滚,只要用在MVCC的时候。在数据修改的流程中,会记录一条与当前操作相反的逻辑日志到UndoLog中(可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录)。
WAL 的全称是 Write-Ahead Logging,它的关键点就是先写日志,再写磁盘。具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。
关键点:将写入拆分为多步,先写日志,空闲时间再写磁盘,提高写效率。
update user set a = 1 where b =2;
以一条更新语句为例,修改并不会直接写入这行数据所在的数据库文件(在硬盘中)。而是先写入到redolog日志。会有其他线程把redolog 的日志写入到硬盘中。当我们执行完这条语句,此时对于这条数据的修改,没有直接刷进其所在的数据页,他现在存在两个地方:change buffer (内存)和redo_log(磁盘) 中。当我们下一次查询的时候会先读change buffer 中的变动,对数据做merge。如果服务挂了,内存没有了,服务再次启动时,会先把redo_log 中的变动更新到数据库文件中,此时数据依然是修改后的状态。这个过程叫做:crash-safe。
第一,为了提高写入磁盘的效率;第二,提高并发。
数据库最大的性能瓶颈在于磁盘IO效率。充分利用磁盘IO,提高效率基本上有三个方法:
两阶段提交是分布式系统中比较常见的一种事务提交算法。在Innodb的日志提交时用到了这个协议,用来保证事务提交时,redolog和binlog 都处于完成状态。具体而言:
这里可以仔细推敲下,异常无论发生在1和2 之间还是其他之间,都可以保证下次恢复现场时数据的完整性。因为只有BinLog和RedoLog都存在的事务操作记录才是正确的。
两阶段提交我们在自己的服务开发中也有可能会使用到,这里还有维基-三阶段提交可以参考下
首先要先说明白,他们两个在目前InnoDB中是缺一不可的。少了哪一个都会出现问题。其次,他们之间至少有三点有很大的区别:
最后,简单说下:如果没有了RedoLog,数据就无法做到crash-safe,因为 binlog不具备保存事务的性质,最重要的是它并不具备记录数据页上究竟发生了什么。如果没有 binlog的话,RedoLog是个循环写入的,不存在归档这个功能。
我们先说下,如果没有RedoLog的话,数据怎么就丢了。假设,我们执行完一个事务,更新了一条数据。根据之前的笔记,这时候这条数据所在的数据页 一定保存在内存中,且是一个脏页,并没有被回写到磁盘里。此时的数据是不安全的,假如Mysql异常挂掉了,内存中的数据就没了。这个时候我们的更新就会丢掉。
加上RedoLog以后,我们执行完事务,此时就直接把操作记录保存在RedoLog中,并且已经被保存进磁盘了。事务提交后,RedoLog也就处在完成状态了。这个时候的状态是:虽然我们改过的数据还在内存中,没有刷盘,但是我们操作记录已经写进日志并持久化了。当出现异常后,虽然内存没了,但是服务启动后可以根据RedoLog恢复现场,这样就不会出现数据丢失了。
它们有一个共同的数据字段,叫 XID。崩溃恢复的时候,会按顺序扫描 RedoLog:
当两个参数设置为双1的时候,写入性能最差,sync_binlog=N (N>1 ) innodb_flush_log_at_trx_commit=2 时,MySQL的写操作才能达到最高性能。
MySQL :: MySQL 8.0 Reference Manual :: 15.6.5 Redo Log
Mysql中的Redo Log解析(一) - 云+社区 - 腾讯云
Mysql中的Redo Log解析(二) - 云+社区 - 腾讯云
MySQL中的Redo Log(三) - 云+社区 - 腾讯云
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。