MySQL-15:日志系统

15.1 binlog

binlog的作用:

binlog是MySQL serve 层的日志,任何引擎都可以使用。

binlog(归档日志)是以二进制形式保存语句的原始逻辑的,如果单纯依靠binlog,数据库是不具有crash-safe能力的,binlog日志仅仅用于归档,用于日后的数据备份使用。

binlog有两种记录模式,①statement模式:记录的内容是sql语句;②row模式:记录更新前后行的内容,共两条,所以binlog也叫做逻辑日志。

那binlog是以二进制文件的方式保存,那如何查看binlog文件?

  1. 开启二进制文件,默认为关闭状态,可以show variables like 'log_bin'来进行查看。
  2. 使用sql查看二进制文件

sql命令查看binlog文件传送门

下面是在statement模式下,我们能直观发现日志记录的内容为某表执行某sql语句
在这里插入图片描述

binlog是追加写的,一个文件写到一定大小,就切换下个文件继续写,并不会覆盖以前的日志。

15.2 redo log

redo log的作用:

redo log(重做日志)是属于InnoDB引擎层的日志。

当MySQL进行数据更新操作(insert,update,delete)时,并不会直接更新到磁盘上,而是先写在redo log上,再对内存中的数据进行更新,便算是完成更新操作了,这个技术或者思想叫做WAL:先写日志,后写磁盘

redo log会在合适的时候将日志中记录的操作一起写到磁盘,,这里从随机IO变成了顺序IO,也减少了IO成本。redo log记录的是这个页面做出了什么改动,例如记录某个表的某个字段从1变成3,又比如是某个物理页的某个偏移位置做了什么操作,是实实在在记录了物理上的变化,所以它叫做物理日志

什么是redo log合适的机会:

  1. redo log写满了:出现这种情况,MySQL会停止所有更新操作,等待redo log刷脏页完成。
  2. 内存满了:根据策略选择淘汰的页面,页面有两种情况:干净页和脏页。干净页无事,直接覆盖使用;脏页则需要将涉及的redo log也更新到磁盘中,使脏页变为干净页,才可继续使用。
  3. MySQL觉得空闲的时候
  4. MySQL正常关闭

如何控制刷脏页的性能:

  1. 告诉MySQL磁盘IO上限有多快:innodb_io_capacity
  2. 告诉MySQL内存中脏页比例:innodb_man_dirty_pages_pct
  3. 告诉MySQL支不支持脏页连坐(邻居是脏页一起刷走):innodb_flush_neighbors

redo log存放的内容:

我还没找到查看redo log的方法

redo log的参数设置:

MySQL可以使用如下参数来设置redo log:

  • innodb_log_file:每个redo log的大小,默认为48MB
  • innodb_log_files_in_group:指redo log文件的数量,默认为2
  • innodb_log_group_home_dir:redo log的存放路径,默认为"./",就是MySQL下的data目录

我们可以使用如下命令去查询,红框中就是redo log涉及的参数
在这里插入图片描述

我们可以my.ini中对它进行设置,my.ini可以通过cmd+services.msc→服务→MySQL→右键属性得到。

redo log的实际操作:

redo log是循环写的,就已我们上图为为例,我们有两个日志文件,每个文件为48MB,存在两个指针write pos和check point,分别指向写入的位置和擦除的位置,write pos和check point之间是我们可以写入日志的区域。

举例看下图,有write pos和check point两个指针,它们之间的绿色区域是可写入的,蓝色区域是已经存有日志的,当redo log写满时,MySQL会停止一切数据更新操作,将check point前推,check point擦除部分记录的日志操作需要同步到磁盘上,同时内存上内存页也会从脏页变为干净页

脏页: 内存页上的数据与数据库上的不一致。干净页: 内存上的数据写入磁盘,内存与数据库的数据页内容上一致。

在这里插入图片描述

正是因为有了 redo log,MySQL也具有了crash-safe能力,即使MySQL在某个时刻崩溃,之前提交的记录信息也不会丢失。

15.3 两阶段提交

更新语句的执行流程: 例如存在一条sqlupdate t set a = 12,b=10 where id =10

  1. 引擎找到id=10的这一行返回给执行器,在内存中直接返回,不在则加载磁盘再返回。
  2. 执行器拿到数据,进行修改,调用引擎接口写入这一行。
  3. 引擎拿到数据更新到内存中,写入redo log,redo log处于prepare状态。
  4. 执行器生成binlog写入磁盘
  5. 执行器调用引擎提交事务接口,把刚写入的redo log状态改为commit,更新完成。

两阶段提交的目的是为了保持数据逻辑上的一致性。

我们能假设如果没有两阶段提交,在某个日志写入后,发生系统奔溃,是否还能还原真实数据呢?

先写redo log:数据库实际存在一条,归档日志中少一条,后续如果使用这个binlog来恢复临时库的话,便比实际上缺失了一条。

先写binlog:从奔溃中恢复的数据库会比归档日志少一条更新操作。

不使用两阶段提交,会存在binlog和redo log数据逻辑上不一致的状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值