用戶進程 PGA 生成 Redo Entry → 獲取 Redo Copy Latch**(多個,CPU_COUNT*2) → 獲取 **Redo Allocation Latch**(單一) → 分配 Log Buffer 空間 → 釋放 Allocation Latch → 拷貝 Redo Entry → 釋放 Copy Latch。高併發 OLTP 下,單一 Allocation Latch 成為嚴重熱點。
將 Log Buffer 劃分為多個 Strand(共享絞),每個 Strand 獨立受一個 Redo Allocation Latch 保護。分配並行化,Latch 爭用指數級下降。
| 參數 | 含義 | 備註 |
|---|---|---|
_log_parallelism | 初始 Strand 數 | 10g 起隱含 |
_log_parallelism_max | 最大 Strand 數 | 不超過 CPU_COUNT |
_log_parallelism_dynamic | 是否動態調整 | 默認 TRUE |
SELECT INDX, STRAND_SIZE_KCRFA FROM X$KCRFSTRAND WHERE LAST_BUF_KCRFA != '00';
-- 共享 Strand 信息
SHOW PARAMETER LOG_BUFFER;
-- 每 Strand 大小 = LOG_BUFFER / 共享 Strand 數
redo allocation latch 等待時,每增加 16 CPU 考慮 +1 Strand,上限 8。_log_parallelism,由 _log_parallelism_max、_log_parallelism_dynamic、CPU_COUNT 共同決定。| 階段 | 傳統/Shared Strand | Private Strand |
|---|---|---|
| 事務開始 | 獲取 Allocation Latch | 獲取 Private Strand Allocation Latch(失敗回退 Shared) |
| Redo 生成 | PGA → Log Buffer(需 Copy Latch) | 直接在 Private Strand 生成(無 Copy Latch) |
| Flush/Commit | LGWR 異步寫入 | 用戶進程批量寫入 Log File(需 Copy Latch 一次) |
| 釋放 | 釋放 Allocation + Copy Latch | 釋放 Private Strand Allocation Latch |
_log_private_mul(默認 5%)× 當前日志文件大小 / 65KB。_log_private_parallelism_mul(默認 10%)× TRANSACTIONS 參數值。-- 查看 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';
切換前必須 Flush 所有 Private Strand 到日志文件(Alert Log 可能出現 "Private strand flush not complete",可忽略)。切換後根據新日志文件大小重新計算上限,動態調整。
_log_private_parallelism_mul 根據實際活躍事務佔比微調(默認 10% 通常合理)。redo allocation latch /