精华内容
下载资源
问答
  • ORACLE redo undo.docx

    2021-08-20 15:19:15
    Oracle redo undo的说明解释
  • Oracle 查看 使用 UNDO 段的事务 脚本

    千次阅读 2012-06-18 18:25:36
    Undo 表空间管理的说明,参考:Oracle undo 表空间管理http://blog.csdn.net/tianlesoftware/article/details/5689558我们可以使用如下脚本查看Oracle undo segment段的信息:/* Formatted on 2012/6/18 18:10:55 ...


    Undo 表空间管理的说明,参考:

    Oracle undo 表空间管理

    http://blog.csdn.net/tianlesoftware/article/details/5689558


    我们可以使用如下脚本查看Oracle undo segment段的信息:

    /* Formatted on 2012/6/18 18:10:55 (QP5 v5.185.11230.41888) */
    SELECT T1.USN,
           T2.NAME,
           T1.STATUS,
           T1.LATCH,
           T1.EXTENTS,
           T1.WRAPS,
           T1.EXTENDS
      FROM V$ROLLSTAT T1, V$ROLLNAME T2
     WHERE T1.USN = T2.USN;
    


     

     

    当Undo 表空间出现故障的时候,我们就会需要注意这些undo segment 信息:

    Currentonline Redo 和 Undo 损坏的处理方法

    http://www.cndba.cn/Dave/article/525

     

    结合v$session 和v$transaction 视图就可以确认每个事务使用使用undo segment的情况,当undo 表空间使用异常的时候,就可以使用如下的脚本来检查事务使用undo segment的情况:


    /* Formatted on 2012/6/18 13:28:55 (QP5 v5.185.11230.41888) */
      SELECT S.SID,
             S.USERNAME,
             U.NAME,
             Q.SQL_TEXT,
             Q.HASH_VALUE,
             T.UBABLK
        FROM V$TRANSACTION T,
             V$ROLLSTAT R,
             V$ROLLNAME U,
             V$SESSION S,
             V$SQL Q
       WHERE     S.TADDR = T.ADDR
             AND T.XIDUSN = R.USN
             AND R.USN = U.USN
             AND Q.HASH_VALUE =
                    DECODE(S.SQL_HASH_VALUE,
                            NULL, S.PREV_HASH_VALUE,
                            S.SQL_HASH_VALUE)
    ORDER BY S.USERNAME;
    


     

     

     

     


    -------------------------------------------------------------------------------------------------------

    QQ:492913789

    Email:ahdba@qq.com

    Blog:  http://www.cndba.cn/dave

    Weibo:            http://weibo.com/tianlesoftware

    Twitter: http://twitter.com/tianlesoftware

    Facebook: http://www.facebook.com/tianlesoftware

    Linkedin: http://cn.linkedin.com/in/tianlesoftware

     

     

    -------加群需要在备注说明Oracle表空间和数据文件的关系,否则拒绝申请----

    DBA1 群:62697716(满);   DBA2 群:62697977(满)  DBA3 群:62697850(满)  

    DBA 超级群:63306533(满);  DBA4 群:83829929   DBA5群: 142216823

    DBA6 群:158654907    DBA7 群:172855474   DBA总群:104207940

    展开全文
  • oracle 收缩undo表空间

    2014-02-18 09:27:20
    oracle 收缩undo表空间,需要收缩Undo表空间时特别有用。
  • oracle undo

    2017-10-02 08:19:54
    oracle undo的更深一层的东西,能解决一定的undo问题。
  • oracle redo undo

    千次阅读 2011-08-17 01:33:31
    oracle redo undo  2009-08-11 20:22:10| 分类: 系统管理技术 | 标签: |字号大中小 订阅   通常对undo有一个误解,认为undo用于数据库物理地恢复到执行语句或事务之前的样子,但实际上并非如此...
      
    

    oracle redo undo  

    2009-08-11 20:22:10|  分类: 系统管理技术 |  标签: |字号 订阅

     

    通常对undo有一个误解,认为undo用于数据库物理地恢复到执行语句或事务之前的样子,但实际上并非如此。数据库只是逻辑地恢复到原来的样子,所有修改都被逻辑地取消,但是数据结构以及数据库块本身在回滚后可能大不相同。原因在于:在所有多用户系统中,可能会有数十、数百甚至数千个并发事务。数据库的主要功能之一就是协调对数据的并发访问。也许我们的事务在修改一些块,而一般来讲往往会有许多其他的事务也在修改这些块。因此,不能简单地将一个块放回到我们的事务开始前的样子,这样会撤销其他人(其他事务)的工作!

       

    9.3 redo和undo如何协作?

    有意思的是,尽管undo信息存储在undo表空间或undo段中,但也会受到redo的保护。换句话说,会把undo数据当成是表数据或索引数据一样,对undo的修改会生成一些redo,这些redo将计入日志。为什么会这样呢?稍后在讨论系统崩溃时发生的情况时将会解释它,到时你会明白了。将undo数据增加到undo段中,并像其他部分的数据一样在缓冲区缓存中得到缓存。另外这些redo信息还用于在实例恢复时重建SGA内存的状态。

     

    9.3.1 COMMIT做什么?

    COMMIT通常是一个非常快的操作,而不论事务大小如何。你可能认为,一个事务越大(换句话说,它影响的数据越多),COMMIT需要的时间就越长。不是这样的。不论事务有多大,COMMIT的响应时间一般都很“平”(flat,可以理解为无高低变化)。这是因为COMMIT并没有太多的工作去做,不过它所做的确实至关重要。

    这一点很重要,之所以要了解并掌握这个事实,原因之一是:这样你就能心无芥蒂地让事务有足够的大小。一种错误的信念认为分批提交可以节省稀有的系统资源,而实际上这只是增加了资源的使用。如果只在必要时才提交(即逻辑工作单元结束时),不仅能提高性能,还能减少对共享资源的竞争(日志文件、各种内部闩等)。

    分批提交COMMIT的开销存在两个因素:

    l         显然会增加与数据库的往返通信。如果每个记录都提交,生成的往返通信量就会大得多。

    l         每次提交时,必须等待redo写至磁盘。这会导致“等待”。在这种情况下,等待称为“日志文件同步”(log file sync)。

     

    为什么COMMIT的响应时间相当“平”,而不论事务大小呢?在数据库中执行COMMIT之前,困难的工作都已经做了。我们已经修改了数据库中的数据,所以99.9%的工作都已经完成。例如,已经发生了以下操作:

    l         已经在SGA中生成了undo块。

    l         已经在SGA中生成了已修改数据块。

    l         已经在SGA中生成了对于前两项的缓存redo。

    l         取决于前三项的大小,以及这些工作花费的时间,前面的每个数据(或某些数据)可能已经刷新输出到磁盘。

    l         已经得到了所需的全部锁。

    执行COMMIT时,余下的工作只是:

    l         为事务生成一个SCN。如果你还不熟悉SCN,起码要知道,SCN是Oracle使用的一种简单的计时机制,用于保证事务的顺序,并支持失败恢复。SCN还用于保证数据库中的读一致性和检查点。可以把SCN看作一个钟摆,每次有人COMMIT时,SCN都会增1.

    l         LGWR将所有余下的缓存重做日志条目写到磁盘,并把SCN记录到在线重做日志文件中。这一步就是真正的COMMIT。如果出现了这一步,即已经提交。事务条目会从V$TRANSACTION中“删除”,这说明我们已经提交。

    l         V$LOCK中记录这我们的会话持有的锁,这些所都将被释放,而排队等待这些锁的每一个人都会被唤醒,可以继续完成他们的工作。

    l         如果事务修改的某些块还在缓冲区缓存中,则会以一种快速的模式访问并“清理”。块清除(Block cleanout)是指清除存储在数据库块首部的与锁相关的信息。实质上讲,我们在清除块上的事务信息,这样下一个访问这个块的人就不用再这么做了。我们采用一种无需生成重做日志信息的方式来完成块清除,这样可以省去以后的大量工作(在下面的“块清除”一节中将更全面地讨论这个问题)。

     

    可以看到,处理COMMIT所要做的工作很少。其中耗时最长的操作要算LGWR执行的活动(一般是这样),因为这些磁盘写是物理磁盘I/O。不过,这里LGWR花费的时间并不会太多,之所以能大幅减少这个操作的时间,原因是LGWR一直在以连续的方式刷新输出重做日志缓冲区的内容。在你工作期间,LGWR并非缓存这你做的所有工作;实际上,随着你的工作的进行,LGWR会在后台增量式地刷新输出重做日志缓冲区的内容。这样做是为了避免COMMIT等待很长时间来一次性刷新输出所有的redo。

    因此,即使我们有一个长时间运行的事务,但在提交之前,它生成的许多缓存重做日志已经刷新输出到磁盘了(而不是全部等到提交时才刷新输出)。这也有不好的一面,COMMIT时,我们必须等待,直到尚未写出的所有缓存redo都已经安全写到磁盘上才行。也就是说,对LGWR的调用是一个同步(synchronous)调用。尽管LGWR本身可以使用异步I/O并行地写至日志文件,但是我们的事务会一直等待LGWR完成所有写操作,并收到数据都已在磁盘上的确认才会返回。

    前面我提高过,由于某种原因,我们用的是一个Java程序而不是PL/SQL,这个原因就是PL/SQL提供了提交时优化(commit-time optimization)。我说过,LGWR是一个同步调用,我们要等待它完成所有写操作。在Oracle 10g Release 1及以前版本中,除PL/SQL以外的所有编程语言都是如此。PL/SQL引擎不同,要认识到直到PL/SQL例程完成之前,客户并不知道这个PL/SQL例程中是否发生了COMMIT,所以PL/SQL引擎完成的是异步提交。它不会等待LGWR完成;相反,PL/SQL引擎会从COMMIT调用立即返回。不过,等到PL/SQL例程完成,我们从数据库返回客户时,PL/SQL例程则要等待LGWR完成所有尚未完成的COMMIT。因此,如果在PL/SQL中提交了100次,然后返回客户,会发现由于存在这种优化,你只会等待LGWR一次,而不是100次。这是不是说可以在PL/SQL中频繁地提交呢?这是一个很好或者不错的主意吗?不是,绝对不是,在PL/SQ;中频繁地提交与在其他语言中这样做同样糟糕。指导原则是,应该在逻辑工作单元完成时才提交,而不要在此之前草率地提交。

        COMMIT是一个“响应时间很平”的操作,虽然不同的操作将生成不同大小的redo,即使大小相差很大或者说无论生成多少redo,但也并不会影响提交(COMMIT)的时间或者说提交所用的时间都基本相同。

     

    9.3.2 ROLLBACK做什么?

    一般地回滚时间是所修改数据量的一个函数。回滚操作的开销很大,这是可以想像的,因为ROLLBACK必须物理地撤销我们所做的工作。类似于COMMIT,必须完成一系列操作。在到达ROLLBACK之前,数据库已经做了大量的工作。再复习一遍,可能已经发生的操作如下:

    l         已经在SGA中生成了undo块。

    l         已经在SGA中生成了已修改数据块。

    l         已经在SGA中生成了对于前两项的缓存redo。

    l         取决于前三项的大小,以及这些工作花费的时间,前面的每个数据(或某些数据)可能已经刷新输出到磁盘。

    l         已经得到了所需的全部锁。

     

    ROLLBACK时,要做以下工作:

    l         撤销已做的所有修改。其完成方式如下:从undo段读回数据,然后实际上逆向执行前面所做的操作,并将undo条目标记为已用。如果先前插入了一行,ROLLBACK会将其删除。如果更新了一行,回滚就会取消更新。如果删除了一行,回滚将把它再次插入。

    l         会话持有的所有锁都将释放,如果有人在排队等待我们持有的锁,就会被唤醒。

     

    1.4   分析redo

    作为一名开发人员,应该能够测量你的操作生成了多少redo,这往往很重要。生成的redo越多,你的操作花费的时间就越长,整个系统也会越慢。你不光在影响你自己的会话,还会影响每一个会话。redo管理是数据库中的一个串行点。任何Oracle实例都只有一个LGWR,最终所有事务都会归于LGWR,要求这个进程管理它们的redo,并BOMMIT其事务,LGWR要做的越多,系统就会越慢。

     

    9.4.1 测量redo

    要查看生成的redo量相当简单,这在本章前面已经见过。我使用了SQL*Plus的内置特性AUTOTRACE。不过AUTOTRACE只能用于简单的DML,对其他操作就力所不能及了,例如,它无法查看一个存储过程调用做了什么。为此,我们需要访问两个动态性能视图:

    l         V$MYSTAT,其中有会话的提交信息。

    l         V$STATNAME,这个视图能告诉我们V$MYSTAT中的每一行表示什么(所查看的统计名)。

     

    9.4.2 redo生成和BEFORE/AFTER触发器

    l         BEFORE或AFTER触发器不影响DELETE生成的redo。

    l         在Oracle9i Release 2 及以前版本中,BEFORE或AFTER触发器会使INSERT生成同样数量的额外redo。在Oracle 10g中,则不会生成任何额外的redo。

    l         在Oracle9i Release 2及以前的所有版本中,UPDATE生成的redo只受BEFORE触发器的影响。AFTER触发器不会增加任何额外的redo。不过,在Oracle 10g中,情况又有所变化。具体表现为:

    Ø         总的来讲,如果一个表没有触发器,对其更新期间生成的redo量总是比Oracle9i及以前版本中要少。看来这是Oracle着力解决的一个关键问题:对于触发器的表,要减少这种表更新所生成的redo量。

    Ø         在Oracle 10g中,如果表有一个BEFORE触发器,则其更新期间生成的redo量比9i中更大。

    Ø         如果表有AFTER触发器,则更新所生成的redo量与9i中一样。

     

    在Oracle9i Release 2和Oracle 10g这两个版本之间,触发器对事务实际生成的redo存在不同的影响。可以很容易地看到这些变化:

    l         是否存在触发器对DELETE没有影响(DELETE还是不受触发器的影响)。

    l         在Oracle9i Release 2及以前版本中,INSERT会受到触发器的影响。初看上去,你可能会说,Oracle 10g优化了INSERT,所以它不会受到影响,但是再看看Oracle 10g中无触发器时生成的redo总量,你会看到,这与Oracle9i Release 2及以前版本中有触发器时生成的redo量是一样的。所以,并不是Oracle 10g减少了有触发器时INSERT生成的redo量,而是所生成的redo量是常量(有无触发器都会生成同样多的redo),无触发器时,Oracle 10g中的INSERT比Oracle9i中生成的redo要多。

    l         在9i中,UPDATE会受BEFORE触发器的影响,但不受AFTER触发器的影响。初看上去,似乎Oracle 10g中改成了两个触发器都会影响UPDATE。但是通过进一步的分析,可以看到,实际上Oracle 10g中无触发器是UPDATE生成的redo有所下降,下降的量正是有触发器时UPDATE生成的redo量。所用与9i和10g中INSERT的情况恰恰相反,与9i相比,没有触发器时Oracle 10g中UPDATE生成的redo量会下降。

     

    触发器对redo生成的影响

    DML操作

    AFTER触发器(10g以前)

    BEFORE触发器(10g以前)

    AFTER触发器(10g)

    BEFORE触发器(10g)

    DELETE

    不影响

    不影响

    不影响

    不影响

    INSERT

    增加redo

    增加redo

    常量redo

    常量redo

    UPDATE

    增加redo

    不影响

    增加redo

    增加redo

     

    现在你应该知道怎么来估计redo量,这是每一个开发人员应该具备的能力。你可以:

    l         估计你的“事务”大小(你要修改多少数据)。

    l         在要修改的数据量基础上再加10%~20%的开销,具体增加多大的开销取决于你要修改的行数。修改行越多,增加的开销就越小。

    l         对于UPDATE,要把这个估计值加倍。

     

    9.4.3 我能关掉重做日志生成吗?

    答案很简单:不能。因为重做日志对于数据库至关重要;它不是开销,不是浪费。

     

    1. 在SQL中设置NOLOGGING

    有些SQL语句和操作支持使用NOLOGGING子句。这并不是说:这个对象的所有操作在执行时都不生成重做日志,而是说有些特定操作生成的redo会比平常(即不使用NOLOGGING子句时)少得多。

    在NOARCHIVELOG模式的数据库中,除了数据字典的修改外,CREATE TABLE不会记录日志。(为什么?CREATE TABLE难道不是数据字典操作?)如果你想在NOARCHIVELOG模式的数据库上看到差别,可以把对表T的DROP TABLE和CREATE TABLE换成DROP INDEX和CREATE INDEX。默认情况下,不论数据库以何种模式运行,这些操作都会生成日志。

     

    关于NOLOGGING操作,需要注意以下几点:

    l         事实上,还是会生成一定数量的redo。这些redo的作用是保护数据字典。这是不可避免的。与以前(不使用NOLOGGING)相比,尽管生成的redo量要少多了,但是确实会有一些redo。

    l         NOLOGGING不能避免所有后续操作生成redo。在前面的例子中,我创建的并非不生成日志的表。只是创建表(CREATE TABLE)这一个操作没有生成日志。所有后续的“正常“操作(如INSERT、UPDATE和DELETE)还是会生成日志。其他特殊的操作(如使用SQL*Loader的直接路径加载,或使用INSERT /*+ APPEND */语法的直接路径插入)不生成日志(除非你ALTER这个表,再次启用完全的日志模式)。不过,一般来说,应用对这个表执行的操作都会生成日志。

    l         在一个ARCHIVELOG模式的数据库上执行NOLOGGING操作后,必须尽快为受影响的数据文件建立一个新的基准备份,从而避免由于介质失败而丢失对这些对象的后续修改。实际上,我们并不会丢失后来做出的修改,因为这些修改确实在重做日志中;我们真正丢失的只是要应用这些修改的数据(即最初的数据)。

     

    2.在索引上设置NOLOGGING

    使用NOLOGGING选项有两种方法。你已经看到了前一种,也就是把NOLOGGING关键字潜在SQL命令中。另一种方法是在段(索引或表)上设置NOLOGGING属性,从而隐式地采用NOLOGGING模式来执行操作。

    如alter一个索引:

    ops$tkyte@ORA10G> alter index t_idx rebuild;

    Index altered.

    以后rebuild的时候只会生成少许日志,而不会生成大量的额外的日志。但是,现在这个索引没有得到保护(unprotected),如果它所在的数据文件失败而必须从一个备份恢复,我们就会丢失这个索引数据。了解这一点很重要。现在索引是不可恢复的,所以需要做一个备份。或者,DBA也可以干脆创建索引,因为完全可以从表数据直接创建索引。

     

    3. NOLOGGING小结

    可以采用NOLOGGING模式执行以下操作:

    l         索引的创建和ALTER(重建)。

    l         表的批量INSERT(通过/*+APPEND */提示使用“直接路径插入“。或采用SQL*Loader直接路径加载)。表数据不生成redo,但是所有索引修改会生成redo,但是所有索引修改会生成redo(尽管表不生成日志,但这个表上的索引却会生成redo!)。

    l         LOB操作(对大对象的更新不必生成日志)。

    l         通过CREATE TABLE AS SELECT创建表。

    l         各种ALTER TABLE操作,如MOVE和SPLIT。

    在一个ARCHIVELOG模式的数据库上,如果NOLOGGING使用得当,可以加快许多操作的速度,因为它能显著减少生成的重做日志量。

     

    9.4.4 为什么不能分配一个新日志?

    老是有人问我这个问题。这样做会得到一条警告消息(可以在服务器上的alert.log中看到):

    Thread 1 cannot allocate new log, sequence 1466

    Checkpoint not complete

    Current log# 3 seq# 1465 mem# 0: /home/ora10g/oradata/ora10g/redo03.log

    警告消息中也可能指出Archival required而不是Checkpoint not complete,但是效果几乎都一样。DBA必须当心这种情况。如果数据库试图重用一个在线重做日志文件,但是发现做不到,就会把这样一条消息写到服务器上的alert.log中。如果DBWR还没有完成重做日志所保护数据的检查点(checkpointing),或者ARCH还没有把重做日志文件复制到归档目标,就会发生这种情况。对最终用户来说,这个时间点上数据库实际上停止了。它会原

    地不动。DBWR或ARCH将得到最大的优先级以将redo块刷新输出的磁盘。完成了检查点或归档之后,一切又回归正常。

    如果你看到会话因为一个“日志文件切换”、“日志缓冲区空间”或“日志文件切换检查点或归档未完成”等待了很长时间,就很可能遇到了这个问题。

    要解决这个问题,有几种做法:

     

    l         让DBWR更快一些。让你的DBA对DBWR调优,为此可以启用ASYNC I/O、使用DBWR I/O从属进程,或者使用多个DBWR进程。看看系统产生的I/O,查看是否有一个磁盘(或一组磁盘)“太热”,相应地需要将数据散布开。这个建议对ARCH也适用。这种做法的好处是,你不用付出什么代价就能有所收获,性能会提高,而且不必修改任何逻辑/结构/代码。这种方法确实没有缺点。

    l         增加更多重做日志文件。在某些情况下,这会延迟Checkpoint not complete的出现,而且过一段时间后,可以把Checkpoint not complete延迟得足够长,使得这个错误可能根本不会出现(因为你给DBWR留出了足够的活动空间来建立检查点)。这个方法也同样适用于Archival required消息。这种方法的好处是可以消除系统中的“暂停”。其缺点是会消耗更多的磁盘空间,但是在此利远远大于弊。

    l         重新创建更大的日志文件。这会扩大填写在线重做日志与重用这个在线重做日志文件之间的时间间隔。如果重做日志文件的使用呈“喷射状”,这种方法同样适用于Archival required消息。倘若一段时间内会大量生成日志(如每晚加载、批处理等),其后一段数据却相当平静,如果有更大的在线重做日志,就能让ARCH在平静的期间有足够的时间“赶上来”。这种方法的优缺点与前面增加更多文件的方法是一样的。另外,它可能会延迟检查点的发生,由于(至少)每个日志切换都会发生检查点,而现在日志切换间隔会更大。

    l         让检查点发生得更频繁、更连续。可以使用一个更小的块缓冲区缓存(不太好),或者使用诸如FAST_START_MTTR_TARGET、LOG_CHECKPOINT_INTERVAL和LOG_CHECKPOINT_TIMEOUT之类的参数设置。这会强制DBWR更频繁地刷新输出脏块。这种方法的好处是,失败恢复的时间会减少。在线重做日志中应用的工作肯定更少。其缺点是,如果经常修改块,可能会更频繁地写至磁盘。缓冲区缓存本该更有效的,但由于频繁地写磁盘,会导致缓冲区缓存不能充分发挥作用,这可能会影响下一节将讨论的块清除机制。

     

    9.4.5 块清除

    在第6章中,我们曾经讨论过数据锁以及如何管理它们。我介绍了数据锁实际上是数据的属性,存储在块首部。这就带来一个副作用,下一次访问这个块时,可能必须“清理”这个块,换句话说,要将这些事务信息删除。这个动作会生成redo,并导致变脏(原本并不脏,因为数据本身没有修改),这说明一个简单的SELECT有可能生成redo,而且可能导致完成下一个检查点时将大量的块写至磁盘。不过,在大多数正常的情况下,这是不会发生的。如果系统中主要是小型或中型事务(OLTP),或者数据仓库会执行直接路径加载或使用DBMS_STATS在加载操作后分析表,你会发现块通常已经得到“清理”。如果还记得前面“COMMIT做什么?”一节中介绍的内容,应该知道,COMMIT时处理的步骤之一是:如果块还在SGA中,就要再次访问这些块,如果可以访问(没有别人在修改这些块),则对这些块完成清理。这个 活动称为提交清除(commit cleanout),即清除已修改块上事务信息。最理想的是,COMMIT可以完成块清除,这样后面的SELECT(读)就不必再清理了。只有块的UPDATE才会真正清除残余的事务信息,由于UPDATE已经在生成redo,所用注意不到这个清除工作。

    可以强制清除不发生来观察它的副作用,并了解提交清除是怎么工作的。在与我们的事务相关的提交列表中,Oracle会记录已修改的块列表。这些列表都有20个块,Oracle会根据需要分配多个这样的列表,直至达到某个临界点。如果我们修改的块加起来超过了块缓冲区缓存大小的10%,Oracle会停止为我们分配新的列表。例如,如果缓冲区缓存设置为可以缓存3,000个块,Oracle会为我们维护最多300个块(3,000的10%)。COMMIT时,Oracle会处理这些包含20个块指针的列表,如果块仍可用,它会执行一个很快的清理。所以,只要我们修改的块数没有超过缓存中总块数的10%,而且块仍在缓存中并且是可用的,Oracle就会在COMMIT时清理这些块。否则,它只会将其忽略(也就是说不清理)。

    如果你有如下的处理,就会受到块清除的影响:

    l         将大量新数据批量加载到数据仓库中;

    l         在刚刚加载的所有数据上运行UPDATE(产生需要清理的块);

    l         让人们查询这些数据。

     

     

    9.4.6 日志竞争

    l         redo放在一个慢速设备上:磁盘表现不佳。该购买速度更快的磁盘了。

    l         redo与其他频繁访问的文件放在同一个设备上。redo设计为要采用顺序写,而且要放在专用的设备上。如果系统的其他组件(甚至其他Oracle组件)试图与LGWR同时读写这个设备,你就会遭遇某种程度的竞争。在此,只要有可能,你就会希望确保LGWR拥有这些设备的独占访问权限。

    l         已缓冲方式装载日志设备。你在使用一个“cooked”文件系统(而不是RAW磁盘)。操作系统在缓冲数据,而数据库也在缓冲数据(重做日志缓冲区)。这种双缓冲会让速度慢下来。如果可能,应该以一种“直接”方式了装载设备。具体操作依据操作系统和设备的不同而有所变化,但一般都可以直接装载。

    l         redo采用了一种慢速技术,如RAID-5。RAID-5很合适读,但是用于写时表现则很差。前面已经了解了COMMIT期间会发生什么,我们必须等待LGWR以确保数据写到磁盘上。倘若使用的技术会导致这个工作变慢,这就不是一个好主意。

     

    9.4.7 临时表和redo/undo

    临时表不会为它们的块生成redo。因此,对临时表的操作不是“可恢复的” 。修改临时表中的一个块时,不会将这个修改记录到重做日志文件中。不过,临时表确实会生成 undo,而且这个 undo 会计入日志。因此,临时表也会生成一些redo。初看上去好像没有道理:为什么需要生成undo?这是因为你能回滚到事务中的一个 SAVEPOINT。由于undo数据必须建立日志,因此临时表会为所生成的undo生成一些重做日志。这样似乎很不好,不过没有你想像中那么糟糕。在临时表上运行的 SQL 语句主要是 INSERT 和SELECT。幸运的是,INSERT 只生成极少的 undo(需要把块恢复为插入前的“没有”状态,而存储“没有”不需要多少空间),另外SELECT根本不生成undo。

    注意:

    l         对“实际”表(永久表)的 INSERT 生成了大量 redo。而对临时表几乎没有生成任何 redo。这是有道理的,对临时表的INSERT只会生成很少的undo数据,而且对于临时表只会为undo数据建立日志。

    l         实际表的UPDATE生成的redo大约是临时表更新所生成redo的两倍。同样,这也是合理的。必须保存UPDATE的大约一半(即“前映像”)。对于临时表来说,不必保存“后映像”(redo)。 

    l         DELETE 需要几乎相同的redo空间。这是有道理的,因为对DELETE的 undo很大,而对已修改块的redo很小。因此,对临时表的DELETE与对永久表的DELETE几乎相同。

    因此,关于临时表上的DML 活动,可以得出以下一般结论:

    l         INSERT 会生成很少甚至不生成undo/redo活动。

    l         DELETE 在临时表上生成的redo与正常表上生成的redo同样多。

    l         临时表的UPDATE会生成正常表UPDATE一半的redo。

    有了以上了解,你可能会避免删除临时表。可以使用TRUNCATE (当然要记住, TRUNCATE是 DDL,而 DDL 会提交事务,而且在 Oracle9i 及以前版本中,TRUNCATE 还会使你的游标失效) ,或者只是让临时表在 COMMIT 之后或会话终止时自动置空。执行方法不会生成 undo,相应地也不会生成 redo。你可能会尽量避免更新临时表,除非由于某种原因必须这样做。你会把临时表主要用于插入(INSERT)和选择(SELECT) 。采用这种方式,就能更优地使用临时表不生成redo的特有能力。

     

    9.5分析 undo 

    9.5.1什么操作会生成最多和最少的 undo?

    一般来讲,INSERT 生成的 undo 最少,因为 Oracle 为此需记录的只是要“删除”的一个rowid(行ID) 。UPDATE 一般排名第二(在大多数情况下)。DELETE生成的 undo最多。与加索引列的更新相比,对一个未加索引的列进行更新不仅执行得更快,生成的 undo 也会好得多。而更新有索引的列则可能生成大量的undo,因为索引结构本身所固有的复杂性,而且我们更新了这个表中的每一行,移动了这个结构中的索引键值。

     

    9.5.2 ORA-01555: snapshot too old错误

    注意 ORA-01555 与数据破坏或数据丢失毫无关系。在这方面,这是一个“安全”的错误;惟一的影响是:接收到这个错误的查询无法继续处理。

     

    这个错误实际上很直接,其实只有两个原因,但是其中之一有一个特例,而且这种特例情况发生得如此频繁,所以我要说存在3 个原因:

    l         undo段太小,不足以在系统上执行工作。

    l         你的程序跨COMMIT 获取(实际上这是前一点的一个变体)。我们在上一章讨论了这种情况。

    l         块清除。

     

    在充分说明这三种情况之前,我想先与你分享ORA-01555错误的几种解决方案,一般来说可以采用下面的方法:

    l         适当地设置参数 UNDO_RETENTION(要大于执行运行时间最长的事务所需的时间)。可以用V$UNDOSTAT来确定长时间运行的查询的持续时间。另外,要确保磁盘上已经预留了足够的空间,使undo 段能根据所请求的UNDO_RETENTION增大。

    l         使用手动 undo 管理时加大或增加更多的回滚段。这样在长时间运行的查询执行期间,覆盖undo数据的可能性就能降低。这种方法可以解决上述的所有3个问题。

    l         减少查询的运行时间(调优)。如果可能的话,这绝对是一个好办法,所以应该首先尝试这种方法。这样就能降低对 undo 段的需求,不需求太大的 undo 段。这种方法可以解决上述的所有3个问题。

    l         收集相关对象的统计信息。这有助于避免前面所列的第三点。 由于大批量的UPDATE或INSERT会导致块清除(block cleanout) ,所以需要在大批量UPDATE或大量加载之后以某种方式收集统计信息。

     

    对于Oracle9i 和以上版本,管理系统中的undo有两种方法:

    l         自动undo管理 (Automatic undo management):采用这种方法, 通过UNDO_RETENTION参数告诉 Oracle 要把 undo 保留多长时间。Oracle 会根据并发工作负载来确定要创建多少个undo段,以及每个undo段应该多大。数据库甚至在运行时可以在各个undo段之间重新分配区段,以满足DBA 设置的UNDO_RETENTION目标。这是undo管理的推荐方法。

    l         手动undo管理(Manual undo management) :采用这种方法的话,要由DBA 来完成工作。DBA 要根据估计或观察到的工作负载, 确定要手动地创建多少个undo 段。 DBA 根据事务量 (生成多少undo)和长时间运行查询的长度来确定这些undo段应该多大。

     

    在手动 undo 管理的情况下,DBA 要确定有多少个 undo 段,以及各个 undo 段有多大,这就产生了一个容易混淆的问题。有人说: “那好,我们已经配置了 XMB 的 undo,但是它们可以增长。我们把MAXEXTENTS 设置为 500,而且每个区段是 1MB,所以 undo 可以相当大。”问题是,倘若手动地管理undo段,undo段从来不会因为查询而扩大;只有INSERT、UPDATE 和DELETE才会让undo段增长。事实上,如果执行一个长时间运行的查询,Oracle不会因此扩大手动回滚段(即手动管理的回滚段)来保留数据,以备以后可能需要用到这些数据。只有当执行一个长时间运行的UPDATE 事务时才会扩大手动回滚段。在前面的例子中,即使手动回滚段有增长的潜力,但它们并不会真正增长。对于这样一个系统,你需要有更大的手动回滚段(尽管它们已经很大了)。你要永久地为回滚段分配空间,而不是只给它们自行增长的机会。对于这个问题,惟一的解决方案只能是适当地设置手动回滚段的大小。

     

    在自动undo 管理的情况下,从ORA-01555角度看,问题则要容易得多。无需自行确定undo空间有多大并完成预分配,DBA 只有告诉数据库运行时间至少在这段时间内保留 undo。如果已经分配了足够的空间可以扩展,Oracle 就会扩展 undo 段,而不是回绕,从而满足 UNDO_RETENTION 保持时间的要求。这与手动管理的 undo 截然相反,手动管理是会回绕,并尽可能块地重用 undo 空间。这是由于这个原因(即自动undo管理支持UNDO_RETENTION参数) ,所以我强烈建议尽可能采用自动undo 管理。

    使用手动undo管理时,还要记住重要的一点,遇到ORA-01555错误的可能性是由系统中最小的回滚段指示的(而非最大的回滚段,也并非平均大小的回滚段)。增加一个“大”回滚段不能解决这个问题。处理查询时只会让最小的回滚段回绕,这个查询就有可能遇到 ORA-01555 错误。使用遗留的回滚段时我主张回滚段大小要相等,以上就是原因所在。如果回滚段的大小都相等,那么每个回滚段即是最小的,也是最大的。这也是我为什么避免使用“最优大小”回滚段的原因。如果你收缩一个此前被扩大的回滚段,就要丢掉以后可能还需要的大量 undo。倘若这么做,会丢掉最老的回滚数据,从而力图使风险最小,但是风险还是存在。我喜欢尽可能在非高峰期间手动地收缩回滚段。

        我们已经讨论过块清除机制,不过这里可以做一个总结:在块清除过程中,如果一个块已被修改,下一个会话访问这个块时,可能必须查看最后一个修改这个块的事务是否还是活动的。一旦确定该事务不再活动,就会完成块清除,这样另一个会话访问这个块时就不必再历经同样的过程。要完成块清除, Oracle会从块首部确定前一个事务所用的undo段,然后确定从 undo 首部能不能看出这个块是否已经提交。可以用以下两种方式完成这种确认。一种方式是Oracle可以确定这个事务很久以前就已经提交,它在undo段事务表中的事务槽已经被覆盖。另一种情况是COMMIT SCN还在 undo段的事务表中,这说明事务只是稍早前刚提交,其事务槽尚未被覆盖。

        要从一个延迟的块清除收到ORA-01555错误,以下条件都必须满足:

    l         首先做了一个修改并COMMIT,块没有自动清理(即没有自动完成“提交清除” ,例如修改了太多的块,在SGA块缓冲区缓存的10%中放不下) 。

    l         其他会话没有接触这些块,而且在我们这个“倒霉”的查询(稍后显示)命中这些块之前,任何会话都不会接触它们。

    l         开始一个长时间运行的查询。这个查询最后会读其中的一些块。这个查询从SCN  t1开始,这就是读一致 SCN,必须将数据回滚到这一点来得到读一致性。开始查询时,上述修改事务的事务条目还在undo段的事务表中。

    l         查询期间,系统中执行了多个提交。执行事务没有接触执行已修改的块(如果确实接触到,也就不存在问题了)。

    l         由于出现了大量的COMMIT,undo 段中的事务表要回绕并重用事务槽。最重要的是,将循环地重用原来修改事务的事务条目。另外,系统重用了 undo 段的区段,以避免对 undo 段首部块本身的一致读。

    l         此外,由于提交太多,undo段中记录的最低SCN 现在超过了t1(高于查询的读一致SCN)。 

     

    如果查询到达某个块,而这个块在查询开始之前已经修改并提交,就会遇到麻烦。正常情况下,会回到块所指的undo段,找到修改了这个块的事务的状态(换句话说,它会找到事务的COMMIT SCN)。如果这个 COMMIT  SCN 小于 t1,查询就可以使用这个块。如果该事务的 COMMIT  SCN 大于 t1,查询就必须回滚这个块。不过,问题是,在这种特殊的情况下,查询无法确定块的COMMIT SCN是大于还是小于t1。相应地,不清楚查询能否使用这个块映像。这就导致了ORA-01555错误。

     

    万一你发现遭遇了这个问题,即选择(SELECT)一个表时(没有应用其他DML操作)出现了ORA-01555错误,能你可以试试以下解决方案:

    l         首先,保证使用的事务“大小适当”。确保没有不必要地过于频繁地提交。

    l         使用 DBMS_STATS 扫描相关的对象,加载之后完成这些对象的清理。由于块清除是极大量的UPDATE 或INSERT造成的,所以很有必要这样做。

    l         允许undo表空间扩大,为之留出扩展的空间,并增加undo保持时间。这样在长时间运行查询期间,undo 段事务表中的事务槽被覆盖的可能性就会降低。针对导致ORA-01555错误的另一个原因(undo 段太小) ,也同样可以采用这个解决方案(这两个原因有紧密的关系;块清除问题就是因为处理查询期间遇到了 undo 段重用,而 undo 段大小正是重用 undo 段的一个根本原因) 。实际上,如果把undo表空间设置为一次自动扩展1MB,而且undo保持时间为900秒,再运行前面的例子,对表BIG 的查询就能成功地完成了。

    l         减少查询的运行时间(调优)。如果可能的话,这总是件好事,所以应该首先尝试这样做。

    展开全文
  • oracle 12cr1 中,所有 pdb 只能共享使用 undo,被称为 Global Shared Undo 模式,即共享 Undo 模式 。 在 oracle 12cr2 中,每个 pdb 可以有自己独立的 undo ,被称为 PDB Local UNDO 模式,使用 dbca 创建数据库时, ...

    os: 7.6.1810
    db: oracle 19.3

    在 oracle 12cr1 中,所有 pdb 只能共享使用 undo,被称为 Global Shared Undo 模式,即共享 Undo 模式 。
    在 oracle 12cr2 中,每个 pdb 可以有自己独立的 undo ,被称为 PDB Local UNDO 模式,使用 dbca 创建数据库时, local undo 是默认勾选的.

    同时由于引入了 local UNDO, PDB 可以热克隆.
    在12.1版本中Clone一份PDB源库需要打开在 read only 只读模式, 在12.2版本中引入了local undo mode, 源PDB在read/write 读写模式也可以 Clone. 这样可以在复制一份测试环境时对源库影响降到最低, 同时 local undo mode也是ORACLE推荐的.

    12.1 源PDB在read/write模式clone是不允许的.以前的 小例子12.1 clone pdb

    ORA-65081: database or pluggable database is not open in read only mode
    下面会演示一下12.2 的PDB HOT Clone, 开始前先补充一点local undo的知识.

    版本

    # lsb_release -a
    LSB Version:	:core-4.1-amd64:core-4.1-noarch
    Distributor ID:	CentOS
    Description:	CentOS Linux release 7.6.1810 (Core) 
    Release:	7.6.1810
    Codename:	Core
    
    # su - oracle
    $ sqlplus / as sysdba;
    
    SQL*Plus: Release 19.0.0.0.0 - Production on Thu Jul 11 09:37:44 2019
    Version 19.3.0.0.0
    
    Copyright (c) 1982, 2019, Oracle.  All rights reserved.
    
    
    Connected to:
    Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
    Version 19.3.0.0.0
    
    SQL> set lines 200;
    set pages 200;
    
    SQL> select * from v$version;
    
    BANNER
    --------------------------------------------------------------------------------
    BANNER_FULL
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------
    BANNER_LEGACY									     CON_ID
    -------------------------------------------------------------------------------- ----------
    Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
    Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
    Version 19.3.0.0.0
    Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production			  0
    
    
    SQL> 
    
    

    LOCAL_UNDO_ENABLED

    SQL> set lines 200;
    set pages 200;
    col PROPERTY_NAME format a25;
    col PROPERTY_VALUE format a25;
    col DESCRIPTION format a40;
    
    SQL> select PROPERTY_NAME,PROPERTY_VALUE,DESCRIPTION from database_properties where property_name='LOCAL_UNDO_ENABLED';
    
    PROPERTY_NAME		  PROPERTY_VALUE	    DESCRIPTION
    ------------------------- ------------------------- ----------------------------------------
    LOCAL_UNDO_ENABLED	  TRUE			    true if local undo is enabled
    
    SQL> SELECT CON_ID,NAME FROM V$TABLESPACE A WHERE A.NAME  LIKE 'UNDO%' ORDER BY CON_ID,TS# ;
    
    CON_ID NAME
    ------ ------------------------------
         1 UNDOTBS1
         1 UNDOTBS2
         2 UNDOTBS1
         3 UNDOTBS1
         3 UNDO_2
         4 UNDOTBS1
         4 UNDO_2
    
    7 rows selected.
    
    

    另外 Shared Undo 和 Local Undo 切换,可以参考帮助文档.

    参考:
    https://docs.oracle.com/en/database/oracle/oracle-database/19/multi/administering-a-cdb-with-sql-plus.html#GUID-24EA5811-94F0-4EEC-864F-23AEF48F2D51

    展开全文
  • Oracle-UNDO表空间解读

    万次阅读 2016-11-16 01:45:27
    UNDO概述 官方文档Managing Undo Tablespaces UNDO 表空间用于存放UNDO数据,当执行...在 oracle9i之前,管理UNDO数据时使用(Rollback Segment)完成的.从oracle9i开始,管理UNDO数据不仅可以使用回滚段,还可以使用UN...

    UNDO概述

    官方文档Managing Undo Tablespaces

    UNDO 表空间用于存放UNDO数据,当执行DML操作(INSERT,UPDATE和DELETE)时,oracle会将这些操作的旧数据写入到UNDO段。

    在 oracle9i之前,管理UNDO数据时使用(Rollback Segment)完成的.从oracle9i开始,管理UNDO数据不仅可以使用回滚段,还可以使用UNDO表空间。

    10g开始貌似已经不在使用Rollback Segment来管理UNDO数据了,统一使用UNDO表空间。


    UNDO数据的作用

    1,回退事务

    当执行DML操作修改数据时,UNDO数据被存放到UNDO段,而新数据则被存放到数据段中,如果事务操作存在问题,旧需要回退事务,以取消事务变化.

    这里写图片描述

    比如:

    用户A执行了语句UPDATE emp SET sal=9999 WHERE empno=7788后发现,应该修改雇员7963的工资,而不是雇员7788的工资,那么通过执行ROLLBACK语句可以取消事务变化.

    >update emp a set a.sal=9999 where a.empno=7788;
    >rollback;
    

    当执行ROLLBACK命令时,oracle会将UNDO段的UNDO数据800写回的数据段中.


    2,读一致性

    用户检索数据库数据时,oracle 总是让用户只能看到被提交过的数据(读取提交)或特定时间点的数据(SELECT语句时间点).这样可以确保数据的一致性.

    比如:

    当用户A执行语句 UPDATE emp SET sal=1000 WHERE empno=7788时,UNDO记录会被存放到回滚段中,而新数据则会存放到EMP段中;假定此时该数据尚未提交,并且用户B执行SELECT sal FROM emp WHERE empno=7788,此时用户B将取得UNDO数据 800,而该数据正是在UNDO记录中取得的.

    会话A:

    SQL> SELECT sal FROM emp WHERE empno=7369;
     
          SAL
    ---------
       800.00
     
    SQL> UPDATE emp SET sal=1000 WHERE empno=7369;
     
    1 row updated
     
    SQL> 
    

    会话B(在这里我们通过新开一个SQL窗口来模拟) ,如果还是继续使用会话A,则查询的仍是1000.

    SQL> SELECT sal FROM emp WHERE empno=7369;
     
          SAL
    ---------
       800.00
    

    3,事务恢复

    事务恢复是例程恢复的一部分,它是由oracle server自动完成的.

    如果在数据库运行过程中出现例程失败(如断电,内存故障,后台进程故障等),那么当重启oracle server时,后台进程SMON会自动执行例程恢复,执行例程恢复时,oracl会重新做所有未应用的记录.回退未提交事务.


    4,闪回查询(FlashBack Query)

    倒叙查询用于取得特定时间点的数据库数据, 它是9i新增加的特性,假定当前时间为上午09:00,某用户在上午10:00执行UPDATE emp SET sal= 1000 WHERE empno=7369语句,修改并提交了事务(雇员原工资为800),为了取得10:00之前的雇员工资,用户可以使用倒叙查询特征.

    Oracle10g闪回查询特性的增强

    Oracle 9i的闪回查询只能提供某个时间点的数据视图,并不能告诉用户这样的数据经过了几个事务、怎样的修改(UPDATE、INSERT、DELETE等),而这些信息在回滚段中是存在的,在Oracle10g中,Oracle进一步加强了闪回查询的特性,提供了以下两种闪回查询:

    • 闪回版本查询(Flashback Versions Query)
    • 闪回事务查询(Flashback Transaction Query)

    闪回版本查询允许使用一个新的VERSIONS子句查询两个时间点或者SCN之间的数据版本。这些版本可以按照事务区分,闪回版本查询只返回提交数据,未提交数据不被显示。

    Oracle10g的闪回版本查询通过使用VERSIONS子句和对数据表引入一系列的伪列(version_starttime等),可以获得对数据表的所有事务操作,versions_operation代表不同类型的操作(D-DELETE、I_INSERT、U_UPDATE),VERSIONS_XID是一个重要依据,代表了不同版本的事务ID。

    Select versions_starttime,versions_endtime,versions_xid,versions_operation,字段xx
    From table_name versions between timestamp minvalue and maxvalue;
    

    通过以上查询,根据versions_xid可以清晰地区分不同事务在不同时间对数据所作的更改。

    由于这个查询需要从Undo中获取前镜像信息,如果Undo中的信息被覆盖,则以上查询将会失败。

    数据恢复栗子

    用户更新了或者误删除了一批数据(假设数据量很大),

    下面用一条数据做演示:7369工号的原始工资为800 ,更新后工资为1000

    UPDATE emp SET sal=1000 WHERE empno=7369;
    

    此时用户想恢复,假设删除的时间点是2016-11-13 09:00:00 之后,那么我们找到9点之前的 SCN(System Change Number 系统改变号) .

    SCN提供了Oracle的内部时钟机制,可被看作逻辑时钟,这对于恢复操作是至关重要的.

    1.获得当前SCN

    select timestamp_to_scn(to_timestamp('2016-11-13 09:00:00','YYYY-MM-DD HH24:MI:SS')) as scn from dual ;
    
    select dbms_flashback.get_system_change_number scn from dual;   --查询当前数据库的SCN
    

    2.将emp表中的scn点的数据取出

    select * from emp  AS OF SCN 13267939370491;
    

    这里写图片描述

    可以看到这个时间点之前的数据 7369是800.

    3.然后可以根据这个数据进行还原操作

    insert into emp select * from emp AS OF SCN 13267939370491;
    

    回滚段著名的ORA-01555问题

    从应用角度来看ORA-01555

    • 1.查询执行时间太长。首先是优化查询,然后考虑在数据块不繁忙的时候运行,最后考虑加大回滚段。

    • 2.过渡频繁的提交。把能够成批提交的单条事务改成成批提交

    • 3.exp的时候使用而来consistent = y. 这个参数主要是为了保证在exp的时候使得所有的到处的表在时间点上具有一致性,避免存在主外键关系的表由于不同的时间点的不一致而破坏了数据的完整性。建议该操作在系统空闲的时候进行。

    • 4.由于回滚段回缩导致回滚段还没有循环使用的情况下就出现了回滚段中找不着数据的情况。只能加大回滚段增大optimal设置。


    Undo 表空间的两种管理方式

    Oracle 的 Undo 有两种方式: 一是使用 undo 表空间,二是使用回滚段.

    我们通过 undo_management 参数来控制使用哪种方式,

    如果设为 auto, 就使用 UNDO 表空间,这时必须要指定一个 UNDO 表空间。

    如果设为 manual,系统启动后使用 rollback segment 方式存储 undo 信息。

    SQL> show parameter undo
     
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    undo_management                      string      AUTO
    undo_retention                       integer     900
    undo_tablespace                      string      UNDOTBS1
     
    SQL> 
    

    Undo配置参数含义

    • UNDO_MANAGEMENT undo的管理模式,分自动和手动

    • UNDO_TABLESPACE 当前正在被使用的undo表

    • UNDO_RETENTION 规定多长时间内,数据不能被覆盖。

    • AUTO 表示undo 为自动管理模式。

    • 900 表示在900秒内,undo上的数据不能被覆盖。

    • UNDOTBS1 是当前正在使用的undo表空间


    如果系统没有指定 undo_management,那么系统默认以 manual 方式启动,即使设置了 auto 方式的参数,这些参数将被忽略。

    当实例启动的时候,系统自动选择第一个有效的 undo 表空间或者是 rollback
    segment, 如果没有有效的可用的 undo 表空间或者是回滚段,系统使用 system rollback segment。这种情况是不被推荐的,当系统运行在没有 undo 的情况下,系统会在 alert.log 中记录一条警告信息。


    使用 rollback segment

    当 undo_management 被设置成 MENUAL 时使用系统回滚段, 即将 undo records 记录到 SYSTEM 表空间下的 SYSTEM 段。

    select segment_name,tablespace_name,bytes,next_extent from dba_segments  where segment_type='ROLLBACK'; 
    

    这里写图片描述

    通过上面的这条语句,我们查到了这个用于 rollback 的 system segment 存在
    与 system 表空间。 默认情况下,只有一个 segment,并且它还比较小, 所以,如果使用 system 段来存储 undo records,肯定会影响数据库的性能。 所以 Oracle是建议使用 Undo tablespace 来管理 undo records。


    使用 Undo 表空间

    当 undo_management 设置成 AUTO 时使用 UNDO tablespace 来管理回滚段这个时候,我们将有多个 undo segment,并且这些 segment 是存放在 UNDO 表空间里的, 这样对 DB 的性能就会提高。

     select segment_name,tablespace_name,bytes,next_extent from dba_segments where segment_type='TYPE2 UNDO';
    

    这里写图片描述

    目前我们的这个数据库已经有58个undo segment了。默认的好像是10个。


    除了通过dba_segment 表查看的结果, 也可以通过 v r o l l s t a t 和 v rollstat 和 v rollstatvrollname 两个视图来查看信息, 这 2 个视图会显示所有 rollback 段的信息,包括 system 段和 undo 段。

    select s.usn,n.name,s.extents,s.hwmsize,s.status from v$rollstat s, v$rollname n where s.usn=n.usn;
    

    这里写图片描述


    undo_retention 和 retention guarantee 参数

    使用如下SQL 来查看 undo 表空间里空闲和非空闲比例:

    
    SELECT tablespace_name, status, SUM (bytes) / 1024 / 1024  "Bytes(M)" 
     FROM dba_undo_extents
     GROUP BY tablespace_name, status;
    

    这里写图片描述


    UNEXPIRED 和 EXPIRED 是已使用的 undo 表空间,

    其中 expired 说明是已经过期的数据,也就是 15 分钟(默认情况)以外的数据,已经被覆盖, 可以认为是空闲的。

    在这里就关系到一个参数: UNDO_RETENTION, 该参数用来指定 undo 记录保存的最长时间,以秒为单位,是个动态参数,完全可以在实例运行时随时修改,通常默认是 900 秒,也就是 15 分钟。

    如下所示:

    SQL> show parameter undo
     
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    undo_management                      string      AUTO
    undo_retention                       integer     900
    undo_tablespace                      string      UNDOTBS1
     
    SQL> 
    

    undo_retention 只是指定 undo 数据的过期时间,并不是说, undo 中的数据一定会在 undo 表空间中保存 15 分钟,比如说刚一个新事务开始的时候,如果undo 表空间已经被写满, 则新事务的数据会自动覆盖已提交事务的数据,而不管这些数据是否已过期

    因此呢,这就又关联回了第一点,当你创建一个自动管理的 undo 表空间时,还要注意其空间大小,要尽可能保证 undo 表空间有足够的存储空间。

    undo_retention 中指定的时间一过,已经提交事务中的数据就立刻无法访问,它只是失效,只要不被别的事务覆盖,它会仍然存在,并可随时被 flashback 特性引用。

    如果你的 undo 表空间足够大,而数据库又不是那么繁忙,那么其实undo_retention 参数的值并不会影响到你,哪怕你设置成 1,只要没有事务去覆盖 undo 数据,它就会持续有效。 总之, 要注意 undo 表空间的大小,保证其有足够的存储空间。

    只有在一种情况下, undo 表空间能够确保 undo 中的数据在undo_retention指定时间过期前一定有效,就是为 undo 表空间指定 Retention Guarantee,指定之后, oracle 对于 undo 表空间中未过期的 undo 数据不会覆盖.

    例如:

    SQL> Alter tablespace undotbs1 retention guarantee;
    

    禁止 undo 表空间 retention guarantee


    总结:

    • UNDO 表空间是会被重用的,只有当事务没结束,或开了 retention guarantee, 或在 undo_retention时间内不能被重用。

    • 在 undo_retention 规定的时间内,数据都是有效的,过期后都会设为无效, 状态被改为 Expired,这些回滚段将会被看作Free Space。但是只要数据没有被覆盖就可以使用。

    • 如果空间已满,新事务的数据会自动覆盖掉已经提交的事务数据,即使在 undo_retention 的时间内。除非指定 Retention
      Guarantee 模式,才能保证在 undo_retention 内不被覆盖。


    调优原则

    关于oracle UNDO表空间自动管理自动调优的原则介绍,在Oracle 10gr2后面的版本中添加了UNDO信息最短保留时间段自动调优的特性,不再仅仅依据参数UNDO_RETENTION的设定,其调优原则如下:

    1 当UNDO TABLESPACE为 fixed-size,Oracle将根据表空间的大小和历史使用情况,自动调整undo信息保存时间,同时忽略 undo_retention的值除非 undo_retention的guarantee 特性被启用。

    2 当UNDO TABLESPACE为AUM时,Oracle将动态调整撤销信息最短保留时间为该时段最长查询时间(MAXQUERYLEN)加上300秒或参数UNDO_RETENTION间的较大者,即MAX((MAXQUERYLEN+300),UNDO_RENTION);

    在自动调整启用的情况下,实际的撤销信息最短保留时间可以通过查询V$UNDOSTAT视图上的TUNED_UNDORETENTION列获得。往往最短保存时间远远大于设定的UNDO_RETENTION。在无法就UNDO TABLESPACE做相应修改的情况,可以通过修改隐式参数”_UNDO_AUTOTUNE”为FALSE关闭该自动调优特性。以上设定生效后,V$UNDOSTAT视图上TUNED_UNDORETENTION列不再更新,且撤销信息最短保留时间固定为参数UNDO_RETENTION的设定值。该参数可以不用重启数据库而动态设置生效。

    UNDO自动优化功能能够最大限度的使用undo表空间,满足大部分的sql执行,但是也带来一个问题:很多事务执行完毕之后,发现UNDO表空间会在很长时间都一直保持着使用率是接近100%的状态,active 状态的很少。

    这种接近状态还无法手工的收缩,甚至于重启数据库实例也无法缓解,而此时常常会收到undo表空间的监控报警。

    可以通过修改隐式参数”_UNDO_AUTOTUNE”为FALSE关闭该自动调优特性。以上设定生效后,V$UNDOSTAT视图上TUNED_UNDORETENTION列不再更新,且撤销信息最短保留时间固定为参数UNDO_RETENTION的设定值。该参数可以不用重启数据库而动态设置生效。

    > alter system set "_undo_autotune"=false;
    System altered.
    
    

    禁用UNDO自动优化之后,Oracle不再的每十分钟记录一次当前UNDO使用情况了,在动态视图V$UNDOSTAT中也只保留禁止undo自动调优之前的数据 。 .一般不建议关闭Oracle的自动调优


    相关数据字典

    数据字典解释
    v$undostat包含所有undo表空间的统计信息,用于对undo表空间进行监控和调整。通过该视图,可以估计当前undo表空间的大小,Oracle利用该视图完成对回退信息的自动管理,该视图数据是有最近4天内,每10分钟产生一条统计记录构成的。
    v$rollstat包含undo表空间中回退段的性能统计信息
    v$transaction包含事务所使用的回退段信息
    dba_undo_extents包含undo表空间中区的大小与状态信息
    dba_hist_undostat包含v$undostat的快照,主要是4天前的统计信息

    undo表空间中区的状态一共有3种:EXPIRED、UNEXPIRED、ACTIVE。

    • EXPIRED:表示该回退信息对应的事务已经提交,保存时间超过保留区;

    • UNEXPIRED:表示该回退信息对应的事务已经提交,保存时间没有超过保留区;

    • ACTIVE:表示回退信息对应的事务还没有提交,该区还在使用;


    undo 表空间满时的处理方法

    默认情况下的 Undo_retention 只有 15 分钟,这个默认值,一般都无法满足
    系统的需求。 一般建议是改成 3 个小时, 这样给万一的情况,多争取一些时间。

    SQL> alter system set undo_retention=10800; -- 3 个小时
    系统已更改。
    

    当然, undo_retention 设置的越大,所需要的 undo tablespace 也就越大。 这个需要结合自己的系统来设置这个参数。


    模拟 UNDO 表空间满的情况

    SQL> create undo tablespace undo datafile '/oradata/undo.dbf' size 1m;
    表空间已创建。
    SQL> alter tablespace undo retention guarantee;
    表空间已更改。
    SQL> alter system set undo_tablespace=undo;
    系统已更改。
    SQL> create table DBA(id number);
    表已创建。
    SQL> begin
    2 for i in 1 .. 100000 loop
    3 insert into dba values(i);
    4 commit;
    5 end loop;
    6 end;
    7 /
    begin
    *1 行出现错误:
    ORA-30036: 无法按 8 扩展段 (在还原表空间 'UNDO')
    ORA-06512: 在 line 3
    

    解决办法

    处理方法有两种,

    • 一是添加 undo 表空间的数据文件,
    • 二是切换 UNDO tablespace. 这种情况下多用在 undo 表空间已经非常大的情况。

    增加数据文件

    SQL> ALTER TABLESPACE undo ADD DATAFILE '/oradata/undo2.dbf' size 100M reuse;
    表空间已更改。
    SQL> begin
    2 for i in 1..100000 loop
    3 insert into dba values(1);
    4 commit;
    5 end loop;
    6 end;
    7 /
    PL/SQL 过程已成功完成。
    

    切换 UNDO 表空间

    1、 建立新的表空间 UNDOTBS2

    SQL> CREATE UNDO TABLESPACE UNDOTBS2 DATAFILE
    '/oradata/und3.dbf' size 100M reuse;
    表空间已创建。
    

    2、 切换到新建的 UNOD 表空间上来,操作如下

    SQL> alter system set undo_tablespace=UNDOTBS2 scope=both;
    系统已更改。
    

    3、将原来的 UNDO 表空间,置为脱机:

    SQL> alter tablespace UNDO offline;
    表空间已更改。
    

    4、删除原来的 UNDO 表空间:

    SQL> drop tablespace UNDO including contents AND DATAFILES CASCADE CONSTRAINTS ;
    表空间已删除。
    

    如果只是 drop tablespace UNDO ,则只会在删除控制文件里的记录,并不会物理删除文件。

    Drop undo 表空间的时候必须是在未使用的情况下才能进行。如果 undo 表空间正在使用(例如事务失败,但是还没有恢复成功),那么 drop 表空间命令将失败。在 drop 表空间的时候可以使用 including contents。


    undo 表空间损坏的处理方法

    出现 undo 损坏的情况, 大多数是因为异常宕机,在启动的时候报的错误,DB 不能启动。
    比如: ORA-00600: internal error code, arguments: [4194]

    当 alert log 里出现 ORA-600 + [4194] 时,基本就可以断定,是 undo 表空间出现了损坏。 对于 Undo 损坏的情况,能用备份恢复最好,如果不能,就只能通过一些特殊的方法来恢复。

    方法一: 使用 system segment

    当我们使用 undo 表空间出现损坏时,可以先用 system segment 启动 DB,
    启动之后,在重新创建 UNDO 表空间,在用 undo 来启动。 步骤如下:

    ( 1) 用 spfile 创建 pfile,然后修改参数:

    #*.undo_tablespace='UNDOTBS1'
    #*.undo_management='AUTO'
    #*.undo_tablespace
    #*.undo_retention
    undo_management='MANUAL'
    rollback_segments='SYSTEM'
    

    如何通过SPFILE创建PFILE?

    SQL> shutdown immediate 数据库已经关闭。
    已经卸载数据库。
    ORACLE 例程已经关闭。
    SQL> create pfile from spfile;
    文件已创建。
    
    

    pfile文件-linux等平台在 O R A C L E H O M E / d b s 下 , O r a l c e 在 启 动 实 例 的 时 读 取 ‘ ORACLE_HOME/dbs下, Oralce在启动实例的时读取` ORACLEHOME/dbsOralceORACLE_HOME/dbs`下面的初始化文件。

    ( 2)用修改之后的 pfile,重启 DB

    SQL> STARTUP MOUNT pfile='F:\initorcl.ora' ;
    

    ( 3)删除原来的表空间,创建新的 UNDO 表空间

    SQL> drop tablespace undotbs;
    SQL> create undo tablespace undotbs1 datafile '/u01/oradata/undotbs1.dbf' size 10M;
    

    ( 4)关闭数据库,修改 pfile 参数,然后用新的 pfile 创建 spfile,在正常启动数据库。

    *.undo_tablespace='UNDOTBS1'
    *.undo_management='AUTO'
    #undo_management='MANUAL'
    #rollback_segments='SYSTEM'
    

    创建SPFILE

    SQL> CREATE SPFILE=$ORACLE_HOME/dbs/spfileSID.ora FROM PFILE $ORACLE_HOME/dbs/initSID.ora
    

    若都使用默认的,则可简写为:

    SQL> CREATE SPFILE FROM PFILE;
    
    SQL> show parameter spfile
    
    NAME				     TYPE	 VALUE
    ------------------------------------ ----------- ------------------------------
    spfile				     string	 /oracle/product/112/dbs/spfile
    						 cc.ora
    

    方法二: 跳过损坏的 segment

    在方法一里面,我们使用了 system segment。 通过前面的说明, 我们了解到,undo segment 有多个,我们可以通过 alert log 来查看正在使用的是哪些 segment,这些段有可能损坏了。 我们只需要把这些损坏的 segment 跳过,先正常启动 DB,在创建新的 UNDO 表空间,在切换一下。

    ( 1)修改 pfile,添加参数:

    *._corrupted_rollback_segments='_SYSSMU11$','_SYSSMU12$','_SYSSMU13$'
    

    这些字段的值, 我们通过 alert log 查看。 也可以通过如下命令查看:

    #strings system01.dbf | grep _SYSSMU | cut -d $ -f 1 | sort -u
    

    ( 2)用修改之后的 pfile 启动 DB
    因为跳过了哪些损坏的 segment,所以 DB 可以正常启动。
    ( 3)创建新的 UNDO 表空间,并切换过来

    SQL> create undo tablespace undotbs1 datafile '/u01/oradata/undotbs1.dbf' size 10M;
    SQL> alter system set undo_tablespace=undotbs1;
    SQL> drop tablespace undotbs;
    

    ( 4)修改 pfile,创建 spfile,并正常启动

    删除:

    *._corrupted_rollback_segments='_SYSSMU11$','_SYSSMU12$','_SYSSMU13$'
    
    展开全文
  • Oracle 10g及后续版本较以前版本有一新特性即自动调整undo retention时间,大大简便了管理,对于自动扩展(autoextend on)的undo表空间,参数undo_retention设置成为Oracle自动调...
  • Oracle Undo

    2011-12-20 07:57:00
    Oracle Undo学习资料,对Undo的介绍有利于对回滚和Undo表空间有一个比较清晰地认识
  • ORACLE 管理undo

    千次阅读 2016-07-15 22:19:42
    使用undo tablespace 存放从datafiles 读出的数据块的前镜像,提供以下四种情况所需要的信息 1)回滚事务:rollback 2)读一致性:正在做DML操作的数据块,事务结束前,其他用户读undo里面的数据前镜像 3)实例的...
  • oracleundo与redo

    2018-08-12 17:10:36
    oracle日志,Undo日志记录某数据被修改前的值,可以用来在事务失败时进行rollback;Redo日志记录某数据块被修改后的值,可以用来恢复未写入data file的已成功事务更新的数据。
  • Oracle Managing UNDO

    2013-04-02 16:31:20
    Oracle UNDO表空间的作用:事务回滚,实例恢复,一致性读取。在此总结一下UNDO的表空间管理。 1,Oracle UNDO中的几个重要概念 http://docs.oracle.com/cd/E11882_01/server.112/e25494/undo002.htm#BJFFIACJ ...
  • Automatic Undo Management (AUM), also referred to as System Managed Undo (SMU), was introduced in Oracle9i in response to performance and administrative difficulties associated with rollback segments....
  • Oracle_Undo与Redo的通俗

    2011-01-08 12:02:09
    Oracle_Undo与Redo的通俗
  • seata-oracleundolog.sql

    2020-09-05 10:33:23
    oracle版本的undolog建表语句。 2019 年 1 月,阿里巴巴中间件团队发起了开源项目 Fescar(Fast & EaSy Commit And Rollback),和社区一起共建开源分布式事务解决方案。Fescar 的愿景是让分布式事务的使用像本地...
  • Oracle_undo与redo

    2013-09-24 12:51:20
     你可能会遇到 Oracle 使用 UNDO 表空间问题, 这里将介绍 Oracle 使用 UNDO 表空间问题的解决方法,在这里拿出来和大家分享一下。    UNDO 表空间用于存放 UNDO 数据,当执行 DML 操作 (INSERT , UPDATE 和 ...
  • oracle 估算undo脚本

    2015-08-24 10:48:15
     摘自老道博客: ...   metalink 给出的公式是 UR =undo_retention参数值 UPS= 每秒产生的undo block数量 DBS = undo tablespace block size 10g之前 SE
  • oracleundo理解

    千次阅读 2017-04-15 16:31:45
    浅谈undo
  • oracleUndo Retention

    千次阅读 2013-08-21 22:09:38
    oracleUndo Retention  oralce database 根据undo表空间大小和系统活动状态自动调整保留时间,可以调整undo_retention 参数设置保留时间。但是准确的将分为如下两种情况。 1)在国定大小的undo表空间中undo_...
  • Oracle undo

    千次阅读 2017-01-23 13:49:34
    UNDO表空间相关扫盲(解决ORA-30036:无法按8扩展段(在还原表空间‘XXXX’中))
  • oracle 创建 undo tablespace

    千次阅读 2019-03-19 15:08:55
    db: oracle 12.1.0.2 permanent smallfile tablespace select 'alter database datafile '''||dt.file_name||''' autoextend on next 1g maxsize 30g; ', dt.*, dts.* from dba_data_...
  • 4.latch之oracle latch undo globaldata.pdf
  • Oracle redo undo

    2014-01-09 11:46:41
    通常对undo有一个误解,认为undo用于数据库物理地恢复到执行语句或事务之前的样子,但实际上并非如此。数据库只是逻辑地恢复到原来的样子,所有修改都被逻辑地取消,但是数据结构以及数据库块本身在回滚后可能大不...
  • ORACLEundo表空间操作

    2019-04-04 14:34:19
    1.查看undo表空间 selectfile_id,file_name,tablespace_name,sum(bytes)/1024/1024total_mb,autoextensible fromdba_data_filesgroupbyfile_name,file_id,tablespace_name,autoextensibleorderbyfile_id; ...
  • Oracle释放过度使用Undo表空间,脚本
  • oracleundo和redo的区别

    千次阅读 2014-11-18 22:58:10
    undo表空间与redo日志文件在oracle中的作用非常重要,本文重点介绍undo回滚段的作用与特点,同时简单介绍undo与redo的区别和各自己的作用。 一、undo中数据的特点: 1.是数据修改前的备份,主要是保证用户的读一致...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 44,998
精华内容 17,999
关键字:

oracle查看undo使用