MySQL之Undo日志(回滚日志)
什么是Undo Log?
Undo:
意为撤销或取消,以撤销操作为目的,返回某个状态的操作。
Undo Log:
数据库事务开始之前,会将要修改的记录放到Undo日志里,当事务回滚时或者数据库崩溃时,可以利用UndoLog撤销未提交事务对数据库产生的影响。
Undo Log是事务原子性的保证。在事务中更新数据的前置操作其实是要先写入一个Undo Log
如何理解Undo Log
事务需要保证原子性,也就是事务中的操作要么全部完成,要么什么也不做。但有时候事务执行到一半会出现一些情况,比如:
- 情况一:事务执行过程中可能遇到各种错误,比如服务器本身的错误,操作系统错误,甚至是突然断电导致的错误。
- 情况二:DBA可以在事务执行过程中手动输入ROLLBACK语句结束当前事务的执行。以上情况出现,我们需要把数据改回原先的样子,这个过程称之为回滚。
每当我们要对一条记录做改动时(这里的改动可以指INSERT、DELETE、UPDATE
),都需要把回滚时所需的东西记下来。比如:
- 你插入一条记录时,至少要把这条记录的主键值记下来,之后回滚的时候只需要把这个主键值对应的记录删掉就好了。(对于每个
INSERT
, InnoDB存储引擎会完成一个DELETE
) - 你删除了一条记录,至少要把这条记录中的内容都记下来,这样之后回滚时再把由这些内容组成的记录插入到表中就好了。(对于每个
DELETE
,InnoDB存储引擎会执行一个INSERT
) - 你修改了一条记录,至少要把修改这条记录前的旧值都记录下来,这样之后回滚时再把这条记录更新为旧值就好了。(对于每个
UPDATE
,InnoDB存储引擎会执行一个相反的UPDATE
,将修改前的行放回去)
MySQL把这些为了回滚而记录的这些内容称之为撤销日志
或者回滚日志
(即Undo Log)。注意,由于查询操作(SELECT)并不会修改任何用户记录,所以在杳询操作行时,并不需要记录相应的Undo日志
此外,Undo Log会产生Redo Log
,也就是Undo Log的产生会伴随着Redo Log的产生,这是因为Undo Log也需要持久性的保护。
Undo Log的功能
- 提供数据回滚-原子性
当事务回滚时或者数据库崩溃时,可以利用Undo Log来进行数据回滚。 - 多版本并发控制(MVCC)-隔离性
即在InnoDB存储引擎中MVCC的实现是通过Undo Log来完成。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过Undo Log读取之前的行版本信息,以此实现非锁定读取。
Undo Log的存储结构
- 回滚段与Undo页
InnoDB对Undo Log的管理采用段的方式,也就是回滚段(rollback segment)
。每个回滚段记录了1024 个Undo Log segment
,而在每个Undo Log segment段中进行Undo页
的申请。
在InnoDB1.1版本
之前(不包括1.1版本),只有一个rollback segment
,因此支持同时在线的事务限制为 1024。虽然对绝大多数的应用来说都已经够用。
从1.1版本开始InnoDB支持最大128个rollback segment
,故其支持同时在线的事务限制提高到了128\*1024
。
1 2 3 4 5 6 | mysql> show variables like 'innodb_undo_logs'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | innodb_undo_logs | 128 | +------------------+-------+ |
虽然InnoDB1.1版本支持了128个rollback segment
,但是这些rollback segment
都存储于共享表空间ibdata中。从lnnoDB1.2版本开始,可通过参数对rollback segment
做进一步的设置。这些参数包括:
innodb_undo_directory:
设置rollback segment文件所在的路径。这意味着rollback segment可以存放在共享表空间以外的位置,即可以设置为独立表空间。该参数的默认值为“./”,表示当前InnoDB存储引擎的目录。
innodb_undo_logs:
设置rollback segment的个数,默认值为128。在InnoDB1.2版本中,该参数用来替换之前版本的参数innodb_rollback_segments。
innodb_undo_tablespaces:
设置构成rollback segment文件的数量,这样rollback segment可以较为平均地分布在多个文件中。设置该参数后,会在路径innodb_undo_directory看到undo为前缀的文件,该文件就代表rollback segment文件。