【開發篇sql】 基礎概述(二) undo和redo
2,undo和redo
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
上面的操作產生了1條undo記錄,再看看一次插入多條記錄的情況:
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語句也產生了1個undo記錄,再看看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行,只記錄插入記錄的rowid,delete因為需要把整行的前映像記錄到undo,所以產生最多的undo,update需要記錄行中被更新的欄位部分的前映像,因此一般來說介於insert和delete之間。
回滾段可以說是用來保持資料變化前映像而提供一致性讀和保證事務完整性的一段儲存區域。當一個事務開始的時候,首先把變化前的資料和變化後的資料先寫入日誌緩衝區,然後吧變化前的資料寫入回滾段,最後才在資料緩衝區中修改。
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的優化在效能調整一章中詳述。
Oracle的segment資訊可以在dba_segments或者sys_dba_segs中檢視,從下面的輸出資訊中可以看到幾個比較重要的段物件,如table,index,rollback。
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是產生使操作重做的資訊。Oracle的redo有兩種:online redo log(聯機),archivelog(歸檔)。
Lgwr迴圈的寫入聯機日誌,當前日誌日滿後,lgwr寫下一個日誌。Lgwr總是在一下條件之一滿足之時將緩衝重做日誌寫入磁碟:
1,每三秒;2,每當滿1/3或1MB;3碰到任何事務commit;
在事務commit或者rollback之前往往已經完成了一下工作:
已經在sga中產生了回滾段記錄,用於撤銷
已經在sga中產生了修改資料塊
已經在sga中產生了回滾和修改的重做,是的以上2個操作可以重做
根據lgwr的重新整理特點,一部分資料可能已經重新整理到了磁碟
已經獲得了所有的鎖定
當commit時,要做的工作如下:
為事務產生scn,lgwr寫磁碟,釋放鎖定,訪問修改事務塊,並清除之。
當rollback時,要做的工作如下:
使用回滾段的資料來撤銷修改,釋放鎖定。
同樣的,dml對redo產生的影響也是能夠測定的。
下列語句依次執行:
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的產生量。如果不結合起來看undo和redo的影響而來調整應用,很多時候結果往往是不確定的。值得注意的是觸發器的不同型別對redo的產生也有影響,比如對update使用after觸發器,將不會影響重做。開發過程中,可以大致瞭解一下重做的數量:估計事務的大小,需要修改的資料量,提交的頻率,dml型別佔比(考慮到update產生大約2倍的重做,insert和delete大約為1倍)。而以上的表中似乎看不到不同dml對redo的區別,這是因為b的欄位型別為varchar2(20),本身的修改量很小,如果吧欄位修改為char(2000),則數字規律很明顯,有關字元型別的細節在資料庫設計一章節中詳述。
另外redo是備份和恢復的一個支撐原理。有關聯機日誌和歸檔日誌的管理和使用在備份恢復一章中詳解。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/16179598/viewspace-662794/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【開發篇sql】 基礎概述(三) DDL和DMLSQL
- 【開發篇sql】 基礎概述(一) 鎖定和事務SQL
- Redo 和 Undo 概念解析
- undo log和redo log
- oracle的redo和undoOracle
- redo和undo的區別
- oracle redo和undo系列一Oracle Redo
- MS SQL基礎教程:備份和恢復概述SQL
- Flink Table & SQL API--動態表與Redo和UndoSQLAPI
- Oracle Redo and UndoOracle Redo
- 【REDO】Oracle redo undo 學習Oracle Redo
- SQL Server基礎之《檢視的概述和基本操作》SQLServer
- 視訊開發基礎篇
- 【基礎篇索引】索引基礎(二)索引
- SQLServer的檢查點、redo和undoSQLServer
- MySQL中的redo log和undo logMySql
- MySQL Undo Log和Redo Log介紹MySql
- Oracle的redo 和undo的區別Oracle
- UNDO REDO 區別
- 基於Redo Log和Undo Log的MySQL崩潰恢復流程MySql
- iOS開發小記-基礎篇iOS
- iOS 藍芽開發·基礎篇iOS藍芽
- 關於Oracle的redo和undo的理解Oracle
- 深入淺出-redo和undo記載01
- 深入淺出-redo和undo記載02
- 深入淺出redo和undo記載03
- 轉roger大師_計算sql語句產生的redo和undo大小SQL
- 動態SQL開發基礎和經驗再總結SQL
- MySQL 日誌 undo | redoMySql
- SQL Server調優系列基礎篇(並行運算總結篇二)SQLServer並行
- Flask RESTful API 開發----基礎篇 (1)FlaskRESTAPI
- Flask RESTful API 開發----基礎篇 (2)FlaskRESTAPI
- mybatis入門基礎(二)----原始dao的開發和mapper代理開發MyBatisAPP
- iOS開發基礎篇--CAShapeLayer的strokeStart和strokeEnd屬性iOS
- 【Flutter】開發之基礎Widget(二)Flutter
- Mac開發基礎06-NSView(二)MacView
- Java面試題-基礎篇二Java面試題
- Java面試題基礎篇(二)Java面試題