本文分享自華為雲社區《Proxy下的Prepare透傳,讓GaussDB(for MySQL)更穩固,性能更卓越》,作者: GaussDB 資料庫 。 1.引言 在很多業務場景下,資料庫應用程式處理大量相同的SQL語句——只需更改SQL語句中的文字或變數值。例如:使用相同的SQL模板進行WHERE查 ...
本文分享自華為雲社區《Proxy下的Prepare透傳,讓GaussDB(for MySQL)更穩固,性能更卓越》,作者: GaussDB 資料庫 。
1.引言
在很多業務場景下,資料庫應用程式處理大量相同的SQL語句——只需更改SQL語句中的文字或變數值。例如:使用相同的SQL模板進行WHERE查詢,SET 更新和VALUES 插入等操作。資料庫內部收到SQL語句後,需要對語句進行解析,即翻譯成機器可執行的語言,對大量相似的語句要做反覆的重覆翻譯。GaussDB(for MySQL)支持Prepare協議,來減少重覆翻譯的工作量。Prepare協議利用高效的客戶端/服務端二進位協議,在預處理語句中使用占位符代替參數值,使每個預處理語句只用解析一次,從而減少資料庫的開銷。
另外,由於程式員的水平及經驗參差不齊,相當大一部分程式員在編寫代碼的時候,並不會考慮SQL註入風險,使不法分子植入惡意SQL攻擊資料庫有了可乘之機。SQL註入通過將惡意的SQL查詢或更新語句插入到應用的輸入參數中,後臺資料庫做SQL解析時將遭受攻擊。由於Prepare協議在輸入參數之前已經完成了SQL的預編譯,因此將惡意的SQL當做參數插入時,資料庫不會重新編譯,因此可以防止SQL註入攻擊,具備更高的安全性。
綜上,Prepare協議可以帶來資料庫性能和穩固方面的雙重收益。
2.Prepare執行流程
Prepare協議分為兩個階段,第一階段是提交帶占位符的預編譯SQL,第二階段是傳輸數據,將占位符替換為數據進行執行。
Prepare協議應用代碼案例:
3.資料庫代理(Proxy)場景下的Prepare協議
在“高可用只讀,讓RDS for MySQL更穩定”一文中,我們曾提及了使用資料庫代理(Proxy)實現讀寫分離及高可靠的方案。GaussDB(for MySQL)同樣支持多Proxy,以實現讀寫分離,自動均衡負載及在只讀實例故障時自動路由至其他實例的高可靠和高性能方案。——GaussDB(for MySQL)同樣支持多Proxy,以實現讀寫分離,自動均衡負載及在只讀實例故障時自動路由至其他實例,具備高可靠和高性能能力。
資料庫代理是位於資料庫服務端和應用服務端之間的網路代理服務,其接收應用程式的連接,根據路由情況將SQL請求自動分發到GaussDB(for MySQL)節點上執行。資料庫代理(以下簡稱proxy)具有高可用、高性能、可運維、簡單易用等特點,提供自動讀寫分離、連接池、事務拆分、會話一致性等功能,詳細架構圖如下:
3.1 Proxy下的Prepare協議實現方案
未採用Proxy時,Prepare協議的兩階段(預編譯階段和執行階段)直接在資料庫節點上執行。Proxy加入後,由於資料庫代理會將同一個連接上的不同SQL分發到多個後端資料庫上,因此資料庫代理需要保存預編譯SQL和執行參數的對應關係,併在執行時,傳入至資料庫節點上執行。目前Proxy場景下的Prepare協議實現方案有兩種:
- 文本模式(誕生較早的模式)
- 透傳模式(現下流行的模式)
3.1.1 文本模式:
Proxy內部保存預編譯SQL的相關信息,將客戶端發送的二進位Prepare協議轉換為普通文本協議進行傳輸,即在Proxy側完成解析和替換,將解析和替換後的SQL發往後端資料庫,無需依賴資料庫進行解析轉換。
優勢:
- 實現簡單,任何SQL無條件封裝成文本SQL直接執行。
- 可以任意路由。
- 當資料庫代理和後端資料庫連接斷開時,客戶端無感知,自動相容容災場景。
劣勢:
- 需要解析類型結構,並拼裝原始SQL,對發過來的類型強依賴。例如:執行SELECT * FROM t1 LIMIT ?,當發送String類型數據時,會將其拼接成一個帶引號的String值:SELECT * FROM t1 LIMIT ‘10’, 資料庫不支持此種SQL語法導致執行報錯。
- 由於每條SQL都需要在資料庫代理側進行拼接,且拼接時,Proxy側需要根據數據類型處理SQL註入問題,代理側性能損耗嚴重,容易成為瓶頸。
3.1.2透傳模式
透傳模式下Proxy側只做預編譯階段的事情,執行階段將預編譯語句和參數數據直接發往後端資料庫。即Proxy側不執行解析和編譯。透傳模式有兩種實現方式:
廣播式透傳(多數資料庫廠商在用的模式)廣播式透傳是將客戶端發的預編譯語句發送到所有的後端資料庫節點,即所有後端資料庫節點在接收到參數後都可以解析、編譯和執行語句。故發送參數時,只需要任意選擇一個已發送預編譯語句的節點傳輸即可。
優勢:
- Proxy無需拼裝解析SQL。
- Proxy無需維護預編譯語句和後端資料庫節點之間的映射關係,只需要負責廣播和轉發,實現簡單。
劣勢:
- 所有資料庫節點承受了同等的壓力,同一條預編譯語句被多個資料庫節點執行,資源存在浪費,某個節點壓力大時,還會承受編譯語句的壓力。
- 當多個節點異常後恢復時,Proxy需要在所有恢復的資料庫節點上重新執行預編譯語句,才能保證參數和預編譯語句之間的對應關係,此時會導致代理的壓力過大。
單節點透傳是資料庫代理將預編譯語句根據路由發往資料庫其中一個節點,並維護預編譯語句和資料庫節點之間的映射關係,當執行參數數據時,根據映射關係將參數發往指定節點執行。
優勢:
- Proxy無需拼裝解析SQL。
- 不會導致後端資料庫資源浪費和整體壓力過大。
劣勢:
客戶端存儲的預編譯語句單點透傳到了某資料庫節點,在執行階段需要將客戶端輸入的參數路由到對應的節點, Proxy需要處理此關係,功能實現複雜,給GaussDB(for MySQL)團隊編碼帶來更大挑戰。
4.性能對比
我們對Proxy場景下GaussDB(for MySQL)在文本模式和透傳模式下的Prepare協議做了性能測試對比。測試顯示透傳模式下的性能優於文本模式,性能提升約28%。
執行測試的軟硬體規格說明如下表所示:
由於現下條件所限,雖然我們沒有測試廣播透傳模式與單點透傳模式間的性能對比,但是從前文的方案對比中不難預見,單點透傳模式具有更高的穩固性,因為其更不容易在Proxy側和資料庫節點側產生資源消耗,帶來瓶頸。
5.總結
GaussDB(for MySQL) Proxy下的Prepare協議將原本文本模式的處理方式優化為透傳模式,其性能得到很大提升,解決了文本模式中對數據類型強依賴的問題。目前業界多採用廣播模式的透傳,而GaussDB(for MySQL) Proxy側則將廣播模式優化為單點傳輸模式,降低了資料庫的整體性能損耗。