首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL Proxy 讀寫分離實戰部署:Lua 腳本修正預設 DB 同步 Bug 與生產級高可用架構

     編輯:MySQL 資料庫相關知識

架構圖解


應用層 (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-addressesMaster IP:3306寫入節點,單點寫入保證一致性
--proxy-read-only-backend-addressesSlave IP:3306讀取節點,Proxy 內建輪詢負載均衡
--proxy-lua-scriptrw-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、原生叢集同步,生產就緒度高得多。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved