【開發篇sql】 基礎概述(二) undo和redo

yellowlee發表於2010-05-15

2undoredo

Undo

 

Oracle將所有的資料更改記錄在undo,這些記錄資訊可以使oracle使用rollback來撤銷更改操作。Undo的機制主要有兩個目的:一是用來允許讀不能阻塞寫入,寫入不能阻塞讀,二是可以使事務能夠rollback(回滾)。

事務能夠產生undo(回滾),且產生的undo記錄數量可以在動態效能檢視V$transaction中得到。用一個例子來看看undo的產生:

SQL> set autocommit off;

SQL> insert into t_test_undo values (2,'asd');

 

1 row created.

 

SQL>

SQL> select used_urec from v$session s,v$transaction t where

  2  s.audsid = sys_context('userenv','sessionid') and

  3  s.taddr = t.addr;

 

 USED_UREC

----------

         1

上面的操作產生了1undo記錄,再看看一次插入多條記錄的情況:

SQL> insert into t_test_undo

  2  select rownum + 50000, object_name from all_objects where rownum < 51;

 

 

50 rows created.

 

SQL> SQL> select used_urec from v$session s, v$transaction t

  2   where s.audsid=sys_context('userenv', 'sessionid') and

  3         s.taddr = t.addr;

 

 USED_UREC

----------

         2

上面的語句也只產生了一條undo

然後看看update的情形:

SQL> update t_test_undo a set a.b = 'asdsd' where a.a = 1;

 

1 row updated.

 

SQL> select used_urec from v$session s, v$transaction t

  2   where s.audsid=sys_context('userenv', 'sessionid') and

  3         s.taddr = t.addr;

 

 USED_UREC

----------

         3

這個update語句也產生了1undo記錄,再看看delete的情形:

SQL> delete from t_test_undo a where a.a <10;

 

2 rows deleted.

 

SQL> select used_urec from v$session s, v$transaction t

  2   where s.audsid=sys_context('userenv', 'sessionid') and

  3         s.taddr = t.addr;

 

 USED_UREC

----------

         5

可以看出,delete的每一條記錄都產生了一個undo記錄。

由此可以大概對比一下不同的語句產生的undo大小。

SQL>

SQL>

SQL> insert into t_test_undo values (10, 'asd');

 

1 row created.

 

SQL> select a.XIDUSN, a.UBAREC, a.UBABLK, a.USED_UBLK, a.USED_UREC

  2    from v$transaction a;

 

    XIDUSN     UBAREC     UBABLK  USED_UBLK  USED_UREC

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

         9         17        336          1          1

 

SQL> commit;

 

Commit complete.

 

SQL> select a.XIDUSN, a.UBAREC, a.UBABLK, a.USED_UBLK, a.USED_UREC

  2    from v$transaction a;

 

no rows selected

 

SQL> update t_test_undo a set a.b = 'qwe' where a.a = 10;

 

1 row updated.

 

SQL> select a.XIDUSN, a.UBAREC, a.UBABLK, a.USED_UBLK, a.USED_UREC

  2    from v$transaction a;

 

    XIDUSN     UBAREC     UBABLK  USED_UBLK  USED_UREC

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

         7          6       2701          1          1

 

SQL> commit;

 

Commit complete.

 

SQL> delete from t_test_undo a where a.a = 10;

 

1 row deleted.

 

SQL> select a.XIDUSN, a.UBAREC, a.UBABLK, a.USED_UBLK, a.USED_UREC

  2    from v$transaction a;

 

    XIDUSN     UBAREC     UBABLK  USED_UBLK  USED_UREC

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

         3         25       1057          1          1

 

SQL> commit;

 

Commit complete.

 

SQL> insert into t_test_undo values (10, 'asd');

 

1 row created.

 

SQL> update t_test_undo a set a.b = 'qwe' where a.a = 10;

 

1 row updated.

 

SQL> delete from t_test_undo a where a.a = 10;

 

1 row deleted.

 

SQL> select a.XIDUSN, a.UBAREC, a.UBABLK, a.USED_UBLK, a.USED_UREC

  2    from v$transaction a;

 

    XIDUSN     UBAREC     UBABLK  USED_UBLK  USED_UREC

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

         2         38      10021          1          3

 

SQL>

 

一般來說,insert產生了最少的undo,因為insert行的反操作是delete行,只記錄插入記錄的rowiddelete因為需要把整行的前映像記錄到undo,所以產生最多的undoupdate需要記錄行中被更新的欄位部分的前映像,因此一般來說介於insertdelete之間。

 

回滾段可以說是用來保持資料變化前映像而提供一致性讀和保證事務完整性的一段儲存區域。當一個事務開始的時候,首先把變化前的資料和變化後的資料先寫入日誌緩衝區,然後吧變化前的資料寫入回滾段,最後才在資料緩衝區中修改。

 

