1. 事务日志可以帮助提高事务的效率。使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到磁盘。事务日志采用的是追加的方式,因此写日志的操作是磁盘上一小块区域内的顺序I/O,而不像随机I/O需要在磁盘的多个地方移动磁头,所以采用事务日志的方式相对来说要快得多。事务日志持久以后,内存中被修改的数据在后台可以慢慢地刷回到磁盘,通常称之为预写式日志(Write-Ahead Logging),修改数据需要写两次磁盘。
MySQL Innodb中跟数据持久性、一致性有关的日志,有以下几种:
- Bin Log: 记录了所有的DDL和DML语句(除了select),还包含语句所执行的消耗的时间,是mysql服务层产生的日志,常用来进行数据恢复、数据库复制,常见的mysql主从架构,就是采用slave同步master的binlog实现的
- Redo Log: 保证事务的持久性,记录了数据操作在物理层面的修改,mysql中使用了大量缓存,修改操作时会直接修改内存,而不是立刻修改磁盘,事务进行中时会不断的产生redo log,在事务提交时进行一次flush操作,保存到磁盘中。当数据库或主机失效重启时,会根据redo log进行数据的恢复,如果redo log中有事务提交,则进行事务提交修改数据。
- Undo Log: 保证事务的原子性以及InnoDB的MVCC,当进行数据修改时还会记录undo log,undo log用于数据的撤回操作,它记录了修改的反向操作,比如,插入对应删除,修改对应修改为原来的数据,通过undo log可以实现事务回滚,并且可以根据undo log回溯到某个特定的版本的数据,实现MVCC
2. InnoDB的MVCC(Multi-Version Concurrency Control,多版本并发控制),是为了查询一些正在被另一个事务更新的行,并且可以看到它们被更新之前的值。这是一个可以用来增强并发性的强大的技术,因为查询不用等待另一个事务释放锁。
实现原理:在每一行记录的后面增加两个隐藏列,记录创建版本号和删除版本号,每开启一个新事务,事务的版本号就会递增,并把查询到的数据复制到内存中,后续的所有增删改查操作都是针对于内存中的数据,再把修改行为记录到持久在硬盘上的事务日志中(redo log),而不用每次都将修改的数据本身持久到磁盘。在事务提交时进行一次flush操作,根据redo log保存到磁盘中。
MVCC解决了RR级别的幻读和高并发下的读操作(快照读)。
快照读:读取的是快照版本(内存数据),普通的SELECT就是快照读,而UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE是当前读。
锁定读:SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE读的是磁盘真正数据,并且加了共享锁,其它事务只能读不能修改,直到当前事务提交,跟UPDATE的加锁情况是一样的,即只允许当前事务进行读写,其他事务只能读,不能增删改。