zoukankan      html  css  js  c++  java
  • Oracle专家高级编程 第五章 重做和回滚

    重做

    redo log,重做日志有两种,联机和归档(数据库事务的历史记录)

    • 每个Oracle数据库至少有两个联机重做日志文件,循环使用,Oracle先往日志1写,写满专向日志2,写满转回日志文件1
    • 归档重做文件日志文件只是复制旧的,写满了的联机重做日志文件
    • 当系统写满日志文件时,ARCH进程会把联机重做日志文件复制到另一个位置
    • 当硬盘出现故障或者物理损坏时,使用归档重做日志文件实现介质恢复

    COMMIT

    commit是一个非常快的操作,不管事务大小,commit响应时间通常是"平均的"

    commit 1行花费x隔单位,commit 1000行同样花费x个单位,但是进行1000次commit一行的操作花费的是1000*x个单位

    commit提交前做好的工作

    • 在SGA中产生了回滚段(callback segment)记录
    • 在SGA中产生了修改数据块
    • 在SGA中产生了上面两条缓冲重做(undo)
    • 取决于上面3项大小和消耗的时间,一部分数据可能已经刷新到硬盘上
    • 已经获得所有的锁定

    当commit时,所有剩下的工作

    • 为事务产生一个系统改变号(System Change Number,SCN)
    • LGWR把所有余下的缓冲区中的重做日志存储到硬盘上,并在联机重做日志文件中记录SCN(当前步骤即SCSN)
    • 删除了事务条目,意味着已经提交了,在V$TRANSZCTION试图中的记录将消失
    • 释放会话占用的所有锁定,释放在入队列等待中被占用锁定的每个事项
    • 访问多个修改事务块,若它们仍在缓冲区高速缓存中,用快速模式访问和清除

    执行commit只有很少的工作,时间最长的总是LGWR执行的操作,因为它是物理硬盘的IO

    当操作进行时,LGWR连续刷新,至少:

    • 每3秒
    • 当满1/3或1MB
    • 碰到任何事物commit

    LGWR消耗的时间是由重做日志缓冲区已经释放的内容限定的

    LGWR不会存储所有工作,当操作进行时,他将增加释放后台重做日志缓冲区中的内容,可以立即释放所有重做内容

    在提交前,缓冲重做日志已经被放到硬盘上了,当commit时,必须等待

    LGWR的调用是同步的事物要等待LGWR完全写完,收到的数据存在于硬盘上

    SCN

    是Oracle保证事务顺序并从失败中恢复的简单定时机制,SCN也能保证数据库一致读取性和检查点机制,类似计数器

    回滚

    ROLLBACK 必须物理上取消已完成的工作,在ROLLBACK之前已经完成了很多工作

    • 已经在SGA产生了回滚段记录
    • 已经在SGA产生了修改数据块
    • 已经在SGA中产生了上面两条重做缓冲信息
    • 取决于上面三项大小和消耗时间,一部分上面的数据可能已经刷新到硬盘上
    • 已经获得所有锁定

    当ROLLBACK时

    撤销所有已做的修改,通过从ROLLBACK(undo)读取数据来完成,实际上是逆向操作

    • 如果插入了一行,ROLLBACK删除它
    • 如果更新了一行,ROLLBACK将逆向更新
    • 如果删除了一行,回滚将重新插入它

    释放会话占用的所有锁定,释放在队列中等待被占用锁定的每个事项

    commit只是刷新保留在重做日志缓冲区中的数据,和ROLLBACK相比,做了非常少的工作

    产生多少重做

    重做管理是数据库中串行化的关键,在LGWR结果所有事务,要求它在它们的事务中管理重做和COMMIT

    LGWR做的越多,系统越慢

    使用动态性能试图V$MYSTAT,连接V$STATNAME,然后检索名为redo size的统计值,用V$STATNAME找到它

    select * from v$statname;

    阐述如何指定事务产生的重做量,知道要修改多少数据,可以直观估计要产生多少重做

    对于AUTOTRACE追踪的语句(INSERT,UPDATE和DELETE),可以使用AUTOTRACE

    无论使用一条语句UPDATE200行,都产生相同数量的重做,对DELETE结果也一样,无论是一条语句还是200条语句

    insert情况不太一样,对于单行插入产生的重做稍微多一些,当一行插入时,必须组织不同块中的数据,一次插入多行不是这样

    产生的重做是修改数据量的函数,如果insert2000字节的行,每行产生的重做将会稍微多余2000字节

    当update时,会产生两倍数量的重做(记录日志数据和回滚),DELETE的情况和INSERT情况相似,整个行记录在回滚段

    BEFORE触发器即使不修改行中的任何值,也会增加额外的重做信息

    使用上面的技术,会发现

    • BEFORE或AFTER触发器不影响DELETE
    • 对于BEFORE或AFTER触发器,INSERT产生同样多的额外重做信息
    • UPDATE只受BEFORE触发器的影响,而AFTER触发器不增加额外重做信息
    • 行的大小影响INSERT产生的额外重做信息的数量,不影响UPDATE

    在UPDATE时,AFTER触发器对UPDATE更有效,它根本不影响重做的产生,当且仅当必须使用BEFORE触发器时才使用它

    估计重做的量

    • 估计"事务"的大小--需要修改多少数据
    • 是否增加10%~20%的额外开销,取决于要修改的行数,行越多,额外开销越少
    • 对UPDATE,此值加倍

    为了保持索引结构,必须完成索的工作量从UPDATE到UPDATE可能是不同的,考虑触发器的缺点和代表性能的隐式操作

    如何不让重做日志产生

    redo log对数据库至关重要,某些sql语句和操作支持使用nologging,可以不产生redo log

    当使用nologging操作

    • 会产生一定数量的重做,用来保护数据字典,无法避免重做的产生,虽然可以比以前明显地少
    • nologging不能防止后面的操作产生重做
    • 在ARCHIVELOG模式的数据库中执行nologging操作之后,必须尽快备份受影响的数据文件,可以避免介质故障丢失对文件的修改

    两种方式使用nologging

    • 在sql命令中何时为止嵌入关键字nologging
    • 在nologging模式中隐式执行

    在ARCHIVELOG模式数据库中,适当使用NOLOGGING,可以通过大量减少产生的重做日志数量,加速许多操作

    不能分配一个新日志

    Sun Feb 25 10:59:55 2001
    Thread 1 cannot allocate new log, sequence 326
    Checkpoint not complete

    被要求归档,而不是设置检查点没有完成

    只要数据库试图重用联机重做日志文件,但是发现不行时,就把此消息写入服务器的alert.log文件

    当DBWR没有完成检查重做日志保护的数据,或者ARCH没有把重做日志文件复制到归档为止,就会发生这种情况

    当发现会话长时间等待,最可能碰到提示:

    切换日志文件,日志缓冲区空间,或切换日志文件设置检查点或归档没有完成

    块清除

    数据锁定会影响存储在块头上的数据,缺点是当块写一次被访问时,必须“清除”它,换句话说,删除事务的信息

    这么做会产生重做并且导致块变脏

    如果主要是小到中等的事务(OLTP联机事务处理),或是在批量操作后分析表的数据仓库,一般会"清除"块

    COMMIT时处理的一个步骤,重新访问SGA中的块;如果是可访问的,清除它们,称为"提交清除"

    强制清除

    Oracle分配块清单,这些块在事务相关的提交清单中修改过,每个块清单有20个块,Oracle根据需要尽可能多地分配

    修改过的块总和超过了缓冲区高速缓存大小的10%,Oracle会停止分配新块

    SELECT产生了重做,它还"弄脏"了这些修改过的块,导致DBWR再次写入它们,这是块清除的原因

    在OLTP(联机事务处理)系统中,所有事务都是短半块,修改几块并全部清除

    create table as select

    直接路径装载数据,直接路径插入数据,都将创建''干净"的块

    日志竞争

    最大等待事件是;日志文件同步

    正在经历重做日志竞争,它们运行得不够快,发生原因有很多种

    • 一个应用程序提交频率太高,例如提交在循环中insert,

    等待LGWR把重做日志缓冲刷新到硬盘上,LGWR可以在后台完成工作,不必等待

    当COMMIT越频繁,等待越多,假定所有事务大小合适,导致日志文件等待的通常原因是

    • 重做放到了运行慢的设备上,硬盘性能差,应该去购买更块的硬盘
    • 把重做和其他文件放到了同一设备上,重做是设计用来在专用设备上大量连续写入,其他组件,试图作为LGWR同时在这台设备上读写,就会遇到一定程度竞争
    • 用缓冲方式安装设备,使用一种成熟的文件系统,双倍的缓冲降低了运行速度
    • 用慢的技术放置重做,例如RAID读取性能好,写入性能差,

    需要至少5个专用设备创建日志,为了也能镜像归档文件,最好是6个,找出最小的,最快的,一两个大的硬盘

    重做组1 -- 硬盘1和3

    重做组2 -- 硬盘2和4

    归档 -- 硬盘5和可选的硬盘6

    把成员A和B的第一组重做日志放到"组1",把成员C和D的第二组重做日志放到"组2",如果还有第3组和第4组,放到奇数组和偶数组硬盘上

    LGWR将同时写入硬盘1和硬盘3,当这组写满时,LGWR将移到硬盘2和硬盘4

    写满后,又返回重新写入硬盘1和硬盘3

    同时ARCH处理全部联机重做日志

    LGWR在网组1上写时,ARCH在读组2,同时往归档硬盘上写

    当LGWR往组2上写时,ARCH在读组1,同时往归档硬盘上写,每个LGWR和ARCH都有自己专用的设备

    它们不会竞争其他设备,也不会相互竞争

    日志文件是最利于使用RAW硬盘的一组Oracle文件

    临时表的重做和回滚

    临时表不为它们的块产生重做,临时表上的操作是不能恢复的

    当修改临时表中的块时,这种修改不会在重做日志文件中记录

    然后临时表会产生回滚,回滚是记录到日志的,临时表会产生redo log

    • INSERT产生很少甚至没有回滚/重做
    • DELETE对临时表和对正常表产生同样多的重做
    • UPDATE对临时表产生的重做只有UPDATE对正常表产生的重做的一半

    避免删除临时表,因为如果产生回滚,DELETE的逆向操作INSERT是很麻烦的

    可以使用TRUNCATE或者只是在COMMIT或会话结束后自动清空

    分析重做

    使用Logminer,在里面找到DELETE的OBJ$,查看表何时由于"事故"被删除,且希望DBA在DROP TABLE前刚刚保存 

    回滚

    ORA-01555:snapshot too old 错误问题造成的混乱十分严重

    什么产生最多/最少的撤销

    • INSERT将产生最少数量的撤销,因为Oracle所要做的记录是"删除"行ID
    • UPDATE第二位,记录修改过的字节,只要在撤销中记录行的一小部分
    • DELETE产生最多的撤销,Oracle必须把整行的"前映像"记录到撤销段,等于将整个数据写入到回滚段

    set transaction

    选择事务要使用的回滚段,主要是为比较大的操作能够确保有大的回滚段

    对于罕见的大更新,可以使用一次

    大回滚段的一个问题是,不能阻止其他事务使用

    没有办法使一个回滚段属于单个事务,如果执行许多信息的某种批量更新,使用这种特性比较好

    在原来的地方把大表分区,然后执行并行更新

    ORA-01555: Snapshot too old

    • 对在系统上执行的工作,回滚段太小
    • 程序产生交叉commit(是上面情况的一种变种)
    • 块清除

    前两点和Oracle的一致读模式直接相关,重复使用回滚段,既回滚失败的事务又提供一致读,导致了ORA-01555

    第三点在只有一个会话的数据库中,这个会话没有修改这张表,会产生错误,未修改的表为什么产生回滚呢

    • 分析相关对象,块清除是大量UPDATE或INSERT的结果
    • 增多回滚段,可以降低当执行长时间查询时回滚数据被重写的可能性
    • 降低查询的运行时间,降低对大回滚段的需要

    事实上回滚段太小了

    如果回滚段是确定大小的,那么在查询执行期间便于反转,并且查询访问的数据可能被修改可能再次遇到ORA-01555

    必须去定回滚段的大小需要配置足够的回滚,适应长时间的查询需要

    如果从查询开始的回滚都没有重写,就可以避免ORA-01555

    产生ORA-01555,是由系统最小回滚段确定的,平均容量的回滚段,最大和最小是一样的,但也有风险,最好的做法是为装载工作估计合理的使用空间

    交叉提交

    交叉提交也可能产生ORA-01555错误,可以通过commit x 行降低回滚空间,但是系统变慢,产生更多的undo和redo,必然导致ORA-01555

    最合适的配置方法,为系统配置一个合适大小的回滚段

    延迟块清除

    Oracle确定前面事务使用的回滚段(block header),确定块头是否指出前一事务的提交状态

    为了得到由于推迟块清除产生的ORA-10555,必须满足以下条件

    已经修改并commit,块依旧没有自动清除,超过的块超过了能适应SGA块缓冲区高速缓冲的10%

    论读书
    睁开眼,书在面前
    闭上眼,书在心里
  • 相关阅读:
    CSS3中新增的对文本和字体的设置
    PAT1107:Social Clusters
    Git的一些操作
    PAT1029:Median
    PAT1024:Palindromic Number
    PAT1028:List Sorting
    PAT1035: Password
    PAT1133:Splitting A Linked List
    PAT1017:Queueing at Bank
    PAT1105:Spiral Matrix
  • 原文地址:https://www.cnblogs.com/YC-L/p/14663800.html
Copyright © 2011-2022 走看看