oracle的redo和undo

1 redo

1.1 redo是什么

oracle数据库几乎所有的操作都会产生redo日志。redo日志可以分为在线redo日志和归档redo日志。当数据库实例失败时,数据库会使用redo日志恢复数据。

1.2 在线重做日志和归档重做日志

1.2.1 在线重做日志

数据库的操作产生的redo日志会先存放在在线重做日志中。在线重做日志在oracle中至少有两组重做日志,每组重做日志包含一个或者多个在线重做日志文件,同一组内的在线重做日志内容完全一样。日志切换是指当一组在线重做日志写满时,oracle清空下一组在线重做日志并在下一组写入重做日志。所以,在线重做日志是循环使用的。

1.2.2 归档重做日志

如果数据库开启了日志归档,当一组在线重做日志填满时,就会将这组在线重做日志进行归档,这些归档的日志就是归档重做日志。

1.3 实例恢复和介质恢复

实例恢复一般是指数据库实例发生故障,例如系统突然崩溃,使用shutdown abort关闭数据数据库。数据库重启时就会自动进行实例恢复。实例恢复主要使用在线重做日志进行恢复。
介质恢复是指运行数据库的磁盘发生损坏,需要使用物理备份进行恢复。物理备份包括数据库某个时间的快照以及归档重做日志,在线重做日志。

2 undo

2.1 undo是什么

当我们对数据进行修改时,就会产生undo,undo存储在undo段中。我们就是使用undo对修改但未提交的数据进行恢复的。

2.2 undo的作用

  1. 使用rollback时,利用undo将数据恢复到事务之前的样子
  2. 为oracle的读一致性提供数据保障
  3. flashback table使用undo将表数据恢复到之前某个时间点

3 提交(commit)和回滚(rollback)处理

3.1 提交(commit)

3.1.1 提交前的工作

通常commit是一个快速的操作,其处理时间和事务大小无关。因此,我们应该尽量避免将一个事务拆分进行多次提交。commit是一个快速的操作,这是因为大部分事务的工作在commit之前已经完成

  • 在SGA中生成已修改的数据块
  • 在SGA中生成undo块
  • 在SGA中生成前两项的redo缓存
  • 如果前面执行的比较久,可能SGA中一些缓存数据已经写入磁盘
  • 获取所需要的锁

3.1.2 当进行commit时,只需要完成剩下的工作

  • 为事务生成一个SCN。SCN是oracle的一个序列机制,用来保证事务的顺序,并用来支持实例恢复。此外,它还用于oracle的读一致性和检查点。每commit一次,SCN就会增加
  • LWGR将还在redo缓存中的redo写入在线重做日志。并将SCN记录在在线重做日志中。这一步才是数据库真正的commit。此时事务条目会从V$TRANSACTION中被“删除”
  • 释放V$lock中记录该事务的会话中的锁,从而让等待锁的其他事务继续进行。
  • 如果被修改的块还在数据库高速缓存中,oracle会进行块清除。块清除是指清除数据库块首部的一些锁信息。
    从以上可以看出,commit需要做的工作中,耗时最长的是将redo缓存中的redo写入在线重做日志。如果,commit进行多次,则需要进行多次等待。需要注意的是,PL/SQL对commit是特殊处理的。如果一个PL/SQL中有多个commit,数据库不会在PL/SQL进行commit时等待redo缓存中的redo写入在线重做日志,而是立刻返回。但是,当PL/SQL执行完,将控制权返回客户端前,会等待LGWR将对应的所有redo缓存写入磁盘。虽然如此,也不建议在PL/SQL中使用多次commit。

3.2 回滚(rollback)

当我们进行rollback操作时,会做如下工作

  • 撤销所有修改。oracle使用undo数据撤销所做的修改。并将对应undo数据标记为已应用。例如之前插入了一条数据,ROLLBACK会将其删除。

  • 释放V$lock中记录该事务的会话中的锁,从而让等待锁的其他事务继续进行。

    从以上工作可以看出,rollback的操作的工作量会比commit大很多。commit最大的工作量仅仅是将redo缓存写入磁盘。

4 临时表的redo和undo

临时表(GLOBAL TEMPORARY TABLE)中的事务操作不会产生事务本身的redo,但是会产生undo。undo也会有对应redo,因此临时表也会redo。但是可以通过设置参数TEMP_UNDO_ENABLED来将临时表的undo放在临时表空间中,由于临时表空间的任何数据变更都不会产生redo,所以当这个参数设置为TRUE时,任何临时表上的DML都会产生很少甚至不产生redo。
我们可以在会话和系统级别设置参数TEMP_UNDO_ENABLED,下面我们将这个参数在会话级别设置为 TRUE。
alter session set temp_undo_enabled=true;

5 数据库如何利用redo进行实例恢复

一个事务commit成功是指该事务对应的redo日志已经从redo缓存中写入在线重做日志。数据库进行实例恢复时,会读取在线重做日志的数据。
第一步是cache recovery,SMON根据最后一次检查点后的在线重做日志执行日志内容,往前滚。这一步完成后,恢复所有commit的数据。在线重做日志中可能有一些没有commit的redo日志,因此这一步完成后,数据库高速缓存中也会有一些未提交的数据库。
第二步是Transaction Recovery,根据在线重做日志的undo回滚未提交的数据。

热门相关:史上第一密探   首辅娇娘   单身汉偷喝隔壁的母乳   侯门弃女:妖孽丞相赖上门   极品妖孽归来