MySQL事务日志

本文深入探讨了MySQL事务日志,包括redo日志和undo日志的实现机制、作用及流程。redo日志用于保证事务的持久性,通过WAL策略先写日志后写磁盘,而undo日志则是为了保证事务的原子性和一致性,用于回滚和MVCC。内容详细阐述了redo日志的缓冲区、文件、刷盘策略,以及undo日志的存储结构、生命周期和类型。
摘要由CSDN通过智能技术生成

目录

1.事务的四种特性是基于什么机制实现的

2.redo日志

2.1 为什么需要redo日志

2.2 redo日志的好处、特点

2.3 redo组成

2.4 redo整体流程

2.5 redo log刷盘策略

3.undo 日志

3.1 如何理解undo日志

3.2 undo日志的作用

3.3 undo日志的存储结构

3.4 undo日志的类型

3.5 undo日志的生命周期

4.MySQL事务日志小结


1.事务的四种特性是基于什么机制实现的

事务的隔离性是由锁机制实现的

事务的原子性、一致性和持久性由事务的redo日志和undo日志来保证。

        REDO LOG:重做日志,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性。

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

REDO LOG和UNDO LOG都可以视为是一种恢复操作,但是:

        REDO LOG:记录的是物理级别上的页修改操作,比如页号,偏移量,写入的数据,主要是为了保证数据的可靠性。

        UNDO LOG:记录的是逻辑操作日志,比如对某一行数据进行了insert操作,那么undo log就记录一条与之相反的delete操作。主要用于事务的回滚和一致性非锁定读。

2.redo日志

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

2.1 为什么需要redo日志

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

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

        那么该如何保证持久性呢?InnoDB的事务采用了WAL(Write-Ahead Logging),这种技术的思想就是先写日志,再写磁盘,只有日志写入成功,才算事务提交成功,这里的日志即为redo日志。当发生宕机且数据未刷到磁盘的时候,可以通过redo log来恢复,从而保证数据的持久性。

2.2 redo日志的好处、特点

好处

        降低了刷盘频率

        redo日志占用的空间很小(只保存了存储表空间id、页号、偏移量以及需要修改的值),相当于利用极少的空间保障了事务的持久性

特点

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

        事务执行过程中,redo log不断记录:redo log跟bin log的区别在于,redo log是存储引擎层产生的,而bin log是数据库层产生的。redo log在事务进行的过程中一直不断的往日志文件中写入记录,而bin log直到此事务提交后,才会一次性写入到日志文件中。

2.3 redo组成

redo log可以简单分为两个部分:重做日志缓冲区(redo log buffer)和重做日志文件(redo log file)

重做日志缓冲区(redo log buffer)

        在服务器启动时就向操作系统申请了一大片称为redo log buffer的连续空间,系统默认大小16M。

重做日志文件(redo log file)

        redo日志文件保存在硬盘中,MySQL根目录下ib_logfile0和ib_logfile1即为redo日志。

2.4 redo整体流程

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

        第一步:先将原始数据从磁盘读入内存,在内存中修改数据

        第二步:生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值

        第三步:当事务commit时,将redo log buffer中的内容采用追加写的方式刷新到redo log file中

        第四步:定期将内存中修改的数据刷新到磁盘上

2.5 redo log刷盘策略

        redo log的写入并不是直接写入磁盘的,InnoDB引擎会在写redo log的时候先写redo log buffer,之后以一定的频率刷入到redo log file中。一定的频率是可以通过刷盘策略来设置的。

        注:redo log buffer刷盘到redo log file的过程并不是真正的刷到磁盘中,只是刷入到文件系统缓存(page cache)中去,真正的写入会交给系统自己决定。对于InnoDB来说就存在一个问题,如果交给系统同步,系统宕机会导致数据丢失。

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

        设置为0:每次事务提交时不进行刷盘

        设置为1:每次事务提交时都进行刷盘(默认值)

        设置为2:每次事务提交时都只是把redo log buffer内容写入page cache,不进行同步,由操作系统决定什么时候进行刷盘。

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

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

3.undo 日志

