在站點冗餘的 galera 集群上禁用 sync_binlogs、innodb_flush_log_at_trx_commit 和 innodb_doublewrite 是否安全?
在站點冗餘的 galera 集群上,只有在法定數量的數據庫節點接受了事務後,才能返回送出。如果一個數據庫節點宕機,所有的送出將被集群的其餘部分保留,並且宕機的數據庫節點將在再次啟動數據庫時與集群的其餘部分保持同步。如果數據庫應該已經損壞,可以隨時核對 mysql 數據目錄並從一個空數據庫開始,它最終會趕上集群的其餘部分。因此,聽起來我們可以通過關閉確保本地 ACID 合規性的選項來調整性能。
所以這裡的問題真的是……“可能會出什麼問題?”
:-)
根據評論,我將提供有關我們特定設置的一些資訊:
- 集群由三個節點組成。其中兩個在生產中被積極使用,其中一個比另一個使用得更頻繁。第三個節點僅用於仲裁和備份目的。
- 站點冗餘意味著節點位於不同的伺服器中心。我發現很難想到會導致兩個節點同時關閉的任何事情——除了一個嚴重的 mysql 錯誤,這有多大可能?誠然,其中兩個節點相距不到 10 公里(備份/仲裁節點相隔數百公里,外加國界)。一枚中型核彈可能會同時摧毀兩個節點……再說一次,在這種情況下,“我們的數據庫有問題”可能是我們最不關心的問題。太陽風暴可能同時摧毀兩個或所有伺服器嗎?
- 我們的性能問題是主要的,因為我們的 SAN 上的寫入記憶體有時會滿。我們正在努力緩解這個問題,但我們不能保證它不會再次發生。我們時不時地會遇到“打嗝”,我們的交易等待大約 10-30 秒。
- 在這個特定的設置中,30 秒的延遲實際上可能是生死攸關的問題。好吧,很可能不是,但如果客戶這樣認為,那就夠糟糕了。如果整個集群出現故障,合理的低延遲和快速恢復是最緊迫的優先事項。失去一些交易可能已經夠糟糕了,但這不是生死攸關的問題。
- 我們看到的性能問題是寫入事務卡在“wsrep in pre-commit”狀態。這不是流量控制問題,只是一個節點有問題。我對它進行了一些研究,顯然是所有本地寫入查詢都在等待鎖定,而節點正在將遠端變更集寫入數據庫。這個問題應該在 galera 4 中修復,但升級目前不是一個選項。
- 我們的性能問題只在一個節點上,所以它只在一個節點上我正在考慮關閉那些東西。我會在我們的文件中添加無論發生什麼,所說的節點都不應該用於引導集群。
- 我們不做分片,也不打算做任何分片。除了那些打嗝,我們沒有任何性能問題。
我現在已經對此進行了一些研究,所以我將回答我自己的問題。
先總結
如果僅在一個節點上觀察到性能問題,關閉受影響節點上的 innodb_doublewrite 和 innodb_flush_log_at_trx_commit是完全安全的——只要記住在整個集群出現故障時使用其他節點之一進行引導。
# echo "[server]" >> /etc/mysql/conf.d/temp_perfomance_hax.cnf # echo "innodb_doublewrite = 0" >> /etc/mysql/conf.d/temp_performance_hax.cnf # echo "innodb_flush_log_at_trx_commit = 2" >> /etc/mysql/conf.d/temp_performance_hax.cnf # systemctl restart mysql # innodb_doublewrite cannot be set run-time
此外,在真正的站點冗餘 galera 集群中,在任意數量的節點上將 innodb_flush_log_at_trx_commit 設置為 2 並將 sync_binlog 設置為 0應該是*相當安全的。*如果遇到性能問題,如果正常執行時間和性能很重要,並且如果失去的交易可能不是生死攸關的問題 - 那麼無需猶豫,繼續做吧。
set global sync_binlog = '0'; set global innodb_flush_log_at_trx_commit = 2;
如果性能比 ACID 合規性更重要,人們也可以繼續關閉雙重寫入。發生災難的可能性非常低。
我可以看到堅持“安全”設置的兩個原因:
- 為最壞的情況做好準備:如果整個集群同時崩潰怎麼辦?
- 節點更健壯
節點健壯性:保持 innodb_doublewrite 開啟
innodb_doublewrite 可以在一個節點上安全地關閉而不會失去對 ACID 的兼容性,但打開它可能仍然更好。根據何時禁用 InnoDB 雙寫緩衝是安全的?關閉 innodb-doublewrite 可能會導致數據損壞,在這種情況下,可能需要擦除已關閉節點上的數據分區並重新啟動它。這帶來了三個成本:
- 手動系統管理員干預
- 當損壞的節點正在執行 SST 時,集群上的 IO 級別升高
- 集群必須以減少的冗餘執行,直到節點再次完全執行。
(據我所知,日誌文件失去刷新不應該導致啟動數據庫節點的問題 - 即對於 innodb_flush_log_at_trx_commit 手冊明確指出“InnoDB 的崩潰恢復工作不管值”)
整個集群可能一次燒毀的原因
硬爆炸
考慮將 innodb_flush_log_at_trx_commit 設置為 2,將 binlog_sync 設置為 0,將 innodb-doublewrite-buffering 設置為 1,這可能會提高性能,據我所知,它不會涵蓋的唯一故障模式是仲裁的節點正在遭受斷電或核心恐慌。對於真正的多站點設置,這些似乎非常罕見,以至於人們可能想要忽略它們。
- 如果節點位於附近,則本地問題,即停電、洪水、火災等可能會同時將所有節點擊倒。我多次目睹整個伺服器站點由於最奇怪的原因而崩潰,即使一切都應該是多餘的。
- 太陽風暴會同時影響整個星團嗎?特別是如果集群位於同一個城市和極地地區?我已經看到兩台筆記型電腦同時崩潰,在太陽風暴期間位於極地地區,並且沒有其他合理的原因(不同的作業系統,它不是閏秒等)。
- 如果所有節點都執行相同的作業系統,則某些作業系統核心問題可能會導致所有節點在完全相同的時間因核心崩潰而嚴重崩潰。
軟體崩潰
我相信如果 innodb_flush_log_at_trx_commit 設置為 0 或 innodb_flush_log_at_trx_commit 設置為 0,那麼同時影響所有節點的 mysql 崩潰可能會導致數據失去。
有沒有人觀察到 galera 以這種方式崩潰?
系統管理員或錯誤腳本也在所有節點上同時在 mysql 上執行“kill -9”……但是如果系統管理員想要導致數據失去,他可能會找到一種方法,而不管這些設置如何。
集群因其他原因而關閉
在這些情況下,這些設置無關緊要:
- 所有三個節點之間突然和完全的網路隔離,或者使集群碎片化,因此無法找到仲裁。發生此類事件後需要引導集群,如果真的想 100% 確定沒有事務失去,則需要手動調查二進制日誌(請參閱下面的更多內容) - 但由於 mysql 和作業系統都沒有崩潰,無論同步設置如何,最終都會同步所有狀態。
- 糟糕的時機 - 即一個節點宕機,而當它宕機時,另一個節點可能宕機,或者可能存在一些網路隔離。之後,需要引導集群。但是,節點收到的所有內容都將寫入磁碟,因此上述設置不會影響任何內容。(我們曾經遇到過這種情況)。
集群故障需要人工干預
無論設置如何,為了 100% 確保在災難性集群故障後不會失去任何事務,實際上需要手動檢查/合併 binlog。我們只需要使用一個節點來引導集群,但我們不知道這個節點是否獲得了所有的變更集,這個資訊只能通過調查所有節點的 binlogs 獲得(
log_slave_updates
打開後,可能可以使用來自一個節點的 binlogs節點的法定人數)。這意味著您需要提前做出決定——如果我們遇到災難性的集群崩潰,應該優先考慮什麼?是讓集群盡快啟動並再次執行的優先級,還是在引導集群之前 100% 確保沒有事務失去?
你的旅費可能會改變
如果在極端情況下某些停機時間是可以接受的(完全災難性的數據庫集群崩潰是極端的),並且如果在返回生產模式之前確保所有事務都到位至關重要,那麼需要 100% 確保二進制日誌已同步並保留,並且備份機制很好。同步 innodb 日誌和雙重寫入是非關鍵的,如果這能帶來性能優勢,可以將其關閉。
如果“讓集群盡快啟動並再次執行”很重要,那麼
set innodb_flush_log_at_trx_commit = 1
對set innodb_doublewrite = 1
節點的法定人數也很重要;如果集群應該關閉,那麼它可以從任何打開了這些設置的伺服器快速引導。(可能需要考慮一下。在我們之前的崩潰中,節點 C 跌倒並再次站起來。在節點 C 正確加入集群之前,節點 A 和節點 B 之間的網路故障,導致關閉。顯然,我們可以從 A 引導或 B 沒有任何數據失去,但不是來自 C)。