ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MySQL中的Binlog和Redo log

2022-07-20 20:38:30  阅读:182  来源: 互联网

标签:bin Binlog log 数据 redo 写入 磁盘 Redo


为什么要有redo log

一般当MySQL更新数据时,有两种情况,追加数据或定位到已经存在的一条数据进行修改。

然而磁盘随机读写速度很慢,无法满足高IO操作的场景。

为了提高写入效率,一般我们可以先将数据写入内存,空闲时再批量刷入磁盘。

但是这样就产生了一个问题:内存中的数据不是持久化的,如果掉电,数据就会丢失。

为了解决数据丢失的问题,MySQL引入了redo log来解决这个问题。

这被称为WAL(Write-Ahead Logging)技术,对于非内存数据库,这是一种提高IO效率的常见做法。

通过WAL技术,使得在发生崩溃时依靠日志记录,就可以恢复数据,从而确保数据不丢失。

关于WAL(Write-Ahead Logging)

对于非内存数据库,磁盘I/O操作是导致数据库性能低下的主要原因。

在数据量相同的情况下,使用WAL日志的数据库系统,可以成倍减少磁盘写入操作,大大提高了数据库磁盘I/O操作的效率,从而提高了数据库性能。

WAL的优势

  • 读取和写入可以完全并发执行而不会相互阻塞(但写入仍然不能相互并发)。
  • WAL在大多数情况下具有更好的性能(因为不需要每次写入两个文件)。
  • 磁盘I/O行为更具可预测性。
  • 减少刷盘fsync()操作,提高系统健壮性。

redo log的实现

当需要更新记录时,InnoDB引擎先写redo log并更新内存。在适当的时候,例如当磁盘空闲时,将redo log数据刷新到磁盘。

在InnoDB引擎中,redo log的大小是固定的,例如,它可以配置为一组四个文件,每个文件大小为1GB,因此总共可以记录4GB的操作。

write pos用于记录当前位置,在写入时移动,注意是循环移动的。

checkpoint用于标记要擦除的位置,在擦除时往后移动,注意也是循环移动的。

记录在被擦除之前会更新到磁盘数据文件。

如果write pos完成最后一个文件的写入,它将移动到ib-log-file-0并再次开始写入。

如果write pos赶上check point,则表示redo log已满,因此无法执行新的更新,必须停止并擦除一些数据,将数据同步到磁盘,然后再继续以上步骤。

如何查看redo log 配置参数

每个InnoDB存储引擎至少有一个重做日志文件组,每个文件组至少有两个重做日志文件,默认为ib-log-file-0和ib-log-file-1。

可使用以下命令查看参数配置信息:

show variables like '%innodb_log%';

关于binlog

redo log是InnoDB引擎特有的,可以记录数据,并保证数据的安全性,那么其它存储引擎如何记录数据呢?

在Server级别,MySQL有自己的日志,即bin-log(归档日志)。了解MySQL逻辑架构的同学应该知道,Mysql不是一个整体,MySQL = Server层 + 不同的数据存储引擎。

Binlog用于记录MySQL数据库表结构和表数据的所有变更操作,但不包括select和show查询操作。bin-log以事件的形式记录下来,包括语句消耗的时间。

Binlog日志最重要的两个使用场景如下:

  • 主从复制:在主库开启Binlog功能,使主库可以将Binlog传递给从库,从库获取Binlog并实现数据恢复,实现主从数据一致性。

  • 数据恢复:通过mysqlbinlog工具恢复数据.

Bin-log文件以三种模式记录:statement, row和mixed, 通常使用row模式。

为什么有两个日志?

MySQL一开始没有InnoDB引擎,MySQL自带的引擎是MyISAM,但是MyISAM没有处理崩溃恢复数据的能力,bin-log日志只是用来归档。

InnoDB后来作为插件添加,它实现了自己的日志系统来保护数据,防止崩溃丢失数据问题。

bin log和redo log的区别

  • 内容不同:redo log是物理日志,记录的是数据页修改逻辑,bin-log内容是二进制的,取决于 binlog_format参数,可能基于SQL语句、数据本身或两者的混合。

  • 不同级别:redo log只能和InnoDB引擎一起使用,而bin-log位于MySQL服务器级别,可用于所有引擎。

  • 磁盘存储形式不同:redo log循环写入,bin-log是累积追加的,所以可以用于数据恢复或者主备同步

  • 写入的时间不同:bin-log通常在一个事务提交时写入,而redo log会在不同的时间点写入,如每次事务提交时,通过另一个线程事务执行,或在刷盘时写入。(注意:未提交的事务redo log也可能被刷新到磁盘)

  • 作用不同:redo log用于crash恢复,保证MySQL宕机不丢失数据;bin-log用于指定时间点恢复数据,保证服务器可以根据时间点恢复数据,另外bin-log也用于主从复制。

两阶段提交

由于redo-log是在InnoDB层,而bin-log是在 Server 层,这样就引入了一个新的问题。

如果redo log写入成功,但是在bin-log写入磁盘之前,程序crash了,说明事务还没有提交,所以redo-log里写入的新数据是无效的。

重新启动数据库进行数据恢复会将redo-log数据恢复到磁盘,从而创建无效数据。

为了解决这个问题,引入了两阶段提交。

在第一阶段,redo-log写入并处于准备状态。Server层将bin-log数据保存到磁盘,然后执行器调用引擎的提交事务接口提交事务,把redo-log变更为已提交状态,更新完成。

通过两阶段提交协议保证了redo-log数据和bin-log数据的一致性。

一条更新语句的执行过程

学习完全面的知识后,我们就可以探索一下update语句在MySQL中是如何执行的。

假设我们现在要执行SQL:

update table_test set a = a+1 where id = 2;

首先,客户端通过连接器连接并确定权限。

验证后,SQL会经过解析器进行词法和语法分析(AST),如果是Update语句,MySQL将清除查询表的所有查询缓存table_test。(一般不建议开启查询缓存,通常会影响性能)。

优化器优化经过验证的SQL,匹配id索引,并生成执行计划。

执行器获取最终的SQL,并调用相应存储引擎的接口开始执行该更新SQL。

InnoDB引擎打开一个事务,执行引擎首先从内存中查询是否有数据id=2,如果匹配则设置对应的数据为field+1,然后将其保存到内存中。

如果内存中没有查询到id=2的数据,那么它将以页的形式加载磁盘中的数据到内存,然后更新并保存到内存中。

然后InnoDB引擎会将数据行保存到redo-log,此时处于准备状态,表示已经准备好可以提交事务了。

执行器将生成相应的bin-log并将其写入磁盘。

事务被提交,然后redo-log也被提交。

这样事务就执行完成了。

标签:bin,Binlog,log,数据,redo,写入,磁盘,Redo
来源: https://www.cnblogs.com/chenpi/p/16499724.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有