使用Oradebug修改Oracle SCN
Oracle SCN對於資料庫執行、維護而言是至關重要的因素。在啟動從mount到open過程中,主要是各種檔案的SCN進行比較的行為。通常情況下,我們是不需要介入到Oracle SCN的取值和設定,甚至錯誤的干預可能會引起嚴重執行事故。
在之前的文章中,筆者介紹過使用隱含引數和跟蹤事件來推動Oracle SCN前進的方法。但是,在11.2.0.2之後的版本中,Oracle關閉了這個通道,這種方法不在有效。在高版本情況下,我們是可以透過oradebug工具對SCN進行修改。
注意:這種方法比較危險,請不要在投產環境下進行測試。
1、實驗環境說明
筆者使用Oracle 11g進行測試,版本為11.2.0.4。對應作業系統是Linux 6.5 64bit版本。
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 – Production
我們先聊聊Oracle的SCN。在資料庫內部,SCN是一個單向遞增的數字編號,控制檔案、資料檔案、線上Redo日誌、歸檔日誌和備份集合中,都包括這個數字編號。在內部檔案中,SCN是透過Base和Wrap兩個部分進行儲存。Base是SCN編號的基礎位,是透過32位二進位制位進行儲存。一旦超過這32位長度,系統會自動在Wrap進位。也就是說,Wrap表示的超過4G個數的進位次數。
使用Oracle oradebug修改SCN,可以在兩個場景下進行,就是Oracle啟動Open狀態和Mount狀態。下面分別進行說明。
2、Open狀態下SCN修改
在Open狀態,系統的SCN是在不斷的向前推動,即使對外沒有事務操作,系統內部SCN編號也在不斷的前進。我們先將資料庫進入open狀態。
SQL> alter database open;
Database altered.
SQL> select CHECKPOINT_CHANGE#, current_scn from v$database;
CHECKPOINT_CHANGE# CURRENT_SCN
------------------ -----------
1753982 1754355
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
1754364
此時,從系統中提取出的SCN編號約為1754364,顯然沒有超過wrap的進位4G,變化為16進位制如下:
SQL> select to_char(1754364, 'XXXXXXXX') from dual;
TO_CHAR(1754364,'XXXXXXXX')
---------------------------
1AC4FC
使用oradebug檢視記憶體中SCN對應的變數。
SQL> oradebug setmypid
Statement processed.
SQL> oradebug dumpvar sga kcsgscn_
kcslf kcsgscn_ [06001AE70, 06001AEA0) = 001AC52A 00000000 00000000 00000000 00000065 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000
其中,0x001AC52A近似SCN的Base部分。注意:Linux系統是Little位的作業系統,Base在前,Wrap在後。
SQL> select to_number('1AC52A','xxxxxx') from dual;
TO_NUMBER('1AC52A','XXXXXX')
----------------------------
1754410
下面計劃將Base修改為1800000,檢視16進製取值。
SQL> select to_char(1800000, 'XXXXXXXX') from dual;
TO_CHAR(1800000,'XXXXXXXX')
---------------------------
1B7740
使用poke命令將計算好的值寫入進去。
SQL> oradebug poke 0x06001AE70 4 0x001B7740
BEFORE: [06001AE70, 06001AE74) = 001AC66F
AFTER: [06001AE70, 06001AE74) = 001B7740
SQL> oradebug DUMPvar SGA kcsgscn_
kcslf kcsgscn_ [06001AE70, 06001AEA0) = 001B7745 00000000 00000000 00000000 00000164 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000
SQL>
poke命令中,第一位引數是對應寫入的記憶體位數,第二位引數是寫入長度,第三位引數是寫入取值。預設寫入取值是10進位制,我們在這裡指定寫入16進位制。
每一個取值段,用8個16進位制對應,對應到數字位數是4位。此時檢視Oracle情況。
SQL> select CHECKPOINT_CHANGE#, current_scn from v$database;
CHECKPOINT_CHANGE# CURRENT_SCN
------------------ -----------
1753982 1800400
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
1800402
SQL> select file#, checkpoint_change# from v$datafile;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 1753982
2 1753982
3 1753982
4 1753982
5 1753982
6 1753982
7 1753982
7 rows selected
SQL> select file#, checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 1753982
2 1753982
3 1753982
4 1753982
5 1753982
6 1753982
7 1753982
7 rows selected
從上面看,記憶體和控制檔案中新的取值已經寫入進去了。但是各個檔案的頭塊和檢查點還沒有反應過來。此時可以使用checkpoint強制寫入。
SQL> alter system checkpoint;
System altered.
SQL> select file#, checkpoint_change# from v$datafile;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 1800422
2 1800422
3 1800422
4 1800422
5 1800422
6 1800422
7 1800422
7 rows selected
SQL> select file#, checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 1800422
2 1800422
3 1800422
4 1800422
5 1800422
6 1800422
7 1800422
7 rows selected
SQL> select CHECKPOINT_CHANGE#, current_scn from v$database;
CHECKPOINT_CHANGE# CURRENT_SCN
------------------ -----------
1800422 1800433
此時,關閉重啟系統也不會有問題。篇幅原因,不進行具體展示。那麼,很多時候SCN錯誤是會影響到開啟資料庫的,我們可能都不能進入open狀態。從mount狀態下我們怎麼修改SCN編號。
3、Mount狀態修改SCN編號
我們測試進入mount狀態。
SQL> startup mount
ORACLE instance started.
Total System Global Area 3540881408 bytes
Fixed Size 2258320 bytes
Variable Size 855640688 bytes
Database Buffers 2667577344 bytes
Redo Buffers 15405056 bytes
Database mounted.
此時,oradebug命令匯出記憶體取值。
SQL> oradebug setmypid
Statement processed.
SQL> oradebug DUMPvar SGA kcsgscn_
kcslf kcsgscn_ [06001AE70, 06001AEA0) = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000
注意:在mount狀態下,記憶體中的SCN取值都是0,包括base和wrap兩部分。我們這次修改wrap從0到1。這個過程中,我們需要寫入base和wrap兩個部分,如果我們只寫入了wrap部分,base部分保持0,那麼系統執行的時候,會從base為0開始。
此時,需要檢視一下當前檔案裡面SCN是多少。
SQL> select file#, checkpoint_change# from v$datafile;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 1800920
2 1800920
3 1800920
4 1800920
5 1800920
6 1800920
7 1800920
7 rows selected
SQL> select file#, checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 1800920
2 1800920
3 1800920
4 1800920
5 1800920
6 1800920
7 1800920
7 rows selected
SQL> select CHECKPOINT_CHANGE#, current_scn from v$database;
CHECKPOINT_CHANGE# CURRENT_SCN
------------------ -----------
1800920 0
計算1800920對應到16進製取值為:0x001B7AD8。下面分別寫入base和wrap取值。
SQL> oradebug DUMPvar SGA kcsgscn_
kcslf kcsgscn_ [06001AE70, 06001AEA0) = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000
SQL> oradebug poke 0x06001AE70 4 0x001B7AD8
BEFORE: [06001AE70, 06001AE74) = 00000000
AFTER: [06001AE70, 06001AE74) = 001B7AD8
SQL> oradebug poke 0x06001AE74 4 0x00000001
BEFORE: [06001AE74, 06001AE78) = 00000000
AFTER: [06001AE74, 06001AE78) = 00000001
SQL> oradebug DUMPvar SGA kcsgscn_
kcslf kcsgscn_ [06001AE70, 06001AEA0) = 001B7AD8 00000001 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000
啟動資料庫。
SQL> alter database open;
Database altered.
SQL> select CHECKPOINT_CHANGE#, current_scn from v$database;
CHECKPOINT_CHANGE# CURRENT_SCN
------------------ -----------
4296768217 4296768485
SQL> select file#, checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 4296768217
2 4296768217
3 4296768217
4 4296768217
5 4296768217
6 4296768217
7 4296768217
7 rows selected
SQL> select file#, checkpoint_change# from v$datafile;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 4296768217
2 4296768217
3 4296768217
4 4296768217
5 4296768217
6 4296768217
7 4296768217
7 rows selected
顯然在open的時候,寫入的checkpoint在所有檔案中。寫入的wrap頭也比較清晰。
SQL> select 4296768217/(4*1024*1024*1024) from dual;
4296768217/(4*1024*1024*1024)
-----------------------------
1.0004193095956
SQL> oradebug DUMPvar SGA kcsgscn_
kcslf kcsgscn_ [06001AE70, 06001AEA0) = 001B7C1D 00000001 00000000 00000000 00000047 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000
4、結論
使用oradebug直接修改記憶體SCN,是我們在故障修復時候非常快捷的方法。不過,快捷建立在對內部機制清晰理解的前提之下。所以,無論何種場景進行修復,有備份、可恢復是我們工作的基本前提。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-2127169/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- oracle oradebug使用詳解Oracle
- ordebug 手動修改Oracle sga scnOracle
- ORACLE EVENT && ORADEBUGOracle
- 【kingsql分享】使用BBED修改Oracle資料檔案頭推進SCNSQLOracle
- Oracle:SCNOracle
- 【SCN】Oracle SCN 詳細介紹Oracle
- 【SCN】Oracle推薦scn命令參考Oracle
- 【SCN】Oracle檢查scn值指令碼Oracle指令碼
- Oracle SCN詳解Oracle
- ORACLE -詳解SCNOracle
- oracle的scn及sequenceOracle
- 透過修改控制檔案scn推進資料庫scn資料庫
- oradebug的使用說明
- Oracle 檢查點涉及的SCNOracle
- Oracle的SCN顯示問題Oracle
- oracle基於SCN增量恢復Oracle
- Oracle SCN健康狀態檢查Oracle
- Oracle的DBMS_SCN修正以及SCN的auto-rollover新特性Oracle
- Oracle SCN機制詳細解讀Oracle
- oracle 推進scn(poke、gdb、event、bbed)方法Oracle
- BBED 修改oracle 資料檔案的 SCN 號來做資料庫不完全恢復。Oracle資料庫
- 使用NID修改Oracle資料庫名Oracle資料庫
- Oracle資料庫中的多種SCN彙總Oracle資料庫
- Oracle 之利用BBED修改資料塊SCN----沒有備份資料檔案的資料恢復Oracle資料恢復
- 【BBED】使用BBED修改資料檔案SCN,使該檔案從offline轉變為online
- 用oradebug掛起程式
- [20180619]oradebug peek.txt
- Oracle修改時區Oracle
- oracle nid修改dbnameOracle
- Oracle 限制業務使用者自身修改密碼Oracle密碼
- oracle11g修改使用者名稱Oracle
- 【恩墨學院】深入剖析 - Oracle SCN機制詳細解讀Oracle
- [20180625]oradebug peek 2.txt
- Oracle 字符集修改Oracle
- oracle中的某一個使用者名稱修改Oracle
- [20210407]oradebug dump heapdump_addr.txt
- oracle如何修改單個使用者密碼永不過期Oracle密碼
- oracle ora-00333 修改案例Oracle
- Oracle 增加 修改 刪除 列Oracle