在這里會介紹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 0
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但是卻沒有可用的??赡苁怯捎贒BWR沒有完成(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。(要考慮全面喲)
以及他們之間如何協同工作的。 什么是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 0
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但是卻沒有可用的??赡苁怯捎贒BWR沒有完成(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。(要考慮全面喲)