3.1 如何理解undo日志

        事务需要保证原子性,但有时候事务执行到一半会出现一些情况,比如:

        1.事务执行过程中遇到服务器错误、操作系统错误、各种环境因素等

        2.程序员手动输入ROLLBACK语句结束当前执行的事务

        如果出现以上情况,我们需要把数据恢复成原来的样子,此过程称之为回滚。比如:

        1.当我们插入一条数据时,我们记录下该数据的主键,如需回滚只需把该主键值对应的记录删掉就好。

        2.当我们删除一条记录,我们记录下这条数据的全部字段,如需回滚只需再把这些内容重新插入到表中就好。

        3.当我们修改一条记录,我们记录下这条数据被修改前的全部字段,如需回滚只需把这条数据更新为旧值就好。

        MySQL把这些为了回滚而记录的内容称之为回滚日志(undo log)。

        注:

        1.查询操作不需要记录undo日志。

        2.undo log会产生redo log,因为undo log也需要持久性的保护

3.2 undo日志的作用

        回滚数据:undo是逻辑日志,因此只是将数据库逻辑地恢复到原来的样子,所有修改都被逻辑地取消了,但是数据结构和页本身在回滚之后可能会不相同。例如事务新建的页所开辟的物理空间就不会被回滚。

        MVCC:即在InnoDB存储引擎中MVCC的实现是通过undo日志来完成。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo日志读取之前的行版本信息,以此实现非锁定读取。

3.3 undo日志的存储结构

回滚段与undo页

        InnoDB对undo log的管理采用段的方式,也就是回滚段。每个回滚段记录了1024个undo log segment,而在每个undo log segment段中进行undo页的申请。

回滚段与事务

        1.每个事务只会使用一个回滚段,一个回滚段在同一时刻可能会服务于多个事务。

        2.当一个事务开始的时候,会制定一个回滚段,在事务进行的过程中,当数据被修改时,原始数据会被复制到回滚段。

        3.在回滚段中,事务会不断填充盘区,直到事务结束或所有的空间都被用完。如果当前盘区不够用,事务会在段中请求扩展下一个盘区,如果所有已分配的盘区都被用完,事务会覆盖最初的盘区或者在回滚段允许的情况下扩展新的盘区。

        4.回滚段存在于undo表空间中

        5.当事务提交时,InnoDB引擎会做以下两件事

        将undo log放入列表,以供之后purge操作

        判断undo log所在的页是否可以重用,若可用则分配给下个事务使用。

回滚段中的数据分类

        1.未提交的回滚数据:该数据所关联的事务并未提交,用于实现读的一致性,所以该数据不能被其他事务的·数据覆盖。

        2.已经提交但未过期的回滚数据:该数据关联的事务已经提交,但仍受到undo retention参数的保持时间的影响。

        3.事务已经提交并过期的数据:事务已经提交,而且数据保存时间已超过undoretention参数指定的时间,当回滚段满了之后,会优先覆盖事务已经提交并过期的数据。

        注:事务提交以后并不能马上删除undo log及undo log所在的页,这是因为可能还有其他事务需要通过undo log来得到行记录之前的版本。故事务提交时将undo log放入一个链表,是否可以最终删除undo log以及undo log所在的页由purge线程判断。

3.4 undo日志的类型

insert undo log

        insert undo log是指在insert操作汇总产生的undo log,因为insert操作的记录,只对事务本身可见,对其他事务不可见(事务隔离性要求),故insert undo log可以在事务提交后直接删除。

update undo log

        update undo log记录的是对update和delete操作产生的undo log。该undo log可能需要提供MVCC机制,因此不能在事务提交时就进行删除。事务提交时会放入undo log链表,等待purge线程进行最后的删除。

3.5 undo日志的生命周期

        undo+redo log事务简化过程

        假设有两个值A = 1,B = 2,目的将A修改为3,B修改为4

1.begin
2.记录A = 1到undo log;
3.update A = 3;
4.记录A = 3到redo log;
5.记录B = 2到undo log;
6.update B = 4;
7.记录B = 4到redo log;
8.将redo log刷新到磁盘
9.commit;

        如果在1~8步中任意一步系统宕机,由于事务并没有提交,故对系统无影响。

        如果在8~9步骤宕机,由于undo log已经被redo log持久化,故服务恢复后可以选择回滚或提交,故对系统无影响。

        如果在9之后宕机,内存数据还没来得及刷回磁盘,由于redo log已经写入磁盘,系统恢复后可以根据redo log把数据刷回磁盘,故对系统无影响。

4.MySQL事务日志小结

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值