MySQL事务日志

事务有4种特性:原子性、一致性、隔离性和持久性。那么事务的四种特性到底是基于什么机制实现呢?

  • 事务的隔离性由 锁机制 实现。
  • 而事务的原子性、一致性和持久性由事务的 redo 日志和undo 日志来保证。
    • REDO LOG 称为 重做日志 ,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持

久性。 主要就是保证事务的持久性,从内存保存到磁盘的过程的数据的持久性一致性,提交事务就是通过read日志保证。

    • UNDO LOG 称为 回滚日志 ,回滚行记录到某个特定版本,用来保证事务的原子性、一致性。

有的DBA或许会认为 UNDO 是 REDO 的逆过程,其实不然。主要保证事务的原子性,终止事务就是通过undo日志来完成的。

  • redolog :是存储引擎层(innodb)生成的日志,记录的是物理级别上的页修改操作,比如页号xxx、偏移量yyy写入了“zzz”数据。主要为了保证数据的可靠性。
  • undolog :是存储引擎层(innodb)生成的日志,记录的是逻辑操作日志,比如对某一行数据进行INSERT语句操作,那么undo log 就会记录一条与之相反的DELETE操作。主要用于事务的回滚(undo log 记录的是每个修改操作的逆操作)和一致性非锁定读(undo log 回滚记录某个特点的版本 -MVCC ,即多版本并发控制)。

一、redo日志

InnoDB 存储引擎以页为单位来管理存储空间的。在真正访问页面之前,需要把磁盘上的页缓存到内存中的Buffer Pool 之后才可以访问。所有的变更都必现先更新缓冲池中的数据然后缓冲池中的脏页会以一定的频率刷入磁盘(checkPoint机制),通过缓冲池来优化CPU和磁盘之间的鸿沟,这样就可以保证整体的性能不会降低太快。

1.1 为什么需要REDO日志

        read日志的作用就是保证,数据修改之后,只会先修改内存中的数据,不会去更新磁盘中数据,而是定期统一的进行刷盘操作,如果在刷盘过程中出现了宕机的操作,那么就会导致数据的不一致性,此时read就可以保证宕机的一个问题,因为在内存修改是,也就记录到redo日志当中,就是宕机内存中的数据丢失,但是redo日志的数据是存在,通过读取redo日志来进行数据的一致性和持久化。

        就是保证内存和磁盘的数据一致性。

        这样的机制是因为,如果就刷新较少的数据,也会导致需要以数据页的为单位进行刷新。如果存在不同的页中数据,那么如果页之间不是连续的就会出现随机io

就是将内存的修改,先保存在一个日志文件中,一但服务器宕机了,日志文件是存在,在重新启动服务器时,就会读取redo文件进行同步。
 

     

        一方面,缓冲池可以帮助我们消除CPU和磁盘之间的鸿沟,checkpoint机制可以保证数据的最终落盘,然而由于checkpoint 并不是每次变更的时候就触发 的,而是master线程隔一段时间去处理的。所以最坏的情况就是事务提交后,刚写完缓冲池,数据库宕机了,那么这段数据就是丢失的,无法恢复。

        另一方面,事务包含 持久性 的特性,就是说对于一个已经提交的事务,在事务提交后即使系统发生了崩溃,这个事务对数据库中所做的更改也不能丢失。

        那么如何保证这个持久性呢? 一个简单的做法 :在事务提交完成之前把该事务所修改的所有页面都刷新到磁盘,但是这个简单粗暴的做法有些问题:

  • 修改量与刷新工作量严重不成比例

有时我们仅仅修改某个页面中的字节,但是我们知道在InnoDB中是以页为单位进行磁盘IO的,也就是说我们在该事物提交时不得不将一个完成的页面从内存中刷新到磁盘,我们又知道一个页面是16kb大小,只修改一个字节就需要刷洗16KB的数据到磁盘上显然是太小题大做了。

  • 随机IO刷新较慢

        一个事务可以包含很多语句,即使是一条语句也可能修改许多页面,假如该事务修改的这些页面可能并不相邻这就意味着在某个修改的Buffer Pool中的页面刷新磁盘时,需要进行很多的随机IO,随机IO比顺序IO要慢,尤其对于传统的机械硬盘来说。

另一个解决的思路 :我们只是想让已经提交了的事务对数据库中数据所做的修改永久生效,即使后来系统崩溃,在重启后也能把这种修改恢复出来。所以我们其实没有必要在每次事务提交时就把该事务在内

存中修改过的全部页面刷新到磁盘,只需要把 修改 了哪些东西 记录一下 就好。比如,某个事务将系统表空间中 第10号 页面中偏移量为 100 处的那个字节的值 1 改成 2 。我们只需要记录一下:将第0号表空间的10号页面的偏移量为100处的值更新为 2 。

InnoDB引擎的事务采用了WAL技术(Write-Ahead-Logging),这种技术的思想就是先写日志,再写磁盘,只有日志写入成功,才算事务提交成功,这里的日志就是 redo log 。当发送宕机且数据未刷新到磁盘的时候,可以通过 redo log 来恢复,保证ACID中D,这就是 redo log 的作用。

