App下載

在PostgreSQL如何實現同步提交選項和同步備用復制?PostgreSQL實現同步提交選項和復制方法!

倒影年華 2021-09-18 20:00:58 瀏覽數 (3402)
反饋

我發(fā)現自己在與許多 PostgreSQL 用戶,尤其是新手用戶討論和解釋sychronous_commit。所以,我想把所有的關鍵點記下來作為一篇博文,這對更多的用戶會有用。最近我有機會在我們的 PostgreSQL Percona Tech Days 中談論一些相關主題。

sychronous_commit 是什么?

這是我們可以決定何時可以向客戶端確認事務提交成功的參數。

因此,此參數不僅與同步備用有關,而且具有更廣泛的含義和含義,這對于獨立的 PostgreSQL 實例也很有用。為了更好地理解,我們應該查看整個 WAL 記錄傳播以及可以接受提交確認的各個階段。這使我們可以為每個事務選擇不同級別的持久性。持久性選擇越少,確認越快,從而提高系統(tǒng)的整體吞吐量和性能。

WAL 傳播

PostgreSQL WAL(Write Ahead Log)是主端更改/活動的記錄,可以被視為數據庫中發(fā)生的更改的日志/分類帳。下圖展示了本地主PostgreSQL實例和遠程熱備實例中WAL傳播的流程。

PostgreSQL 使用內部函數 pg_pwrite() 寫入 WAL 段,該函數內部使用write()系統(tǒng)調用,該系統(tǒng)調用不保證將數據刷新到磁盤。為了完成刷新,另一個函數 issue_xlog_fsync() 被調用,它根據參數 (GUC) 發(fā)出適當類型的 fsync:wal_sync_method

上圖顯示了所有 5 個主要階段。

  1. WAL 記錄插入(本地):WAL 記錄首先在 WAL 緩沖區(qū)中創(chuàng)建。由于多個后端進程將同時創(chuàng)建 WAL 記錄,因此它受到鎖的適當保護。wal_buffers 中 WAL 記錄的寫入被不同的后臺進程連續(xù)寫入 WAL 段。如果 sychronous_commit 完全關閉,刷新將不會立即發(fā)生,而是依賴于 wal_writer_delay 設置,我們將在下一節(jié)中討論。
  2. WAL 寫入和 WAL 刷新(本地):這種刷新到本地磁盤上的 WAL“段文件”被認為是繁重的操作之一。PostgreSQL 在這方面做了很多優(yōu)化,以避免頻繁的flush。
  3. 遠程寫入:  WAL 記錄寫入遠程備用數據庫(但尚未刷新)。數據可能會在頁面緩存中保留一段時間。除非我們想解決 Primary 和 Standby 實例同時崩潰的情況,否則可以考慮這種級別的持久性保護。
  4. Remote Flush:在這個階段,數據真正在遠程備端寫入并刷新到磁盤。所以我們可以保證數據在備用端可用,即使它也會崩潰。
  5. 遠程應用:在此階段,WAL 記錄在遠程/備用端重放,可供在那里運行的會話使用。

synchronous_commit 對應的接受值如下:

  1. off: 您可以使用值 off、0(零)、false 或 no 來關閉 synchronous_commit。顧名思義,提交確認可以在將記錄刷新到磁盤之前出現。這通常稱為異步提交。如果 PostgreSQL 實例崩潰,最后幾次異步提交可能會丟失。
  2. 本地:  WAL 記錄被寫入并刷新到本地磁盤。在這種情況下,將在本地 WAL 寫入和 WAL 刷新完成后確認提交。
  3. remote_write:  WAL 記錄成功地移交給遠程實例,該實例確認了寫入(不刷新)。
  4. on:這是默認值,您可以使用 on、true、yes 或 1 將值設置為“on”。但是含義可能會根據您是否有同步待機而改變。如果有同步待機,將值設置為 on 將導致等待直到“遠程刷新”。
  5. remote_apply: 這將導致提交等待,直到來自當前同步備用數據庫的回復表明他們已收到事務的提交記錄并應用它,以便它對備用數據庫上的查詢可見。

通過為參數選擇適當的值,我們可以選擇確認何時返回。如果沒有同步備用( synchronous_standby_names 為空), synchronous_commit 到 on、remote_apply、remote_write 和 local 的設置都提供相同的同步級別:事務提交只等待本地刷新到磁盤。

該領域的常見問題之一是:

“如果我們選擇完全異步提交(synchronous_commit = off),我們會丟失多少數據?”

答案有點復雜,它取決于 wal_writer_delay 設置。默認為 200 毫秒。這意味著WAL 將在每個wal_writer_delay 中 刷新到磁盤。WAL 編寫器會定期喚醒并調用 XLogBackgroundFlush()。這會檢查完全填充的 WAL 頁面。如果它們可用,它會寫入到該點的所有緩沖區(qū)。所以在良好的負載條件下,WAL 寫入器寫入整個緩沖區(qū)。在找不到完整頁面的低負載情況下,將刷新上次異步提交之前的所有內容。

