3.3 Redo產生場景
我們知道,Oracle Redo是以條目(Redo Entries/Records)的形式記錄數據庫的所有更改操作(OP)。更改操作主要包括:
數據庫物理文件更改:主要指的是數據庫物理文件的增減等操作;
數據庫運行狀態更改:數據庫當前狀態版本的更改(Current Status Version),例如數據庫檢查點(Checkpoint)等操作;
數據庫后臺進程寫操作:數據庫后臺進程對數據庫的操作,例如DBWR寫磁盤、LGWR寫日志等操作;
DML事務操作:DML事務對數據的更改操作;
數據字典DDL操作:DDL操作會更改數據字典,例如Drop、Truncate等DDL操作;
數據庫內部遞歸調用:更改數據庫內部字典表操作。
可以看到,數據庫更改是Redo產生的根源,下面將對Redo產生的主要場景進行介紹。
3.3.1 Redo與DML事務
DML事務會產生Redo。DML事務(索引行)與Redo OP的關系如表3-4所示。
索引行DML事務是最典型的DML,因此以索引行DML事物為例進行介紹更具代表性。
以表3-4所示為基礎,下面驗證索引鍵(Index Key)DML更新與Redo(OP)的詳細關系。
1)基礎數據準備,如下所示:
2)以索引鍵數據更新為基準,經過多次測試得到索引鍵DML更新與Redo(OP)的詳細關系,如表3-5所示。
通過表3-5可以看出:
Step1:將索引鍵(c1)的值從非Null更新到不同的非Null時,首先對索引鍵進行更新操作,接著對索引鍵進行刪除、插入操作;
從某種意義來講,Update操作可以看作Delete操作之后的Insert操作。
Step2:將索引鍵的值從非Null更新到相同的非Null時,只有索引鍵更新操作,不會產生回滾和重做信息;
Step3:將索引鍵的值從非Null更新到Null時,首先對索引鍵進行更新操作,然后對索引鍵進行刪除操作,沒有索引鍵的插入操作;
Step4:將索引鍵的值從Null更新到非Null時,首先索引鍵進行更新操作,接著跳過索引鍵刪除操作直接進行索引鍵插入操作。
為了簡化內容,上述步驟省略了事務開始(OP:5.2)和事務結束(OP:5.4)的描述。
不難看出:
DML中的Null不會影響索引操作;
更新索引鍵數據時,索引也會相應更新;
當索引創建較多時,索引行DML更新可能會影響到多個索引鍵的DML更新,這樣會產生大量的Redo,從而影響數據庫的整體性能。因此,在滿足性能需求的情況下,應當盡可能少地創建索引。
3.3.2 Redo與Block Cleanout
在一般情況下,當事務提交后,事務影響的數據塊的ITL標識會立即被清除。如果當事務提交后,事務數據塊的ITL沒有及時被清除(ITL仍處于打開狀態),那么將會產生延遲塊清除(Delayed Block Cleanout)。
Block Cleanout 會產生Redo,如下所示:
Block Cleanout可以由Select語句產生,這就意味著Select查詢也可能產生Redo。Block Cleanout詳細內容請參考4.2.3節。
Block Cleanout主要與事務“熱塊”緊密相關。因此,我們在進行數據庫優化設計時,應當盡可能地將“熱塊”事務分散到不同的數據塊中,這樣就可以減少Block Cleanout產生的概率,從而減少Redo的產生。
3.3.3 Redo與Block Write
從Oracle 9開始,DBWR進程將Block Buffer寫入磁盤操作(Block Write)會被記錄到Redo中。與此同時,數據庫恢復操作也會引發Block Write,如下所示:
可以看到,當數據庫恢復引發Block Write時,系統將Block Write信息完整地記錄在Redo中,體現了“Redo記錄數據庫所有更改”這一特點。
3.3.4 Redo與Hot Backup
當數據庫進行熱備(Hot Backup)操作時,熱備信息會記錄在Redo中,如下所示:
可以看到,當數據庫進行熱備時,系統將熱備信息完整地記錄在Redo中,確保熱備數據的可恢復性。
3.3.5 Redo與Direct Load
當進行數據直接路徑加載(Direct Load)時,也會將Direct Load信息記錄在Redo中,如下所示:
可以看到,當進行數據直接路徑加載時,系統仍然會將數據直接路徑加載的信息記錄到Redo中。相對于其他方式的數據加載方式,數據直接路徑加載將會產生較少的Redo。
Direct Load操作會越過Buffer Cache直接將數據寫入磁盤,從而產生較少的Redo。
3.3.6 Redo與Nologging
Nologging 日志記錄模式可以減少Redo的產生,但是Nologging的使用需要特別留意,這是因為:
Nologging 方式創建的數據庫對象將不可恢復;
一旦數據庫對象被設置為Nologging模式后,必須立即進行數據庫(對象)備份;
當使用Nologging完成特定操作后,強烈建議將數據庫對象的日志記錄模式恢復為Logging模式(默認模式)。可使用以下命令實現:
Alter [database] tablespace force logging;
Nologging模式下進行特定的數據庫操作可以提升數據庫性能,例如,在創建索引時就可以使用Nologging來加快索引創建的速度。
Nologging的使用級別:
對象級(Database/Tablespace/Table等)的使用,如下所示:
Create[Alter] table[index] table_name[index_name] parallel nologging;
SQL語句級的使用,如下所示:
Insert /+ nologging append/ into table_name select from xxx..;
Nologging可以減少Redo的產生,如下所示:
可以看出,采用Nologging模式后,Redo產生量大幅度降低。