MySQL事务redo,undo日志

MySQL事务redo,undo日志

redo日志

InnoDB存储引擎是以页为单位来管理存储空间的,真正访问页面之前,需要把在磁盘上的页缓存到内存的Buffer Pool之后才能访问,所有的变更都必须先更新缓冲池中的数据,缓冲池中被修改的脏页会以一定的频率刷入磁盘(CheckPoint机制),通过缓冲池来优化CPU和磁盘之间的鸿沟

这种机制存在的问题:
当缓冲池数据被修改后,事务提交,当还没有发生刷盘(缓存池数据写入磁盘)之前,发生宕机,脏页就会消失,数据写入失败,无法实现事务的持久性

事务提交后就实时刷新到磁盘?

这样做不可行,原因:

  • 不值得比如只修改了一行的某个字段,而刷盘是以页为单位了,16KB大小都得进行刷盘,不划算
  • 随机IO刷新慢一个事务的修改不一定数据都在一个页当中,如果事务提交就进行刷盘,会产生很多的随机IO

所以就使用redo日志

解决思路
把修改的地方先写到磁盘中的redo日志,刷盘操作正常进行,因为统一存储到一个日志中,属于顺序IO,速度较快,数据库崩溃时,使用redo文件来恢复

特点:

  • 顺序写入磁盘
  • 事务执行时,redo log不断记录

redo log日志的组成

redo log buffer保存在内存中,是容易丢失的,在服务器启动时就向操作系统申请一大片称为redo log buffer的连续空间,这片空间被划分成若干个连续的redo log block,一个block占512字节

redo log file: 保存在磁盘,是持久的MySQL事务redo,undo日志_第1张图片
从存储逻辑上是一个两个循环指针来控制写入和清除,写入时write pos后移,当数据刷入磁盘后,checkpoint后移,两指针之间就是缓存和磁盘的差异数据,当俩指针碰撞后,说明写满了,就得等checkpoint清除一下之后再写入了

redo log 执行流程

MySQL事务redo,undo日志_第2张图片
请添加图片描述
事务查询->数据从磁盘加载到内存->数据修改->写redo到redo log buffer->redo刷盘->数据页刷盘

redo log刷盘策略

注意,log刷盘过程并不是直接刷到磁盘中,而是刷入文件系统缓存(page cache,OS为了提高写入效率的缓冲区),真正的写入时机可以交给系统自己来决定,交给系统来处理,即刷盘后系统宕机仍然可能出现问题

InnoDB给出innodb_flush_log_at_trx_commit参数来控制事务提交时,log的刷盘进行策略,默认为每次提交就刷盘(提交给page cache并立即写入),可以设置0->每个1秒进行一次,或者2->提交后log提交给page cache,由OS决定写入时机。

通过测试,执行效率相比为 0>2>1
1是默认的,提交后立即刷入page cache并立即刷入磁盘,效率最低,但是最安全,还是推荐使用的,最大的保证了数据恢复

redo log总结

redo log保证了事务的持久性和一致性,当服务器发生宕机重启时,会通过redo log file来恢复未成功刷盘的数据,redo log file可以分多个文件,每个文件大小可以设置,由两个指针分别指向空闲位置和为刷盘的数据行,两指针之间的数据就是需要重新写入数据库的文件

undo log日志

redo 日志保证了事务的持久性,undo 日志则保证了事务的原子性,在事务执行更新操作时,会记录undo日志,在发生回滚时,就得依赖undo log来实现,undo log也会产生redo log,因为回滚也需要持久性的保护
undo log是对数据库逻辑上的回滚,并不是物理上的回滚,如果插入时创建了新的页,回滚并不会删除页
undo log也用于MVCC的实现,通过日志指针,找出当前事务查询合理的结果,具体请查看MySQL锁专题

回滚段

InnoDB对undo log 的管理采用段的方式,就是回滚段(rollback segment),每个回滚段记录了1024个undo log segment,而每个undo log segement段中进行undo 页的申请。
这里就可以体现InnoDB引擎的并发度:InnoDB1.1版本之前,只有一个rollback segment,所以并发度是1024
在之后的版本支持了128个回滚段,所以并发事务可以达到128*1024

回滚段和事务

  • 每个事务只会使用一个回滚段,一个回滚段可以同时服务多个事务
  • 事务开始,会制定一个回滚段,事务过程中,数据被修改,原始的数据会被复制到回滚段中
  • 当事务结束或者所有空间被用完,如果盘区不够用,事务会在段中请求拓展下一个盘区

undo log的类型

  • insert undo log:插入时产生,只对事务本身可见,其他事务不可见,所以事务提交时可以直接删除
  • update undo log:记录delete 和 update的操作,该undo log需要提供MVCC机制,因此事务提交也不能删除,提交时放入undo log 链表,等待清除线程删除

undo log的使用时机

如果事务没有提交,而且redo log没有进行刷盘,那数据库中都是旧的数据
如果redo log刷盘了,相当于已经进行了持久化(因为即使宕机恢复后也会根据redolog日志来进行数据刷盘)
redo log刷盘后,事务还没有提交,这时就需要回滚

MySQL事务redo,undo日志_第3张图片

undo log总结

undo log的功能有两部分:

  • 保证事务的原子性
  • 保证MVCC机制

当持久化发生时,如果发生回滚,就会根据undo log日志链来查找之前的数据,这些回滚记录都在回滚段中

这里两个日志保证了事务的一致性,持久性和原子性,还剩下一个隔离性,这个需要使用锁机制来保证,具体可以查看我的博客《MySQL的锁机制》

你可能感兴趣的:(MySql,java,面经,mysql,数据库)