首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle Redo Log 並行機制深度解析:Shared Strand 與 Private Strand 的演進與調優

     編輯:Oracle 資料庫基礎

背景:Redo 生成鏈路與 Latch 爭用

用戶進程 PGA 生成 Redo Entry → 獲取 Redo Copy Latch**(多個,CPU_COUNT*2) → 獲取 **Redo Allocation Latch**(單一) → 分配 Log Buffer 空間 → 釋放 Allocation Latch → 拷貝 Redo Entry → 釋放 Copy Latch。高併發 OLTP 下,單一 Allocation Latch 成為嚴重熱點。

第一代優化:Shared Strand(9.2 引入)

原理

將 Log Buffer 劃分為多個 Strand(共享絞),每個 Strand 獨立受一個 Redo Allocation Latch 保護。分配並行化,Latch 爭用指數級下降。

關鍵參數(10g/11g)

參數含義備註
_log_parallelism初始 Strand 數10g 起隱含
_log_parallelism_max最大 Strand 數不超過 CPU_COUNT
_log_parallelism_dynamic是否動態調整默認 TRUE

查看 Strand 分配

SELECT INDX, STRAND_SIZE_KCRFA FROM X$KCRFSTRAND WHERE LAST_BUF_KCRFA != '00';
-- 共享 Strand 信息
SHOW PARAMETER LOG_BUFFER;
-- 每 Strand 大小 = LOG_BUFFER / 共享 Strand 數

調優指南

  • CPU ≤ 16:默認 2 個 Strand 通常足夠。
  • 出現 redo allocation latch 等待時,每增加 16 CPU 考慮 +1 Strand,上限 8。
  • 11g 移除 _log_parallelism,由 _log_parallelism_max、_log_parallelism_dynamic、CPU_COUNT 共同決定。

第二代優化:Private Strand(10g 引入)

架構變革

  • 不再從 Log Buffer 劃分,而是從 Shared Pool** 動態分配 65KB/個(11g 額外 4KB 管理開銷)的 **Private Strand**。
  • 每個活躍事務獨享一個 Private Strand,受獨立 Allocation Latch 保護。
  • Redo 生成直接寫入 Private Strand,**無需 Redo Copy Latch**,Commit/Flush 時**批量**寫入 Log File(需獲取 Redo Copy Latch 一次),大幅減少 Latch 獲取/釋放次數與 CPU 開銷。

流程對比

階段傳統/Shared StrandPrivate Strand
事務開始獲取 Allocation Latch獲取 Private Strand Allocation Latch(失敗回退 Shared)
Redo 生成PGA → Log Buffer(需 Copy Latch)直接在 Private Strand 生成(無 Copy Latch)
Flush/CommitLGWR 異步寫入用戶進程批量寫入 Log File(需 Copy Latch 一次)
釋放釋放 Allocation + Copy Latch釋放 Private Strand Allocation Latch

關鍵限制

  • 事務一旦回退到 Shared Strand,**全程不再嘗試**獲取 Private Strand。
  • Private Strand 數量受雙重約束:
    1. 日志文件大小:_log_private_mul(默認 5%)× 當前日志文件大小 / 65KB。
    2. 活躍事務數:_log_private_parallelism_mul(默認 10%)× TRANSACTIONS 參數值。
    取兩者較小值。Shared Pool 內存按活躍事務數預分配,實際使用取較小值。

監控 SQL

-- 查看 Private Strand 使用情況
SELECT DECODE(BITAND(KTCXBFLG,4096),0,1,0) USED_PRIVATE_STRAND, COUNT(*)
FROM X$KTCXB WHERE BITAND(KSSPAFLG,1)!=0 AND BITAND(KTCXBFLG,2)!=0
GROUP BY BITAND(KTCXBFLG,4096);

-- 計算理論 Private Strand 數(10g)
SELECT TRUNC(VALUE * KSPPSTVL / 100) * 65 * 1024
FROM (SELECT VALUE FROM V$PARAMETER WHERE NAME='TRANSACTIONS') A,
     (SELECT VAL.KSPPSTVL FROM SYS.X$KSPIM VAL WHERE VAL.KSPPINM='_LOG_PRIVATE_PARALLELISM_MUL') B;

-- 實際分配數
SELECT COUNT(1) FROM X$KCRFSTRAND WHERE LAST_BUF_KCRFA = '00';

日志切換時的 Private Strand 重算

切換前必須 Flush 所有 Private Strand 到日志文件(Alert Log 可能出現 "Private strand flush not complete",可忽略)。切換後根據新日志文件大小重新計算上限,動態調整。

最佳實踐總結

  1. 確保日志文件足夠大(建議單組 ≥ 1GB,切換間隔 15-30min)。
  2. _log_private_parallelism_mul 根據實際活躍事務佔比微調(默認 10% 通常合理)。
  3. 監控 redo allocation latch / 等待,若持續存在,檢查 Private Strand 分配是否受限於日志文件大小。
  4. 11g+ 環境優先依賴自動管理,僅在極端併發場景人工干預隱含參數。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved