第七章Redo and Undo (一)

第七章Redo and Undo (一)

oracle dba redo undo

日月明王BLOG:http://sunmoonking.spaces.live.com
         在这里会介绍 UNDO REDO 是如何产生的,对 TRANSACTIONS 的影响,以及他们之间如何协同工作的。
什么是 REDO
       REDO 记录 transaction logs ,分为 online archived 。以恢复为目的。
       比如,机器停电,那么在重起之后需要 online redo logs 去恢复系统到失败点。
       比如,磁盘坏了,需要用 archived redo logs online redo logs 区恢复数据。
       比如, truncate 一个表或其他的操作,想恢复到之前的状态,同样也需要。
什么是 UNDO
       REDO 是为了重新实现你的操作,而 UNDO 相反,是为了撤销你做的操作,比如你得一个 TRANSACTION 执行失败了或你自己后悔了,则需要用 ROLLBACK 命令回退到操作之前。回滚是在逻辑层面实现而不是物理层面,因为在一个多用户系统中,数据结构, blocks 等都在时时变化,比如我们 INSERT 一个数据,表的空间不够,扩展了一个新的 EXTENT ,我们的数据保存在这新的 EXTENT 里,其它用户随后也在这 EXTENT 里插入了数据,而此时我想 ROLLBACK ,那么显然物理上讲这 EXTENT 撤销是不可能的,因为这么做会影响其他用户的操作。所以, ROLLBACK 是逻辑上回滚,比如对 INSERT 来说,那么 ROLLBACK 就是 DELETE 了。
COMMIT
       以前,常想当然地认为,一个大的 TRANSACTION (比如大批量地 INSERT 数据)的 COMMIT 会花费时间比短的 TRANSACTION 长。而事实上是没有什么区别的,因为 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 ,前面有两个脚本, mystat mystat2
SQL> @mystat "redo size"
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                           1016784
SQL> insert into t select * from big_table;
已创建 46990 行。
SQL> @mystat2
NAME                                                                      V
---------------------------------------------------------------- ----------
DIFF
----------------
redo size                                                           6604308
       5,587,524
       看到产生了 5,587,524 REDO ,再对比下用 NOLOG 插入
SQL> @mystat "redo size"
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                           6604308
SQL> insert /*+ APPEND */ into t select * from big_table;
已创建 46990 行。
SQL> @mystat2
NAME                                                                      V
---------------------------------------------------------------- ----------
DIFF
----------------
redo size                                                           6616220
          11,912
       看到 APPEND 插入用了 11,912 字节的 REDO ,比一般性插入要少很多。
       或者用这个 PROCEDURE 也可以观察 SQL 消耗的 REDO
create or replace procedure do_sql( p_sql in varchar2 )
2 as
3 l_start_redo number;
4 l_redo number;
5 begin
6 select v$mystat.value
7 into l_start_redo
8 from v$mystat, v$statname
9 where v$mystat.statistic# = v$statname.statistic#
10 and v$statname.name = 'redo size';
11
12 execute immediate p_sql;
13 commit;
14
15 select v$mystat.value-l_start_redo
16 into l_redo
17 from v$mystat, v$statname
18 where v$mystat.statistic# = v$statname.statistic#
19 and v$statname.name = 'redo size';
20
21 dbms_output.put_line
22 ( to_char(l_redo,'9,999,999') ||' bytes of redo generated for "' ||
23 substr( replace( p_sql, chr(10), ' '), 1, 25 ) || '"...' );
24 end;
25 /       
      用法就不多说了。
减少 REDO
       既然 REDO 这么消耗资源,那我们能屏蔽 REDO 吗?显然不能,那我们能减少 REDO 吗?这是可以的(注意, 9.2 以后,可以用 FORCE  LOGGING 开关来控制是否强制 REDO ,如果 YES ,则不管 NOLOGGING 还是 APPEND 都是不起任何作用的,可以 SELECT FORCE_LOGGING FROM V$DATABASE 查看是否 FORCE 。另外需要明白,没有一个办法能彻底不记录 REDO ,只能是减少 REDO 。因为不管如何,数据字典总是要产生一些 REDO 的。
create table nologging as select xxx 新建的表没有原来表的索引和默认值 , 只有非空 (not null) 的约束素条件可以继承过来 .
INSERT /*+ APPEND */ INTO target_tablename SELECT 如果运行此命令时还有对 target_tablename DML 操作会排队在它后面 , OLTP 系统在用的表操作是不合适的。快速插入数据可以指定 append 提示,但是需要注意 noarchivelog 模式下,默认用了 append 就是 nologging 模式的。    archivelog 下,需要把表设置程 Nologging 模式。可以通过如下语句设置为 NO FORCE LOGGING                  Alter database no force logging;
这两种方法转移数据时没有用 SGA 里数据缓冲区和事物处理的回滚段 , 也不写联机事物日志,就象数据库装载工具 SQLLOAD 一样直接把数据写到物理文件。
REDO 的问题
    有时,会在 ALERT 中发现
Thread 1 cannot allocate new log, sequence 1466
Checkpoint not complete
Current log# 3 seq# 1465 mem# 0: /home/ora10g/oradata/ora10g/redo03.log
       这问题出现在系统尝试 reuse online redo log file 但是却没有可用的。可能是由于 DBWR 没有完成 (Checkpoint not complete) ARCH 没有完成。
       1 DBWR ,用多 DBWR  process ,合理分布数据,
       2 ,增加 REDO LOG FILE
       3 ,扩大 REDO 的大小
       4 ,让 CHECKPOINT 发生更频繁,可以减少 block buffer cache FAST_START_MTTR_TARGET LOG_CHECKPOINT_INTERVAL LOG_CHECKPOINT_TIMEOUT 。(要考虑全面哟) 

你可能感兴趣的:(sql,table,delete,insert,logging,transactions)