前段时间看了下数据库的基础知识,稍微整理一下。
什么是Redo
Redo,顾名思义就,重做。以恢复操作为目的,重现操作。
Redo记录transaction logs,分为online和archived。
比如,机器停电,那么在重起之后需要online redo logs去恢复系统到失败点。
比如,磁盘坏了,需要用archived redo logs和online redo logs区恢复数据。
什么是Undo
Undo,意为取消,以撤销操作为目的,返回上一个状态,类似备份。
注意:Redo也会记录Undo操作。
举个例子
比如我们往一个表中插入一条数据。
- redo记录这个操作。
- undo记录这个操作。
- redo记录上一步undo操作。
如果这张表有索引,那么表中索引的改变也会作redo和undo。
日志先行
redo和undo都是写在内存中的,所以一旦系统奔溃,这些文件将不复存在。所以数据库中很重要的一个东西就是日志。redo log 的信息就需要先写到磁盘上,因为它是最原始的操作,能用于场景重现。
牛逼的MVCC
曾在讲座中听到,当年oracle独霸全球时,很大程度上就是得益于MVCC。
mvcc(多版本控制),如果把基于锁的并发控制机制称成为悲观机制,那么MVCC就算是乐观机制。
乐观和悲观的区别在于,悲观机制是必须等所有条件完备之后再开始执行。乐观机制则是先碰运气往下做,如果不行就回滚。
mvcc的实现:
oracle允许可以由多个用户对数据库进行操作,当你执行一个查询几百万条记录的操作时,这个过程可能需要几分钟。在这个过程中其它用户对你查询的数据时行了修改。这里就要保证你查询的结果是被修改之前的。
刚才说了,乐观机制是需要回滚的,所以undo就派上用场了。
当我们执行一个事务的时候,oracle会分配一个SCN编号,这个编号是递增的。下一个事务的编号一定比当前事务的编号大。上图中执行第一个事务分配的编号为10023,在这个事务执行的过程中,另一事务对SCN 编号为10008和10021的数据块进行了修改。用来替换的数据块SCN编号为10024 ,而被替换掉的数据块会被保存到undo 上面。当第一个事务执行到被修改过的数据块时,发现10024比10023大,这个时候就会到undo segment上找比自己SCN号小的数据块进行读,于是发找到了SCN号为10008和10021两个块。这样就有效的保证读一致性。
执行看上去总是这么顺利,得益于无锁机制。但是提交时就可能悲剧。因为提交时需要检查版本冲突,如果失败则需要重做一次。
mvcc的适用场景:
mvcc费时的地方在于版本冲突时。所以mvcc适用于读多于写的场景。因为冲突只出现于写的时候。
如果写操作很多,则会引起频繁的冲突,使得mvcc花费很多时间在retry。这种情况还不如直接使用锁。
说到底还是在于retry的代价是否大,如果retry代价小,就适合mvcc这种尝试性的操作,否则就是用锁。
转载请注明:旅途@KryptosX » Undo和Redo以及牛逼的MVCC