架構圖解
應用層 (App)
│
▼
MySQL Proxy (192.168.1.6:3306) ← 單一入口,應用零感知
│
├──► Master (192.168.1.225:3306) ← 寫入流量
│
└──► Slave (192.168.1.226:3306) ← 唯讀流量 (可多台輪詢)
預編譯包快速部署 (CentOS/RHEL)
# 1. 下載預編譯
wget https://dev.mysql.com/get/Downloads/MySQL-Proxy/mysql-proxy-0.8.5-linux-el7-x86-64bit.tar.gz
tar zxf mysql-proxy-0.8.5-linux-el7-x86-64bit.tar.gz
cd mysql-proxy-0.8.5-linux-el7-x86-64bit
# 2. 安裝
mkdir -p /usr/local/mysql-proxy/{bin,share}
cp bin/mysql-proxy /usr/local/mysql-proxy/bin/
cp -r share/mysql-proxy /usr/local/mysql-proxy/share/
strip /usr/local/mysql-proxy/bin/mysql-proxy # 去除符號表減小體積
啟動管理腳本
#!/bin/bash
# /etc/init.d/mysql-proxy
export LUA_PATH=/usr/local/mysql-proxy/share/mysql-proxy/?.lua
MODE=${1:-start}
case $MODE in
start)
/usr/local/mysql-proxy/bin/mysql-proxy --daemon \
--admin-address=:4401 \
--proxy-address=:3307 \
--proxy-backend-addresses=192.168.1.225:3306 \
--proxy-read-only-backend-addresses=192.168.1.226:3306 \
--proxy-lua-script=/usr/local/mysql-proxy/share/mysql-proxy/rw-splitting.lua
;;
stop)
killall mysql-proxy
;;
restart)
$0 stop && sleep 2 && $0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
關鍵參數對照
| 參數 | 值 | 說明 |
| --proxy-address | :3307 | 應用連線埠,模擬標準 3306 避免衝突 |
| --proxy-backend-addresses | Master IP:3306 | 寫入節點,單點寫入保證一致性 |
| --proxy-read-only-backend-addresses | Slave IP:3306 | 讀取節點,Proxy 內建輪詢負載均衡 |
| --proxy-lua-script | rw-splitting.lua | 官方內建讀寫分離腳本 |
| --admin-address | :4401 | 管理介面,可查連線池、後端狀態 |
核心 Bug 修正:DEFAULT DB 同步失敗 (ERROR 1105)
現象:應用執行 USE db_name 或連線指定 DB 後,Slave 回報 can't change DB to on slave xxx.xxx.xxx.xxx:3306。
原因:rw-splitting.lua 原始邏輯僅在 COM_INIT_DB 封包時同步 DB,但應用可能在連線建立時直接指定 DB (Handshake 階段),或透過 COM_CHANGE_USER 切換 DB,導致 Proxy 未正確轉發至 Slave。
修正:編輯 /usr/local/mysql-proxy/share/mysql-proxy/rw-splitting.lua,在 read_query 或 read_handshake 回調中加入:
-- 修正片段:確保預設 DB 同步到所有後端
if cmd.type ~= proxy.COM_INIT_DB and
c.default_db and c.default_db ~= s.default_db then
print(" server default db: " .. s.default_db)
print(" client default db: " .. c.default_db)
print(" synchronizing")
proxy.queries:prepend(2, string.char(proxy.COM_INIT_DB) .. c.default_db)
end
管理介面驗證
mysql -u root -h 127.0.0.1 -P 4401
# 內建資料表
SELECT * FROM proxy_connections; -- 當前連線狀態
SELECT * FROM proxy_config; -- 運行時配置
高可用架構:消除 Proxy 單點
方案 A:Keepalived + VIP 漂移
Proxy-1 (Master) ◄── VRRP ──► Proxy-2 (Backup)
應用連線 VIP (192.168.1.100:3307)
方案 B:應用層連線池多 Proxy 配置 (推薦)
HikariCP / Druid / DBCP 配置:
url: jdbc:mysql://proxy1:3307,proxy2:3307/db?loadBalanceConnectionGroup=...
方案 C:ProxySQL 叢集 (現代替代)
多 ProxySQL 節點共享配置 (etcd/Consul) + Keepalived VIP
內建讀寫分離、查詢規則、熔斷、監控指標
效能調優建議
- 連線池預熱:Proxy 啟動後預建連線至後端,減少首次請求延遲。
- Lua 快取:
LUA_PATH 指向本地複製的腳本,避免網路掛載延遲。
- 監控指標:
proxy_connections 連線數分佈、backend_ndx 輪詢均勻度、查詢延遲 P99。
- 壓測基準:sysbench
oltp_read_write 對比直連 Master/Slave 與經 Proxy,確保 Proxy 開銷 < 5%。
MySQL Proxy 0.8.x 為最後版本,官方已停止維護。新專案強烈建議直接採用 ProxySQL 2.x:多執行緒、熱加載配置、豐富查詢規則、Prometheus Exporter、原生叢集同步,生產就緒度高得多。