Oracle 的Lgwr Worker的工作原理

roc_guo發表於2022-09-18
導讀 實際上我看到一些國產資料庫現在也在考慮使用多個WAL WRITER提升高併發WAL寫入的效能,從而更為充分的利用SSD等現代硬體。不過WAL寫入對於延時十分敏感,演算法寫不好,就容易引發更為嚴重的閂鎖序列問題。

這些年Oracle發展的太快,我從12C之後就比較少參與運維工作,頂多幫著客戶看看AWR報告,所以多Oracle 12C以後的很多細節實際上了解不多。搞了二十多年Oracle,從5.1用到11.2,Oracle 10G出來的時候,我就說這應該是我學習的最後一個版本的Oracle了。沒想到沒摟住,11G又搞了10年。12C後因為不怎麼做一線運維了,所以就沒怎麼關注了。

前幾天群裡朋友在討論PG WAL寫入存在效能問題的時候。群裡有個朋友就問,難道PG這麼土,不支援多個WALWRITER併發寫嗎?我當時想都沒想就說,Oracle也不支援啊,早期Oracle支援過LGWR SLAVER,不過因為BUG太多,沒什麼人用,到12C以後,好像就沒有SLAVER這碼子事兒了。當時那個朋友就蒙圈了,Oracle咋能不支援多個LGWR併發寫呢?事後我問了問同事,他們說好像你記錯了,12C之後Oracle所有的SLAVER都被統一改成WORKER了。在12C裡LGWR worker是自動開啟的。

Oracle 的Lgwr Worker的工作原理Oracle 的Lgwr Worker的工作原理

昨天正好有點空,我找了一些關於12C LGWR worker的資料看了看。在公司的測試環境上也找了一套19.15的環境檢查了一下。發現還真如同事所說,12C開始,Oracle已經自動開啟LGWR併發寫了。在12C裡增加了LGnn程式,用於實際寫入REDO資料,LGWR完全不管寫Redo Log檔案的事情,只負責釋出一些和REDO落盤的訊息了。

目前我看的關於LGWR worker的資料不多,從一些資料和我對LGWR的理解,LGWR worker應該是和Oracle Redo Strand有關的。Oracle的LGWR worker都是分配到GROUP的,GROUP的數量如果是和Redo public Strand相關,那麼每個group就之間就不需要透過鎖機制來同步寫入工作。LGWR 也不需要在多個worker之間做協同,而僅僅需要做和訊息公告相關的共組了,這種機制應該是最為高效的。如果多個worker之間寫REDO檔案還需要閂鎖來做序列化,那麼效率肯定是不會好的。

Redo Strand從Oracle 11開始就已經被用來加速REDO效能了,Strand的目的是為了提高併發寫入Redo Log buffer和Redo Log檔案時候的效能,減少因為序列化閂鎖等待導致的REDO效能問題。Oracle會根據CPU_COUNT的值,自動的調整Redo srand的數量。

Oracle 的Lgwr Worker的工作原理Oracle 的Lgwr Worker的工作原理

Oracle會根據CPU_COUNT/16來設定Strand的數量,在LOG BUFFER中會按照Strand數量劃分為N個子池,寫入REDO資料的時候,可以併發的寫入不同的STRAND,這樣可以減少高併發LOG BUFFER寫入的效能。為了確保這一機制起作用,在Redo Log檔案中,也是按照Strand的方式分配Redo Log檔案,這種模式可以讓Redo Log檔案的寫入也可以高速併發。Redo Strand為12C的LGWR worker稱為預設開啟的功能打下了一個良好的基礎。

Oracle 的Lgwr Worker的工作原理Oracle 的Lgwr Worker的工作原理

我這個環境的CPU_COUNT是16,而每個例項的Redo Strand最小值是2,因此啟動例項的時候也啟動了2個LGWR worker,這說明資料庫例項有兩個LGWR worker group,當系統空閒,沒有什麼需要寫入的REDO資料的時候,LGnn都在等待空閒等待事件LGWR worker group idle,而lgwr程式在等待rdbms ipc message。

Oracle 的Lgwr Worker的工作原理Oracle 的Lgwr Worker的工作原理

透過strace看lgwr,也只是在做一些訊號量方面的操作。我們再來看看空閒時的LGnn。

Oracle 的Lgwr Worker的工作原理Oracle 的Lgwr Worker的工作原理

也是在相同的訊號量上休眠。

Oracle 的Lgwr Worker的工作原理Oracle 的Lgwr Worker的工作原理

可以看出LGWR的等待事件發生了變化,而LGnn的等待事件也和以前的LGWR十分類似。從等待事件上看,當一個worker完成工作後,會處於Ordering等待,等待獲取另外的寫任務。在具體實現演算法上,還並沒有和我想象的一樣不需要排程。我們再來TRACE一下LGWR。

Oracle 的Lgwr Worker的工作原理Oracle 的Lgwr Worker的工作原理

可以看出LGWR還是十分頻繁的在操作那個訊號量,這很可能是LGWR在積極參與日誌寫的排程協調。

Oracle 的Lgwr Worker的工作原理Oracle 的Lgwr Worker的工作原理

從worker的行為上也看到了和LGWR之間的互動。這說明Oracle併發日誌寫還是需要多程式之間的同步行為,不是完全自主的無阻塞的。因此在某些場景下,可能會導致當WORKER數量過多時,引發Log file parallel write的等待時間過長,從而引起LOG FILE SYNC的增加,影響資料庫的效能。

當年Oracle的REDO STRAND成為預設開啟的時候,也出現過類似的問題,因為STRANDS數量時和CPU_COUNT相關的。十多年前在Oracle 11g上就有人發現了當CPU數量很多的時候,log file sync會莫名其妙的變壞。

Oracle 的Lgwr Worker的工作原理Oracle 的Lgwr Worker的工作原理

當時的建議時透過_log_parallelism_max引數來減少Strand的數量,解決過多的Strand帶來的效能問題。對於LGWR worker機制,Oracle也提供了一個類似的引數來進行控制,這個引數就是“_max_log_write_parallelism”。

在Oracle 12C或者以後版本中,也經常會出現因為LGWR worker導致的效能問題。Oracle可以透過“_use_single_log_writer”引數來進行調整。預設情況下這個引數的值時ADAPTIVE,這意味著Oracle會自己根據工作負載來選擇工作模式。如果遇到這方面的效能問題的時候,可以將這個引數設定為TRUE,強制使用單個LGWR,也就是恢復以前的工作模式。如果你發現你的資料庫從11G升級到12C之後,log file sync變壞了,從而導致了一些效能問題,你可以考慮調整這個引數。

資料庫的應用場景十分複雜,我們享受某些應用場景受益於一個新技術的時候,難免會引發一些新的問題,某些場景可能和新技術的適應性不夠好。另外加上一些新技術剛剛開始使用時,對某些特殊場景的演算法不夠最佳化,也會引發一些問題。我想,隨著今後Oracle資料庫版本的迭代,LGWR worker的機制也會越來越成熟。

實際上我看到一些國產資料庫現在也在考慮使用多個WAL WRITER提升高併發WAL寫入的效能,從而更為充分的利用SSD等現代硬體。不過WAL寫入對於延時十分敏感,演算法寫不好,就容易引發更為嚴重的閂鎖序列問題。Oracle的Redo Strand與LGWR worker相結合的機制應該是目前最值得借鑑的方法了。如果不針對WAL BUFFER做Strand分割槽,那麼多個WAL WRITER的併發控制的成本會更高。

原文來自:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2915154/,如需轉載,請註明出處,否則將追究法律責任。

相關文章