目录
概述
redo 日志
为什么需要redo日志
redo日志的好处特点
好处
特点
Undo日志
如何理解Undo日志
Undo日志的作用
小结
事务有四种特性:原子性、一致性、隔离性和持久性。那么事务的四种特性到底是基于什么机制实现的呢?
1.事务的隔离性是由锁机制实现。
2.而事务的原子性、一致性、持久性是由事务的redo日志和undo日志来保证的。
①read log称为重做日志,提供再写入操作,回复提交事务修改的页操作,用来保证事务的持久性。
②undo log称为回滚日志,回滚日志记录到某个特定版本,用来保证事务的原子性。一致性。
有的dba或许会认为undo是redo的逆过程,其实不然。redo和undo都可以视为一种恢复操作,但是:
①redo log:是存储引擎层生成的日志,记录的是物理级别上的页修改操作,比如也好xxx、偏移量yyy写入了zzz数据。主要是为了保证数据的可靠性。
②undo log:是存储引擎层生成的日志,记录的是逻辑操作日志,比如对某一行数据进行了insert语句操作,那么undo log就记录一条与之相反的delete操作。主要用于事务的回滚和一致性非锁定读。
innodb存储引擎是以页为单位来管理存储空间的。在真正访问数据页之前需要把在磁盘上的页缓存到内存中的buffer pool之后才可以访问。所有的变更都必须先更新缓冲池中的数据,然后缓冲池中的脏页会以一定的频率刷入磁盘,通过缓冲池来优化CPU和磁盘之间的鸿沟,这样就可以保证整体的性能不会下降太快。
一方面,缓冲池可以帮助我们消除CPU和磁盘之间的鸿沟,checkpoint机制可以保证数据的最终罗盘,然而由于checkpoint并不是每次变更的时候就触发的,而是master线程隔一段时间去处理的。所以最坏的情况就是事务提交后,刚写完缓冲池,数据库宕机了,那么这段数据就是丢失的,无法恢复的。
另一方面,事务包含持久性的特性,就是说对于一个已经提交的事务,在事务提交后即使系统发生了崩溃,这个事务对数据库中所有的更改也不能丢失。
那么如何保证这个持久性呢?一个简单的做法:在事务提交完成之前把该事务所修改的所有页面都刷新到磁盘,但是这个简单粗暴的做法有问题:
①修改量与刷新磁盘工作量严重必成比例
有时候我们仅仅修改了某个页面的某个字节,但是我们知道在innodb中是以页为单位来进行磁盘IO的,也就是说我们在该事务提交时候不得不将一个完整的页面从内存中刷新的磁盘,我们又知道野格页面默认是16KB大小,只修改一个字节就要刷新16KB的数据到磁盘上显然是太小题大作了。
②随机IO刷新较慢
一个事务可能包含很多语句,即使是一条语句也可能修改很多页面,加入该事物修改的这些页面可能并不相邻,这就意味着在将某个事务修改的buffer pool中页面刷新到磁盘时需要进行很多的随机IO,随机IO比顺序IO要慢,尤其对于传统的机械硬盘来说。
另一个解决的思路:我们只是想让已经提交了的事务对数据库中数据所做的修改永久生效,即使后来系统崩溃,在重启后也能把这种修改恢复出来。所以我们其实没有必要在每次事务提交时就把该事物在内存中的修改过的全部页面刷新到磁盘,只需要把修改了哪些东西记录一下就好。比如,某个事务将系统表空间中第十个页面中偏移量为100处的那个字节的值1改为2.我们只需要记录一下:从0好空间的10号页面的偏移量为100处的值更新为2.
innodb引擎的事务采用了wal技术(write-ahead logging),这种技术的思想就是先写日志再写磁盘,只有日志写入成功,才算事务提交成功,这里的日志就是redo log。当发生了宕机且数据未刷到磁盘时候,可以通过redo log恢复,保证acid中的id,这就是redo log的作用。
①redo日志降低了刷盘频率
②热电偶日志占用的空间非常小
存储表空间ID、页号、偏移量以及需要更新的值,所需的存储空间是很小的,刷盘块。
redo日志是顺序写入磁盘的
在执行事务的过程中,每执行一句语句,就可能产生若干条redo日志,这些日志是按照产生的顺序写入磁盘的,也就是使用顺序IO,效率比随机IO快。
事务执行过程中,redolog不断记录
redo long跟bin log的区别,redo日志是存储引擎层产生的,而bin日志是数据库层产生的。假设一个事务,对表做了10万行的记录插入,在这个过程中,一直不断的往redo日志顺序记录,而bin日志不会记录,直到这个事务提交,才会一次写入到bin日志文件中