undo log是InnoDB MVCC事务特性的重要组成部分。当我们对记录做了变更操作时就会产生undo记录,undo记录默认被记录到系统表空间(ibdata)中,但从MySQL 5.6开始,也可以使用独立的undo表空间。
在InnoDB中,insert操作在事务提交前只对当前事务可见,undo log在事务提交后即会被删除,因为新插入的数据没有历史版本,所以无须维护undo log;对于update、delete操作,则需要维护多版本信息。
举个undo log作用的例子:Session1会话(以下简称S1)和Session2会话(以下简称S2)同时访问(不一定同时发起,但S1和S2事务有重叠)同一数据A,S1想要将数据A修改为数据B,S2想要读取数据A的数据。如果没有MVCC(Multi-Version Concurrency Control,多版本并发控制)机制就只能依赖锁了,谁拥有锁谁先执行,另一个等待,但是高并发下的效率很低。InnoDB存储引擎通过MVCC多版本控制的方式来读取当前执行时间数据库中行的数据,如果读取的行正在执行delete或update操作,这时读取操作不会因此等待行上锁的释放;相反,InnoDB会去读取行的一个快照数据(undo log),从历史快照(undo log链)中获取旧版本数据来保证数据一致性。由于历史版本数据存放在undo页当中,对数据修改所加的锁对于undo页没有影响,因此不会影响用户对历史数据的读,从而达到非一致性锁定读,提高并发性能。
如果出现了错误或者用户手动执行了rollback,系统可以利用undo log中的备份将数据恢复到事务开始之前的状态。与redo log不同的是,磁盘上不存在单独的undo log文件,它存放在数据库内部的特殊段(segment)中。
MySQL 5.6以后的版本支持把undo log分离到独立的表空间,并放到单独的文件目录下。采用独立undo表空间,再也不用担心undo会把ibdata1文件搞大,同时也给我们部署不同I/O类型的文件位置带来了便利。对于并发写入型负载,我们可以把undo文件部署到单独的高速存储设备上。