数据库

位置:IT落伍者 >> 数据库 >> 浏览文章

Oracle的redo和undo的区别


发布日期:2021年05月04日
 
Oracle的redo和undo的区别

redo> undo>datafile insert一条记录时 表跟undo的信息都会放进 redo 中 在commit 或之前 redo 的信息会放进硬盘上 故障时 redo 便可恢复那些已经commit 了的数据 redo>每次操作都先记录到redo日志中当出现实例故障(像断电)导致数据未能更新到数据文件则数据库重启时须redo重新把数据更新到数据文件 undo>记录更改前的一份copy但你系统rollback时把这份copy重新覆盖到原来的数据 redo>记录所有操作用于恢复(redo records all the database transaction used for recovery) undo>记录所有的前印象用于回滚(undo is used to store uncommited data infor used for rollback) redo>已递交的事务实例恢复时要写到数据文件去的 undo>未递交的事务 redo的原因是每次commit时将数据的修改立即写到online redo中但是并不一定同时将该数据的修改写到数据文件中因为该数据已经提交但是只存在联机日志文件中所以在恢复时需要将数据从联机日志文件中找出来重新应用一下使已经更改数据在数据文件中也改过来!

undo的原因是在oracle正常运行时为了提高效率加入用户还没有commit但是空闲内存不多时会由DBWR进程将髒块写入到数据文件中以便腾出宝贵的内存供其它进程使用这就是需要UNDO的原因因为还没有发出commit语句但是oracle的dbwr进程已经将没有提交的数据写到数据文件中去了 undo 也是也是datafile 可能dirty buffer 没有写回到磁盘里面去只有先redo apply 成功了才能保证undo datafile 里面的东西都是正确的然后才能rollback 做undo的目的是使系统恢复到系统崩溃前(关机前)的状态再进行redo是保证系统的一致性 不做undo系统就不会知道之前的状态redo就无从谈起 所以instance crash recovery 的时候总是先rollforward 再rollback undo 回退段中的数据是以回退条目方式存储回退条目=块信息(在事务中发生改动的块的编号)+在事务提交前存储在块中的数据 在每一个回退段中oracle都为其维护一张事务表 在事务表中记录着与该回退段中所有回退条目相关的事务编号(事务SCN&回退条目) redo 重做记录由一组变更向量组成每个变更变量中记录了事务对数据库中某个块所做的修改

当用户提交一条commit语句时LGWR进程会立刻将一条提交记录写入到重做日志文件中然后再开始写入与该事务相关的重做信息 #事务提交成功后Oracle将为该事备生成一个系统变更码(SCN)事务的SCN将同时记录在它的提交记录和重做记录中

commit 提交事务前完成的工作

·在SGA区的回退缓存中生成该事务的回退条目在回退条目中保存有该事务所修改的数据的原始版本

·在SGA区的重做日志缓存中生成该事务的重做记录重做记录中记载了该事务对数据块所进行的修改并且还记载了对回退段中的数据块所进行的修改缓存中的重做记录有可能在事务提交之前就写入硬盘中

·在SGA区的数据库缓丰中记录了事务对数据库所进行的修改这些修改也有可能在事务提交之前就写入硬盘中

提交事务时完成的工作

·在为该事务指定的回退段中的内部事务表内记录下这个事务已经被提交并且生成一个惟一的SCN记录在内部事务表中用于惟一标识这个事务

·LGWR后进进程将SGA区重做日志缓存中的重做记录写入联机重做日志文件在写入重做日志的同时还将写入该事务的SCN

·Oracle服务进程释放事务所使用的所有记录锁与表锁

·Oracle通知用户事务提交完成

·Oracle将该事务标记为已完成

rollback 回退事务完成的工作

·Oracle通过使用回退段中的回退条目撤销事务中所有SQL语句对数据库所做的修改

·Oracle服务进程释放事务所使用的所有锁

·Oracle通知事务回退成功

·Oracle将该事务标记为已完成

举个例子 insert into a(id) values();(redo) 这条记录是需要回滚的回滚的语句是delete from a where id = ;(undo) 试想想看如果没有做insert into a(id) values();(redo) 那么delete from a where id = ;(undo)这句话就没有意义了 现在看下正确的恢复: 先insert into a(id) values();(redo) 然后delete from a where id = ;(undo) 系统就回到了原先的状态没有这条记录了

上一篇:在不安装Oracle客户端的情况下进行系统移植

下一篇:Oracle11g新特性之:数据压缩技术