簡體   English   中英

從連接池中驅逐到群集中只讀節點的連接

[英]Evicting connections to a read-only node in a cluster from the connection pool

我的應用程序連接到兩個MySQL 5.6(實際上是Amazon Aurora )實例的故障轉移群集。 活動節點始終可寫入,而被動節點以read_only模式運行(這與規范的MySQL故障轉移群集不同,默認情況下,所有從屬節點都可寫入。 Amazon RDS提供符號DNS名稱,該名稱始終指向活動MySQL節點的IP地址。

在故障轉移過程中,前一個主設備以read_only模式重新啟動,而前一個被動節點變為可寫入,並被提升為主設備。 此外,DNS記錄也會更改,因此群集的DNS名稱現在指向新的主節點。

即使我完全禁用Java端的DNS緩存(通過sun.net.inetaddr.ttlnetworkaddress.cache.ttl ),特定於操作系統的DNS緩存仍然有效,因此在數據庫故障轉移后我最終得到了我的DBCP池充滿了與只讀MySQL實例的連接。 這些連接是valid ,即它們是故障轉移完成之后但 DNS緩存過期之前獲得的。 另外,這些連接都沒有設置readOnly標志,所以我無法判斷我是否正在與一個只讀實例進行通信,直到我執行一些DML,這就是當ER_OPTION_PREVENTS_STATEMENT榮耀時。 即使我通過調用setReadOnly(false)顯式地將連接置於讀寫模式並設置readOnlyPropagatesToServer標志,這只會導致驅動程序向服務器發送SET SESSION TRANSACTION READ WRITE ,這不會導致拋出任何異常。

我希望盡可能少地影響應用程序邏輯來解決這個問題。 如果有一種方法可以將只讀實例的連接視為無效/封閉連接(即從池中驅逐它),則可以實現這一點。

我可以使用一個驗證查詢,例如SHOW GLOBAL VARIABLES LIKE 'read_only' ,並附加一個額外的邏輯嗎? 是否可以根據驗證查詢返回的標量值來影響池的行為?

可以使用以下驗證查詢:

select case when @@read_only = 0 then 1 else (select table_name from information_schema.tables) end as `1`

如果數據庫以只讀模式運行,則查詢將失敗

ERROR 1242 (21000): Subquery returns more than 1 row

由於Amazon Aurora在集群中的讀取器端點上設置innodb_read_only但不設置read_only ,因此驗證查詢可以重寫為

select case when @@read_only + @@innodb_read_only = 0 then 1 else (select table_name from information_schema.tables) end as `1`

靈感來自這個答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM