mysql事务相关的redoLogundoLog

Posted 好大的月亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql事务相关的redoLogundoLog相关的知识,希望对你有一定的参考价值。

数据增删改的一个大致过程如下

  1. 先从索引中找到数据所在的表空间ID以及在表空间中的数据页的页号
  2. 然后通过表空间ID+页号作为Key,去缓存页哈希表中查找Buffer
    Pool是否已经加载了这个缓存页。如果已经加载了缓存页,就直接读取这个缓存页。
    如果没有这个缓存页,就需要从磁盘表空间中加载数据页到内存,此时需要从Free链表获取一个空闲页加入LRU链表中,加载的数据页就会放到这个空闲的缓存页中。
  3. 接着在对应的缓存页中执行增删改操作,被修改过的缓存页就变成了脏页,会加入Flush链表中。
  4. 最后,后台线程会在一些时机将LRU链表尾部的冷数据和Flush链表中的脏页刷盘。

redo Log的由来

这个过程有个最大的问题就是,数据修改且事务已经提交了,但只是修改了Buffer Pool中的缓存页,数据并没有持久化到磁盘,如果此时数据库宕机,那数据不就丢失了!
但是也不可能每次事务一提交,就把事务更新的缓存页都刷新回磁盘文件里去,因为缓存页刷新到磁盘文件里是随机磁盘读写,性能是很差的,这会导致数据库性能和并发能力都很差。

所以此时就引入了一个 redo log 机制,在提交事务的时候,先把对缓存页的修改以日志的形式,写到 redo log 文件里去,而且保证写入文件成功才算事务提交成功。而且redo log是顺序写入磁盘文件,每次都是追加到磁盘文件末尾去,速度是非常快的。之后再在某个时机将修改的缓存页刷入磁盘,这时就算数据库宕机,也可以利用redo log来恢复数据。

undo Log

事务的第一个特性就是原子性,原子性就是要保证一个事务中的增删改操作要么都成功,要么都不做。这时就需要 undo log,在对数据库进行修改前,会先记录对应的 undo log,然后在事务失败或回滚的时候,就可以用这些 undo log 来将数据回滚到修改之前的样子。

事务ID
事务执行过程中在对某个表执行增、删、改操作时,InnoDB就会给这个事务分配一个唯一的事务ID。如果一个事务中没有执行增删改操作,就不会分配事务ID。
InnoDB 在内存维护了一个全局变量来表示事务ID,每当要分配一个事务ID时,就获取这个变量值,然后把这个变量自增1。每当这个变量的值为256的倍数时,就会将该变量的值刷新到系统表空间的页号为5的页面中一个称之为Max Trx ID的属性处。当系统下一次重新启动时,会将Max Trx ID属性加载到内存中,并将该值加上256之后赋值给这个全局变量(这个过程跟主键row_id的分配是类似的)。
我们可以通过 information_schema.INNODB_TRX 来查询当前系统中运行的事务信息,这张表的第一个字段trx_id就是事务ID。

行记录中的三个隐藏列

  1. DB_ROW_ID:如果没有为表显式的定义主键,并且表中也没有定义唯一索引,那么InnoDB会自动为表添加一个row_id的隐藏列作为主键。
  2. DB_TRX_ID:事务中对某条记录做增删改时,就会将这个事务的事务ID写入trx_id中。
  3. DB_ROLL_PTR:回滚指针,本质上就是指向 undo log 的指针。

每对一条记录做一次改动,就会产生1条或者2条 undo log。一个事务中可能会有多个增删改SQL语句,一个SQL语句可能会产生多条 undo log,一个事务中的这些 undo log 会被从 0 开始递增编号,这个编号称为 undo no。
undo log 主要是记录对数据库增删改的撤销日志。

直白点,undo log就是事务中对数据增删改后的反向操作记录log,当事务失败或者需要回滚的时候就可以依靠这些log回滚,当前不会直接把数据回滚到本事务开始前的,因为其他事务可能也同时在操作这条数据。

以上是关于mysql事务相关的redoLogundoLog的主要内容,如果未能解决你的问题,请参考以下文章

Mysql相关面试题目

MySQL事务的相关问题

MySQL Innodb 事务实现过程相关内容的整理

mysql insert 事务相关(草稿)

mysql 主从相关

MySQL-长事务详解