如果超過 wal_writer_delay 已經過去,或者自上次刷新以來已經寫入了超過 wal_writer_flush_after 塊,則 WAL 被刷新到當前位置。這種安排保證異步提交記錄在事務完成后最多兩次 wal_writer_delay 后到達磁盤。但是,PostgreSQL 以靈活的方式寫入/刷新完整緩沖區(qū),這是為了減少每個 WAL 寫入器周期填充多個 WAL 頁時在高負載下發(fā)出的寫入次數。從概念上講,這會使最壞情況的延遲達到三個wal_writer_delay 周期。

所以答案很簡單,就是:

在大多數情況下,損失將小于 wal_writer_delay 的兩倍。但在最壞的情況下,它可能高達三倍。

設置范圍

當我們討論參數及其值時,許多用戶會考慮在實例級別進行全局設置。但是,真正的力量和用法是在不同級別適當地確定范圍時才出現的。在實例級別更改它是不可取的。

除了各種值之外,PostgreSQL 還允許我們在不同范圍內進行此設置。

在每個事務級別在完美調整的應用程序設計中,特定事務可以為每個事務選擇特定的 sychronous_commit 級別,例如:

SQL:

SET LOCAL synchronous_commit = 'remote_write';

請注意“本地”規(guī)范。一旦事務塊完成(提交或回滾),設置將恢復到適用于會話級別的設置。這允許架構師選擇加入特定關鍵事務的額外開銷。

在會話級別可以在每個會話級別指定設置,以便它適用于整個會話,除非被上述事務級別設置覆蓋。

SQL:

SET synchronous_commit = 'remote_write';

此外,您可能會選擇將此作為應用程序連接中的連接字符串選項的一部分傳遞給 PostgreSQL。例如: "host=hostname user=postgres ... options='-c synchronous_commit=off'" 。因此可以減少任何代碼修改的要求。

在用戶級別在一個理想的系統(tǒng)中,擁有良好管理的用戶帳戶,每個用戶帳戶都將處理特定的功能。它的范圍可以從關鍵交易系統(tǒng)到報告用戶帳戶。例如:

SQL:

ALTER USER trans_user SET synchronous_commit= ON;
ALTER USER report_user SET synchronous_commit=OFF;

默認情況下,這些用戶創(chuàng)建的會話將具有這些設置??梢栽跁捈墑e或事務級別覆蓋此用戶級別設置。

在數據庫級別當我們有專門的系統(tǒng)用于報告或臨時登臺信息時,在數據庫級別指定非常有用。

SQL:

ALTER DATABASE reporting SET synchronous_commit=OFF;

在實例級別這是在 PostgreSQL 實例級別,如下所示:

SQL:

ALTER SYSTEM SET synchronous_commit=OFF;
SHOW synchronous_commit;

常見用例

遷移:當發(fā)生遷移時,跨系統(tǒng)移動大量數據是很常見的,正確選擇 synchronous_commit 甚至關閉它對于減少整體遷移時間具有重要價值。

數據加載:在數據倉庫系統(tǒng)/報告系統(tǒng)中,可能會發(fā)生大量數據加載,關閉 synchronous_commit 將通過減少重復刷新的開銷來大幅提升。

審計和日志記錄:即使在具有關鍵事務的關鍵系統(tǒng)中,在確認提交之前,在備用端上也只有事務的特定部分可能是非常關鍵的——這是企業(yè)希望可用的。但是會有關聯的日志和審計信息記錄。非常有選擇性地選擇同步備用提交可以產生非常高的好處。

最后一點

使用 pgbench 的快速測試可以幫助驗證特定環(huán)境中不同級別的提交同步的開銷。總體而言,隨著同步要求級別的提高,我們應該預期性能會下降。fsync 到本地磁盤的延遲、網絡延遲、備用服務器上的負載、備用服務器上的爭用、整體復制量、備用服務器上的磁盤性能等環(huán)境因素都會影響開銷和性能。

與 fsync 不同,即使完全關閉 synchronous_commit 也不會導致數據庫損壞。了解整體 WAL 傳播可以幫助您從pg_stat_replication視圖了解復制延遲和信息。

系統(tǒng)的性能就是在不犧牲真正重要的東西的情況下消除不需要的、可避免的開銷。我見過一些 PostgreSQL 的超級用戶,他們通過非常有效和有選擇地使用 synchronous_commit 功能,為PostgreSQL 數據庫提供了一個經過良好調優(yōu)的系統(tǒng)。我希望這篇文章能幫助那些仍然沒有使用它并正在尋找更高性能或耐用性的微調機會的人


SQL

0 人點贊