Undo segment頭部包含記錄了當前事務使用的undo segment資訊的一張表。一系列事務只使用一個undo segment儲存所有資料。許多併發的事務可以使用同一個undo segment

 

再來看看與undo相關的ora-01555

SQL> host oerr ora 1555

01555, 00000, "snapshot too old: rollback segment number %s with name \"%s\" too small"

// *Cause: rollback records needed by a reader for consistent read are

//         overwritten by other writers

// *Action: If in Automatic Undo Management mode, increase undo_retention

//          setting. Otherwise, use larger rollback segments

 

在相對穩定的資料庫中,出現這個錯誤大多數時候是程式碼需要調整,或者由於業務需要在某一時段進行大批量的業務處理,而對一些較大的查詢產生了影響。涉及到的undo的優化或者sql的優化在效能調整一章中詳述。

 

 

Oraclesegment資訊可以在dba_segments或者sys_dba_segs中檢視,從下面的輸出資訊中可以看到幾個比較重要的段物件,如tableindexrollback

SQL> select distinct segment_type from sys_dba_segs;

 

SEGMENT_TYPE

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

LOBINDEX

INDEX PARTITION

TABLE PARTITION

NESTED TABLE

ROLLBACK

LOB PARTITION

LOBSEGMENT

INDEX

TABLE

CLUSTER

TYPE2 UNDO

 

11 rows selected.

 

Redo

 

undo不同,undo是產生使操作撤銷的資訊,而redo是產生使操作重做的資訊。Oracleredo有兩種:online redo log(聯機),archivelog(歸檔)

Lgwr迴圈的寫入聯機日誌,當前日誌日滿後,lgwr寫下一個日誌。Lgwr總是在一下條件之一滿足之時將緩衝重做日誌寫入磁碟:

1,每三秒;2,每當滿1/31MB3碰到任何事務commit

在事務commit或者rollback之前往往已經完成了一下工作:

已經在sga中產生了回滾段記錄,用於撤銷

已經在sga中產生了修改資料塊

已經在sga中產生了回滾和修改的重做,是的以上2個操作可以重做

根據lgwr的重新整理特點,一部分資料可能已經重新整理到了磁碟

已經獲得了所有的鎖定

commit時,要做的工作如下:

        為事務產生scnlgwr寫磁碟,釋放鎖定,訪問修改事務塊,並清除之。

rollback時,要做的工作如下:

        使用回滾段的資料來撤銷修改,釋放鎖定。

同樣的,dmlredo產生的影響也是能夠測定的。

下列語句依次執行:

select a.SID, a.VALUE

  from v$mystat a, v$statname b

 where a.STATISTIC# = b.STATISTIC#

   and b.NAME like 'redo_size';

insert into t_test_undo values (12, '123');

commit;

select a.SID, a.VALUE

  from v$mystat a, v$statname b

 where a.STATISTIC# = b.STATISTIC#

   and b.NAME like 'redo_size';

update t_test_undo a set a.b = '321' where a = 12;

commit;

select a.SID, a.VALUE

  from v$mystat a, v$statname b

 where a.STATISTIC# = b.STATISTIC#

   and b.NAME like 'redo_size';

delete t_test_undo where a.a = 12;

commit;

select a.SID, a.VALUE

  from v$mystat a, v$statname b

 where a.STATISTIC# = b.STATISTIC#

   and b.NAME like 'redo_size';

 

得到的redo size數值如下表:

操作

Sid

Redo size

初始

144

0

Insert 一行

144

548

Update 一行

144

1140

Delete 一行

144

1732

 

同樣可以測試一次插入多行,更新多行和刪除多行對redo的產生量,並且可以測試逐條提交和一次提交對redo的產生量。如果不結合起來看undoredo的影響而來調整應用,很多時候結果往往是不確定的。值得注意的是觸發器的不同型別對redo的產生也有影響,比如對update使用after觸發器,將不會影響重做。開發過程中,可以大致瞭解一下重做的數量:估計事務的大小,需要修改的資料量,提交的頻率,dml型別佔比(考慮到update產生大約2倍的重做,insertdelete大約為1倍)。而以上的表中似乎看不到不同dmlredo的區別,這是因為b的欄位型別為varchar2(20),本身的修改量很小,如果吧欄位修改為char(2000),則數字規律很明顯,有關字元型別的細節在資料庫設計一章節中詳述。

 

另外redo是備份和恢復的一個支撐原理。有關聯機日誌和歸檔日誌的管理和使用在備份恢復一章中詳解。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/16179598/viewspace-662794/,如需轉載,請註明出處,否則將追究法律責任。

相關文章