System Change Number (SCN) 是 Oracle 內部時鐘,10g 前無內建函數可與壁鐘時間互轉,只能靠 LogMiner 分析歸檔。10g 引入 SCN_TO_TIMESTAMP、TIMESTAMP_TO_SCN 及 DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER,讓閃回查詢、時間點恢復可直接用人類可讀時間。本文實測轉換流程並揭示適用邊界。
| 函數 | 用途 | 範例 |
|---|---|---|
DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER | 取得當前 SCN | SELECT dbms_flashback.get_system_change_number FROM dual; |
SCN_TO_TIMESTAMP(scn) | SCN → 時間戳 | SELECT scn_to_timestamp(8908390522972) FROM dual; |
TIMESTAMP_TO_SCN(ts) | 時間戳 → SCN | SELECT timestamp_to_scn(scn_to_timestamp(8908390522972)) FROM dual; |
SQL> COL scn FOR 9999999999999
SQL> SELECT dbms_flashback.get_system_change_number scn FROM dual;
SCN
--------------
8908390522972
SQL> SELECT scn_to_timestamp(8908390522972) scn FROM dual;
SCN
---------------------------------
05-JAN-07 10.56.30.000000000 AM
SQL> SELECT timestamp_to_scn(scn_to_timestamp(8908390522972)) scn FROM dual;
SCN
--------------
8908390522972
雙向轉換精確可逆,誤差在 3 秒內(SCN 粒度約 3 秒/次)。
轉換依賴內部映射表(由 SMON 維護),映射範圍約等於 V$ARCHIVED_LOG.FIRST_CHANGE# 覆蓋的區間。
SQL> SELECT min(FIRST_CHANGE#), max(FIRST_CHANGE#) FROM v$archived_log;
MIN(FIRST_CHANGE#) MAX(FIRST_CHANGE#)
------------------ ------------------
8907349093953 8908393582271
SQL> SELECT scn_to_timestamp(8907349093953) FROM dual;
ORA-08181: specified number is not a valid system change number
-- 低於最小歸檔 SCN,轉換失敗
SQL> SELECT scn_to_timestamp(8908393582271) FROM dual;
SCN
-------------------------------------------
05-JAN-07 11.45.50.000000000 AM
-- 最高歸檔 SCN 可正常轉換
結論:超出歸檔保留範圍的歷史 SCN 無法轉換,報 ORA-08181。
-- 需求:查詢 10 分鐘前的員工表狀態
VARIABLE v_scn NUMBER;
EXEC :v_scn := timestamp_to_scn(systimestamp - interval '10' minute);
SELECT * FROM employees AS OF SCN :v_scn;
-- 或直接用時間戳(10gR2+)
SELECT * FROM employees AS OF TIMESTAMP (systimestamp - interval '10' minute);
DB_FLASHBACK_RETENTION_TARGET 確保映射窗口覆蓋業務所需回溯範圍AS OF TIMESTAMP,免去手動轉 SCN 步驟SCN-Time 雙向轉換是 10g 閃回技術的基石,讓「時間旅行」從 DBA 專屬技能變為開發者可用的 API。但其可用性受限於歸檔保留窗口,生產環境務必規劃足夠的 DB_FLASHBACK_RETENTION_TARGET 並監控歸檔目的地空間,確保關鍵時間點均可精準定位。