引用学习啦,谢谢老师;;Oracle redo undo commit rollback剖析 收藏 刚才在逛一个网友的博客的时候发现了一篇关于REDO、UNDO、COMMIT、ROLLBAKC的文章。虽然内容可能不是特别全面,可是还是总结的挺好的,转过来方便将来学习。==================================================================================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 。做redo的目的是使系统恢复到系统崩溃前(关机前)的状态,再进行undo是保证系统的一致性。 不做redo,系统就不会知道之前的状态,undo就无从谈起 。所以instance crash recovery 的时候总是先rollforward,再rollback undo 回退段中的数据是以“回退条目”方式存储。 回退条目=块信息(在事务中发生改动的块的编号)+在事务提交前存储在块中的数据 在每一个回退段中oracle都为其维护一张“事务表” 在事务表中记录着与该回退段中所有回退条目相关的事务编号(事务SCN&回退条目) redo 重做记录由一组“变更向量”组成。 每个变更变量中记录了事务对数据库中某个块所做的修改。 当用户提交一条commit语句时,LGWR进程会立刻将一条提交记录写入到重做日志文件中,然后再开始写入与该事务相关的重做信息。 事务提交成功后,Oracle将为该事备生成一个系统变更码(SCN)。事务的SCN将同时记录在它的提交记录和重做记录中。 commit 的开销存在两个因素: A. 显然会增加与数据库的往返通信。如果每个记录都提交,生成的往返通信量就会大得多。B. 每次提交时,必须等待redo写至磁盘。这会导致“等待”。在这种情况下,等待成为“日志文件同步”(log file sysnc)提交事务(COMMIT)前完成的工作: #在SGA区的回退缓存中生成该事务的回退条目。在回退条目中保存有该事务所修改的数据的原始版本。 #在SGA区的重做日志缓存中生成该事务的重做记录。重做记录中记载了该事务对数据块所进行的修改,并且还记载了对回退段中的数据块所进行的修改。缓存中的重做记录有可能在事务提交之前就写入硬盘中。 #在SGA区的数据库缓丰中记录了事务对数据库所进行的修改。这些修改也有可能在事务提交之前就写入硬盘中。 提交事务(COMMIT)时完成的工作: #在为该事务指定的回退段中的内部事务表内记录下这个事务已经被提交,并且生成一个惟一的SCN记录在内部事务表中,用于惟一标识这个事务。 #LGWR后进进程将SGA区重做日志缓存中的重做记录写入联机重做日志文件。在写入重做日志的同时还将写入该事务的SCN。 #Oracle服务进程释放事务所使用的所有记录锁与表锁。 #Oracle通知用户事务提交完成。 #Oracle将该事务标记为已完成。 注意在oracle工作期间,LGWR并非缓存着你所做的所有工作;实际上,随着你的工作的进行,LGWR会在后台曾量式地刷新输出重做日志缓冲区的内容到在线重做日志文件中,这样做是为了避免COMMIT等待很长时间来一次性刷新输出所有的redo。直到commit执行,LGWR才将所有余下的缓存重做日志条目写至磁盘,并把SCN记录到在线重做日志文件中。这一部就是真正的COMMIT,此时事务条目会从V$TRANSACTION中删除,这说明我们已经提交。rollback 回退事务完成的工作: ·Oracle通过使用回退段中的回退条目,撤销事务中所有SQL语句对数据库所做的修改。 ·Oracle服务进程释放事务所使用的所有锁 ·Oracle通知事务回退成功。 ·Oracle将该事务标记为已完成 举个例子: insert into a(id) values(1);(redo) 这条记录是需要回滚的。 回滚的语句是delete from a where id = 1;(undo) 试想想看。如果没有做insert into a(id) values(1);(redo) 那么delete from a where id = 1;(undo)这句话就没有意义了。 现在看下正确的恢复: 先insert into a(id) values(1);(redo) 然后delete from a where id = 1;(undo) 系统就回到了原先的状态,没有这条记录了。 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wh62592855/archive/2009/10/26/4730722.aspx
该事务会一会挂在那里 占用大量系统资源 比如说锁和还原空间
2
这个就要看你自己是如何操作的了 导入到哪里就在哪里
3
应该不会 除非数据库突然出现故障
4
如果过了一天你还commit成功了 那么和正常的commit没什么区别 都会永久计入数据库
问题二:没有commit的情况下(已解锁),导入的数据放哪儿去呢?
刚才在逛一个网友的博客的时候发现了一篇关于REDO、UNDO、COMMIT、ROLLBAKC的文章。虽然内容可能不是特别全面,可是还是总结的挺好的,转过来方便将来学习。==================================================================================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 。做redo的目的是使系统恢复到系统崩溃前(关机前)的状态,再进行undo是保证系统的一致性。
不做redo,系统就不会知道之前的状态,undo就无从谈起 。所以instance crash recovery 的时候总是先rollforward,再rollback undo
回退段中的数据是以“回退条目”方式存储。
回退条目=块信息(在事务中发生改动的块的编号)+在事务提交前存储在块中的数据 在每一个回退段中oracle都为其维护一张“事务表”
在事务表中记录着与该回退段中所有回退条目相关的事务编号(事务SCN&回退条目) redo
重做记录由一组“变更向量”组成。
每个变更变量中记录了事务对数据库中某个块所做的修改。
当用户提交一条commit语句时,LGWR进程会立刻将一条提交记录写入到重做日志文件中,然后再开始写入与该事务相关的重做信息。 事务提交成功后,Oracle将为该事备生成一个系统变更码(SCN)。事务的SCN将同时记录在它的提交记录和重做记录中。 commit 的开销存在两个因素:
A. 显然会增加与数据库的往返通信。如果每个记录都提交,生成的往返通信量就会大得多。B. 每次提交时,必须等待redo写至磁盘。这会导致“等待”。在这种情况下,等待成为“日志文件同步”(log file sysnc)提交事务(COMMIT)前完成的工作:
#在SGA区的回退缓存中生成该事务的回退条目。在回退条目中保存有该事务所修改的数据的原始版本。
#在SGA区的重做日志缓存中生成该事务的重做记录。重做记录中记载了该事务对数据块所进行的修改,并且还记载了对回退段中的数据块所进行的修改。缓存中的重做记录有可能在事务提交之前就写入硬盘中。
#在SGA区的数据库缓丰中记录了事务对数据库所进行的修改。这些修改也有可能在事务提交之前就写入硬盘中。 提交事务(COMMIT)时完成的工作:
#在为该事务指定的回退段中的内部事务表内记录下这个事务已经被提交,并且生成一个惟一的SCN记录在内部事务表中,用于惟一标识这个事务。
#LGWR后进进程将SGA区重做日志缓存中的重做记录写入联机重做日志文件。在写入重做日志的同时还将写入该事务的SCN。
#Oracle服务进程释放事务所使用的所有记录锁与表锁。
#Oracle通知用户事务提交完成。
#Oracle将该事务标记为已完成。 注意在oracle工作期间,LGWR并非缓存着你所做的所有工作;实际上,随着你的工作的进行,LGWR会在后台曾量式地刷新输出重做日志缓冲区的内容到在线重做日志文件中,这样做是为了避免COMMIT等待很长时间来一次性刷新输出所有的redo。直到commit执行,LGWR才将所有余下的缓存重做日志条目写至磁盘,并把SCN记录到在线重做日志文件中。这一部就是真正的COMMIT,此时事务条目会从V$TRANSACTION中删除,这说明我们已经提交。rollback 回退事务完成的工作:
·Oracle通过使用回退段中的回退条目,撤销事务中所有SQL语句对数据库所做的修改。
·Oracle服务进程释放事务所使用的所有锁
·Oracle通知事务回退成功。
·Oracle将该事务标记为已完成 举个例子:
insert into a(id) values(1);(redo)
这条记录是需要回滚的。
回滚的语句是delete from a where id = 1;(undo) 试想想看。如果没有做insert into a(id) values(1);(redo)
那么delete from a where id = 1;(undo)这句话就没有意义了。 现在看下正确的恢复:
先insert into a(id) values(1);(redo)
然后delete from a where id = 1;(undo)
系统就回到了原先的状态,没有这条记录了。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wh62592855/archive/2009/10/26/4730722.aspx
问题二:导入的数据放哪儿去呢?
问题三:数据库进程会不会自动放弃这个未commit事务吗?
问题四:过了一天后,我再COMMIT,数据库系统是否会永久载入数据? ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
这些数据会跟着会话(session)走的。如果是直接退出这个会话,这个事务隐含的是提交。
那么所有数据将提交。
如果session 是被异常退出的(比如说你把网线拔掉了导致会话退出),数据库的pmon进程将负责回滚事务。
因为ORACLE在COMMIT之前已经把该写的东西写到DISK中了,
我们COMMIT只是
1,产生一个SCN给我们TRANSACTION,SCN简单理解就是给TRANSACTION排队,以便恢复和保持一致性。
2,REDO写REDO到DISK中(LGWR,这就是log file sync),记录SCN在ONLINE REDO LOG,当这一步发生时,我们可以说事实上已经提交了,这个TRANSACTION已经结束(在V$TRANSACTION里消失了)
3,SESSION所拥有的LOCK(V$LOCK)被释放。
4,Block Cleanout(这个问题是产生ORA-01555: snapshot too old的根本原因) ROLLBACK ROLLBACK和COMMIT正好相反,ROLLBACK的时间和TRANSACTION的大小有直接关系。因为ROLLBACK必须物理上恢复数据。COMMIT之所以快,是因为ORACLE在COMMIT之前已经作了很多工作(产生UNDO,修改BLOCK,REDO,LATCH分配), ROLLBACK慢也是基于相同的原因。
ROLLBACK会
1,恢复数据,DELETE的就重新INSERT,INSERT的就重新DELETE,UPDATE的就再UPDATE。
2,RELEASE LOCK ROLLBACK要比COMMIT消耗更多资源,因为ORACLE认为你一旦做数据更新,那么就意味着你要COMMIT(其他数据库不全是这种设计理念,比如DB2),所以在你更新数据的时候就做了大量的工作,这也可以理解为什么不建议用TABLE来做TEMPORARY TABLE。(TEMP TABLE消耗的REDO比固定表在INSERT时要少很多 ,UPDATE时差不多是1/2,
但是DELETE却相差无几) REDO 产生REDO 越多,你的系统越慢,不但影响你自己的SESSION,还影响其他SESSION,LGWR管理REDO,并且是TRANSACTION的结束标志。 首先要知道怎么监控REDO,当然,SET AUTOTRACE ON可以,不过只能监控DML语句,而像PROCEDURE则无法监视。那么我们就需要观察字典了,V$MYSTAT, V$STATNAME,