作者:dbtan |【转载时请以超链接形式标明文章出处作者信息】


commit做了什么?

当完成事务操作,发出commit命令之后,随后会收到一个反馈Commit complete

dbtan@NEI> insert into emp select * from emp;
128 rows created.
dbtan@NEI> commit;
Commit complete.

提交完成,这个提示意味着Oracle已经将此时间点之前的Redo写入重做日志文件件,这个日志写完成之后,Oracle可以释放用户去执行其他任务。如果此后发生数据库崩溃,那么Oracle可以从重做日志文件中恢复这些提交过的数据,从而保证提交成功的数据不会丢失。

解释:
为什么COMMIT的响应时间相当“平”,而不论事务大小呢?
    在数据库中执行COMMIT之前,困难的工作都已经做了。我们已经修改了数据库中的数据,所以99.9%的工作都已经完成。例如,已经发生了以下操作:
    ·已经在SGA中生成了undo块。
    ·已经在SGA中生成了已修改数据块。
    ·已经在SGA中生成了对于前两项的缓存redo。
    ·取决于前三项的大小,以及这些工作花费的时间,前面的每个数据(或某些数据)可能已经刷新输出到磁盘。
    ·已经得到了所需的全部锁。
执行COMMIT时,余下的工作只是:
    ·为事务生成一个SCN。如果你还不熟悉SCN,起码要知道,SCN是Oracle使用的一种简单的计时机制,用于保证事务的顺序,并支持失败恢复。SCN还用于保证数据库中的读一致性和检查点。可以把SCN看作一个钟摆,每次有人COMMIT时,SCN都会增1.
    ·LGWR将所有余下的缓存重做日志条目写到磁盘,并把SCN记录到在线重做日志文件中。这一步就是真正的COMMIT。如果出现了这一步,即已经提交。事务条目会从V$TRANSACTION中“删除”,这说明我们已经提交。
    ·V$LOCK中记录这我们的会话持有的锁,这些锁都将被释放,而排队等待这些锁的每一个人都会被唤醒,可以继续完成他们的工作。
    ·如果事务修改的某些块还在缓冲区缓存中,则会以一种快速的模式访问并“清理”。块清除(Block cleanout)是指清除存储在数据库块首部的与锁相关的信息。实质上讲,我们在清除块上的事务信息,这样下一个访问这个块的人就不用再这么做了。我们采用一种无需生成重做日志信息的方式来完成块清除,这样可以省去以后的大量工作。

那么我们应该记住一个原则是:确保提交成功的数据不丢失。这个保证正是通过Redo来实现的。由此可以看到日志文件对于Oracle的重要,为了保证日志文件的安全,Oracle允许对重做日志文件进行镜像。

从Oracle 10g开始,如果设置了闪回恢复区(Flash Recovery Area),则Oracle缺省的就会对日志文件进行镜像。镜像的好处是当某个日志出现问题,另外一个日志仍然可用,可以保证数据不丢失,而且通常镜像存储于不同的硬盘,当某个存储出现故障时,另外的存储可以用于保证镜像日志的安全。

- The End -