1.2 REDO 日志的好处、特点

1.好处

  • redo 日志降低了刷盘频率
  • redo日志占用的空间非常小

存储表空间ID、页号、偏移量以及所需要更新的值,所需要的存储空间是很小的,刷盘快。

2.特点

  • redo 日志是顺序写入磁盘的

在执行事务的过程中,每执行一条语句,就可能产生若干条redo日志,这些日志按照产生的顺序写入磁盘的,也就是使用顺序IO,效率比随机IO快。

  • 事务执行过程中,redo log 不断记录

redo log 和 bin log 的区别,redo log 是存储引擎层产生的,而bin log 是 数据库层产生的假设一个事务,对表做10万行的记录插入,在这个过程中,一直不断的往redo log 顺序记录,而bin log 不会记录,知道这个事务提交,才会一些写入到bin log 文件中。

1.3 redo 的组成

Redo log 可以简单分为以下两个部分:

  • 重做的缓冲redo log buffer,保存在内存中,是容易丢失的。

在服务器启动时就想操作系统申请了一大片称之为redo log buffer 的连续内存空间,翻译成中文就是 redo 日志缓冲区。这片内存空间被划分为若干个连续的redo log block。一个 redo log block 占用512字节大小。

redo log buffer 大小,默认 16M ,最大值是4096M,最小值为1M。

mysql> show variables like '%innodb_log_buffer_size%';
+------------------------+----------+
| Variable_name 				 | Value 		| 
+------------------------+----------+
| innodb_log_buffer_size | 16777216 | 
+------------------------+----------+
  • 重做日志文件 (redo log file) ,保存在硬盘中,是持久的。
    • 数据的恢复就是通过 redo log file 在磁盘空间中的。
    • 默认会有两个
    • 大小都是一致,并且空间是开辟好的。

1.4 redo 的整体流程

一个更新事务为例,redo log 流转过程,下图所示:

第一步:先将原始数据从磁盘读取到内存中,修改数据的内存拷贝
第二步:生成一条重做日志并写入 redo log buffer ,记录的是数据被修改后的值
第三步:当事务commit时,将redo log buffer 中的内存刷新到 redo log file ,对redo log file 采用追加写的方式。
第四步:定期将内存中修改的数据刷新到磁盘中。

# 更新为例的流程
- 1.首先先将要操作的数据读取到内存中
- 2.在数据被修改时生成redo log buffer ,将修改的数据记录到内存中
- 3. 在没有提交时也将会将redo log buffer 的数据通过redo log file 中。
- 4. 定期将将内存层面修改数据刷盘到磁盘中。

体会:

Write-Ahead Log(预先日志持久化):在持久化一个数据页之前,先将内存相应的日志页持久化。

1.5 redo log 的刷盘策略

这里是说的将缓存中数据刷盘到redo日志文件中

# 刷盘的过程是 缓存刷到redo日志的过程

- 1.将redo buffer 将数据定刷入到磁盘
- 2.刷入磁盘实际上并没有将数据直接刷入到 redo log file 而是交个文件系统缓存,相当于进行优化,由他觉得具体什么时候进行刷盘。

redo log的写入不是直接写入磁盘的,InnoDB引擎会在写 redo log 的时候先写 redo log buffer ,之后以一定的频率刷入到真正的 redo log file 中。这里的一定频率怎么看待呢?这就是我们要说的刷盘策略。

注意:redo log buffer 刷盘到 red log file 的过程并不是真正的刷到磁盘中去,只是刷到了文件系统缓存(page cache)中去(这是现代操作系统为了提高文件写入效率做的优化),真正的写入会交给系统自己来决定(比如page cache 足够大)。那么对于 InnoDB来说就存在一个问题如果交给系统同步,同样如果系统宕机,那么数据页丢失了(虽然整个系统宕机的概率很小的)。

针对这种情况,InnoDB 给出innodb_flush_log_at_trx_commit参数,该参数控制commit提交事务时,如何将 redo log buffer 中的日志刷新到 redo log file中。它支持三种策略:

  • 设置为0 :表示每次事务提交时不进行刷盘操作。(系统默认master thread每隔1s进行一次重做日

志的同步)交给存储引擎的后台线程来自动刷新

  • 设置为1 :表示每次事务提交时都将进行同步,刷盘操作( 默认值 )
  • 设置为2 :表示每次事务提交时都只把 redo log buffer 内容写入 page cache,不进行同步。由os自己决定什么时候同步到磁盘文件。
show variables like 'innodb_flush_log_at_trx_commit';

另外,InnoDB存储引擎有一个后台线程,每隔1秒,就会把redo log buffer中的内容写到文件系统缓存(Page cache),然后调用刷盘操作。

也就是说,一个没有提交事务的redo log记录,也可能会刷盘。因为在事务执行过程 redo log 记录就会写入到 redo log buffer中,这些redo log 记录会被后台线程刷盘。

除了后台线程每秒1次的轮询操作,还有一种情况,当redo log buffer占用的空间即将达到innodb_log_buffer_size(这个参数默认是16M)的一半的时候,后台线程会主动刷盘。

二、Undo日志

        具体等待更新

  • 16
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值