連接池概述
數據庫代理支持兩種連接池:事務級連接池和會話級連接池。默認使用事務級連接池。兩種連接池都能降低業務與數據庫建立連接的頻率,從而減少數據庫建立連接帶來的開銷。
兩者的區別在于連接復用的程度。數據庫代理中連接分為前端連接和后端連接,前端連接時業務應用到數據庫代理的連接。后端連接是指數據庫代理到數據庫實例的連接,這里連接池是特指后端連接的連接池。
當客戶端發起連接會話請求時,只會與數據庫代理建立前端連接,代理不會馬上將其與后端數據庫建立連接。當真正提交業務請求時,才會從連接池中查找可用的后端連接或者創建后端連接。
事務級連接池
應用場景
- 業務多為短連接,連接建立頻繁;
- 連接數量很大。
工作原理
選擇事務級連接池,當需要處理一個業務事務時,從連接池中查找是否存在可用的連接。如果存在則占用該空閑連接,否則代理與后端數據庫創建一個新的后端連接。
在當前事務結束后將該連接放回連接池中。這樣連接會被下一個事務使用,這個事務可能是當前業務會話,也可能是其他業務會話。
如上圖所示:有事務的會話占用后端連接,沒有事務的會話不占用連接,一個連接被多個會話輪流共用。因此它能顯著減少后端數據的連接數量和連接頻率,避免了空閑連接帶來的資源浪費,特別適用于大量短連接的業務應用。
特別注意,事務級連接會在一些特殊的使用場景會轉換為會話級連接:
- 執行鎖操作LOCK TABLE, LOCK TABLES 或者FLUSH TABLES WITH READ LOCK;
- 執行了PREPARE 語句;
- 使用了TEMPORARY TABLE;
- 設置了SQL_LOG_BIN=0;
- 使用sql_safe_updates ,sql_select_limit ,max_join_size 等safe-updates設置;
- 使用了SQL_CALC_FOUND_ROWS 功能;
- 設置了FOREIGN_KEY_CHECKS ,UNIQUE_CHECKS,AUTO_INCREMENT_INCREMENT AUTO_INCREMENT_OFFSET ,GROUP_CONCAT_MAX_LEN 等等;
- SQL語句中包含了@ 字符。
會話級連接池
應用場景
- 業務多為長連接,連接建立不頻繁
- 連接數量不是很大
工作原理
選擇會話級連接池后,當需要處理第一個會話事務時,從連接池中查找是否存在未綁定的空閑連接。如果存在則綁定空閑連接,否則代理與后端數據庫創建一個新的后端連接。
在當前事務結束后將仍然被會話占用,直到會話結束才會釋放回線程池。此時才能被下一個會話復用。
如上圖所示: 一個會話獨占了專用后端連接,后端連接數量與會話并發數是正相關的,無論會話活躍與否。它的好處是會話始終保持很好響應速度,請求更穩定,適用于長連接的業務場景。
需要注意:
- 代理默認開啟讀寫分離,讀寫事務連接到主實例,只讀事務會連接到只讀實例;
- 存在一個會話獨占多個后端連接(分別到主實例和只讀實例的連接);
- 業務需要評估應用特征是否為長連接,會話數量是否在可控范圍內,是否超過單單實例的連接限制。
事務拆分
數據庫代理提供了事務拆分的能力,開啟事務拆分后,同一個事務中的讀寫SQL請求進行了路由拆分,寫請求路由到主實例,讀請求路由到從實例。
工作原理
數據庫代理具備讀寫分離的能力,寫請求路由到主實例,讀請求路由到從實例。這樣能充分利用從實例的資源,減小主實例負載。
一般情況下,業務應用使用自動提交的模式,即每一個SQL都是單獨的事務。讀寫分離所起到的效果比較顯著。
但有些業務框架會關閉autocommit,業務讀寫SQL需要顯式commit,這樣同時包含讀寫SQL的事務請求都會路由到主實例上。
如上圖所示,包含讀寫SQL的事務,請求都路由到主實例上。如果業務存在大量讀寫事務,會導致主實例負載高而從實例負載低的情況。
為了應對這種情況,數據庫代理提供了事務拆分的選項,業務無需改造應用代碼,實現讀寫實例的負載均衡。開啟后事務中的讀寫SQL路由進行了拆分,寫請求路由到主實例,讀請求路由到從實例,保留了讀寫分離的效果。
如上圖所示,讀請求都路由到了從實例,寫請求路由到了主實例。這樣讀寫分離規則在事務內部中仍然起作用。
特別說明:
- 數據庫代理的事務拆分是默認關閉的;
- 一般情況下主從實例的延遲非常低,業務請求慢于主從同步,但仍然有一定概率讀不到剛提交的數據。如果業務需要非常強一致性的場景,不建議啟用事務拆分。