前一期看了Oracle在redo上保持事務前滾的一致性,同樣Oracle在Undo的管理機制也是現代事務型數據庫的工程典范。核心在于通過多版本并發控制(MVCC)技術,在保障數據一致性與提升系統性能之間實現精妙平衡。Undo機制構建了原子事務的物理基礎,通過存儲數據前像實現秒級回滾。MVCC架構使讀寫操作完全解耦。Undo的智能空間管理(AUM)和保留期自動優化特性,精準控制RTO/RPO指標。通過UNDO_RETENTION GUARANTEE策略,可以為業務側帶來數據保險的時間窗口。引出另外另外一個話題:Flashback的實現對Undo有要求,然而兩者處理的事務又大大不同(單開一期),這次重點是Oracle的Undo機制。
一、Undo機制核心功能與技術原理
1. 核心功能矩陣
?功能類別? | ?具體實現 | ?技術原理? |
?事務回滾? | 回滾單條SQL或整個事務 | 存儲數據前鏡像鏈表,通過回滾指針(ROLL_PTR)構建版本鏈 |
?讀一致性? | MVCC多版本控制 | 基于SCN(System Change Number)構建一致性快照視圖 |
?實例恢復? | 崩潰后回滾未提交事務 | SMON進程應用Undo日志回滾未提交事務 |
?閃回技術? | Flashback Query/Table | 時間戳與SCN映射,訪問歷史Undo數據 |
?臨時表優化 | 12c+臨時Undo | 隔離存儲臨時表變更,減少Redo生成 |
2. 技術演進歷程
- 需要DBA手動創建和管理回滾段
- 易出現空間爭用錯誤(ORA-01555)
- 事務回滾需掃描整個段,效率低
- 引入UNDO_TABLESPACE參數
- 自動分配和管理Undo段
- UNDO_RETENTION參數控制保留時間
- In-Memory Undo(IMU)技術
- 共享池中分配私有Undo緩沖區
- 減少60%磁盤I/O和Redo生成
- 動態計算TUNED_UNDORETENTION
- 自動避免ORA-30036(空間不足)和ORA-01555(快照過舊)
- 全局臨時表(GTT)的Undo存入臨時表空間
- 減少75% Redo日志量
- 物理備庫支持臨時表DML操作
- Undo數據列式存儲壓縮
- 減少40%空間占用
- 優化數據倉庫場景
二、Undo日志技術原理深度解析
1. 數據結構
- XID:事務ID(16字節,包含回滾段號+槽號+序列號)
- UBA:前序Undo記錄地址(文件號+塊號+記錄偏移)
- Opcode:操作類型標識(0x02=INSERT, 0x04=UPDATE, 0x10=DELETE)
- Flags:狀態標志位(活動/過期等)
- Data Length:數據長度
- RowID:修改行的物理地址
- ColID:修改列標識符
- OldVal:修改前的列值
2. 存儲架構
- Undo表空間:專用存儲容器
- 數據文件:物理存儲文件(如undotbs01.dbf)
- 回滾段:每個事務綁定獨立段
- 區(Extents):8個連續塊組成的分配單元
- 塊(Blocks):標準8KB Oracle塊
- Undo記錄:實際存儲單元
- ?活動區(Active)??:事務進行中,強制保留
- ?未過期區(Unexpired)??:已提交+保留期內,優先保留
- ?過期區(Expired)??:超保留期,可覆蓋使用
3. 寫入流程
- DML操作觸發Undo記錄生成
- Undo記錄寫入Buffer Cache
- 同步生成Redo日志(Write-Ahead Logging)
- LGWR進程將Redo寫入日志文件
- DBWn進程異步將Undo數據寫入磁盤
- 事務提交時更新狀態
三、關鍵配置與管理策略
1. 核心參數配置
-- 基礎配置 --
ALTER SYSTEM SET undo_management = AUTO; -- 啟用自動管理
ALTER SYSTEM SET undo_tablespace = undotbs2; -- 指定表空間
ALTER SYSTEM SET undo_retention = 1800 SCOPE=BOTH;-- 保留30分鐘
--
show parameter undo;
NAME TYPE VALUE
----------------- ------- --------
temp_undo_enabled boolean FALSE
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
-- 高級優化 --
ALTER SYSTEM SET "_in_memory_undo" = TRUE; -- 啟用IMU(10g+)
ALTER SYSTEM SET temp_undo_enabled = TRUE; -- 啟用臨時Undo(12c+)
--System altered.
2. 表空間管理
?創建表空間:?
CREATE UNDO TABLESPACE undotbs2DATAFILE '/opt/oracle/oradata/FREE/FREEPDB1/undotbs2_01.dbf' SIZE 20GAUTOEXTEND ON NEXT 1G MAXSIZE UNLIMITEDRETENTION GUARANTEE; -- 關鍵系統啟用保證模式
?空間維護操作:??
-- 空間回收
ALTER TABLESPACE undotbs1 SHRINK SPACE KEEP 15G;
-- 表空間切換
ALTER SYSTEM SET UNDO_TABLESPACE = undotbs2;
-- 刪除舊表空間
DROP TABLESPACE undotbs1 INCLUDING CONTENTS AND DATAFILES;
3. 監測體系
?空間壓力監控:?
SELECT TO_CHAR(begin_time, 'YYYY-MM-DD HH24:MI') AS snapshot_time,undoblks AS undo_blocks_generated,maxquerylen AS longest_query_sec,ssolderrcnt AS ora_01555_count,tuned_undoretention AS actual_retention_sec
FROM v$undostat
ORDER BY begin_time DESC;
?事務級監控:??
SELECT s.sid,s.username,t.start_time,t.used_ublk AS undo_blocks_used,t.used_urec AS undo_records_used
FROM v$transaction t
JOIN v$session s ON t.ses_addr = s.saddr;
--11g 生產庫SID USERNAME START_TIME UNDO_BLOCKS_USED UNDO_RECORDS_USED
-- -------------------- -------------------- ---------------- ------------
3401 HIS50 01/15/24 21:20:00 1 1
?文件級監控:??
SELECT file_name,bytes/1024/1024 AS size_mb,maxbytes/1024/1024 AS max_size_mb,autoextensible,increment_by * 8192/1024/1024 AS increment_mb
FROM dba_data_files
WHERE tablespace_name = 'UNDOTBS1';
---
FILE_NAME SIZE_MB MAX_SIZE_MB AUTOEXTENSIBLE INCREMENT_MB
__________________________________________________ __________ ___________________ _________________ _______________
/opt/oracle/oradata/FREE/FREEPDB1/undotbs01.dbf 345 33554431.9765625 YES 5
四、驗證腳本集
1. 讀一致性驗證
--會話1
UPDATE HR.employees SET salary = 15000 WHERE employee_id = 100;
-- 不提交事務--會話2
SELECT salary FROM HR.employees e WHERE e.employee_id = 100;
-- 應返回修改前的值(比如6000)
2. 保留期保證驗證?
-- 設置保留保證
ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;-- 生成測試數據并等待超保留期
BEGINUPDATE HR.employees SET salary = salary * 1.1;COMMIT;DBMS_LOCK.SLEEP(2000); -- 等待超過undo_retention
END;
/-- 嘗試歷史查詢
SELECT salary FROM HR.employees AS OF TIMESTAMP SYSTIMESTAMP - INTERVAL '30' MINUTE
WHERE employee_id = 100;
-- 應成功返回歷史數據
3. 臨時Undo性能驗證?
-- 啟用臨時Undo
ALTER SESSION SET temp_undo_enabled = TRUE;-- 創建臨時表
CREATE GLOBAL TEMPORARY TABLE temp_emp AS SELECT * FROM HR.employees;-- 測試I/O對比
SET AUTOTRACE STATISTICS;-- 臨時表操作
INSERT INTO temp_emp SELECT * FROM HR.employees;
COMMIT;
-- 記錄統計信息中的redo size-- 常規表操作
INSERT INTO HR.employees SELECT * FROM employees WHERE 1=0;
ROLLBACK;
-- 比較redo size差異(臨時表應顯著減少)
?4. IMU效果驗證
-- 檢查IMU狀態
SELECT name, value
FROM v$sysstat
WHERE name LIKE '%IMU%flush%';
--
NAME VALUE
--------------------------------------------- ----------
IMU recursive-transaction flush 3401
IMU undo retention flush 0
IMU ktichg flush 2
IMU bind flushes 0
IMU mbu flush 0
-- 生成負載測試
DECLARECURSOR c_emp IS SELECT * FROM HR.employees FOR UPDATE;
BEGINFOR r IN c_emp LOOPUPDATE HR.employees SET salary = salary * 1.01 WHERE CURRENT OF c_emp;END LOOP;COMMIT;
END;
/
-- 再次檢查IMU統計
五、最佳實踐指南
1. 容量規劃公式
所需空間(GB) = (DPM × ARS × UR) / (10243) × 1.5
- DPM?:每分鐘DML操作數
- ?ARS?:平均行大小(字節)
- ?UR?:保留期(分鐘)
- ?1.5?:安全系數(含元數據開銷)
2. 高可用架構設計
- 創建至少兩個Undo表空間
- 定期切換:ALTER SYSTEM SET UNDO_TABLESPACE=undotbs2;
- 保留舊表空間24小時后刪除
-- 關鍵系統啟用保留保證
ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;
3. 參數優化對比?
?場景類型? | ?undo_retention | ?IMU? | ?臨時Undo? | ?壓縮? |
?OLTP系統? | 2小時 | 啟用 | 啟用 | 禁用 |
?數據倉庫? | 6小時 | 按需 | 按需 | 啟用 |
?金融系統? | 12小時+保證 | 啟用 | 啟用 | 禁用 |
?開發環境? | 24小時 | 可選 | 可選 | 可選 |
4. 故障處理一覽?
?故障現象? | 可能原因? | ?解決方案? |
ORA-01555 | Undo保留不足 | 增加UNDO_RETENTION或表空間 |
ORA-30036 | 空間不足 | 擴展表空間或啟用AUTOEXTEND |
閃回失敗 | 歷史數據不可用 | 啟用RETENTION GUARANTEE |
性能下降 | IMU未啟用 | 檢查"_in_memory_undo"參數 |
六、演進趨勢與未來方向
- CDB/PDB多租戶Undo隔離
- 基于負載的自動伸縮策略
- 跨區域Undo復制
- AI的到來自動預測和優化
- 利用PMEM存儲Undo日志
- 持久內存直接訪問加速
- 崩潰恢復時間縮短90%
七、使用體驗
- 根據業務負載科學規劃空間容量
- OLTP系統啟用IMU和臨時Undo
- 關鍵業務啟用RETENTION GUARANTEE
- 建立多層次監控預警體系
- 定期進行健康檢查和性能優化