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

MySQL Proxy 實現讀寫分離:原理、部署、Lua 腳本機制與生產級替代方案

     編輯:MySQL 資料庫相關知識

前言

MySQL Proxy 是官方曾推出的基於 Lua 腳本的中間件,通過攔截 SQL 協議實現讀寫分離、負載均衡、SQL 審計、熔斷等功能。雖官方已停止維護 (GA 版停留在 0.8.x),但其**架構設計極具啟發性**,理解其原理有助於掌握現代中間件 (MyCat, ProxySQL, ShardingSphere-Proxy) 的核心邏輯。本文詳細還原部署流程、Lua 腳本機制、測試驗證及生產選型建議。

一、 架構原理

Client (App) 
    │
    ▼
MySQL Proxy (Listener Port 3307)
    ├── Lua Script Engine (rw-splitting.lua)
    │       ├── 決策邏輯: SELECT → 從庫 ; 非 SELECT / 事務 → 主庫
    │       ├── 連接池管理: 保持到後端的長連接
    │       └── 狀態檢測: 後端存活檢查
    │
    ├── Backend Master (192.168.100.104:3306)  -- 寫入
    └── Backend Slaves (192.168.100.210:3306, ...)  -- 讀取

二、 部署實戰 (CentOS 環境)

1. 依賴安裝

# Lua (Proxy 依賴)
yum install -y lua lua-devel
# 或源碼安裝指定版本
wget https://www.lua.org/ftp/lua-5.1.4.tar.gz
tar zxf lua-5.1.4.tar.gz && cd lua-5.1.4 && make linux test && make install

# MySQL Proxy (預編譯包)
wget https://downloads.mysql.com/archives/get/file/mysql-proxy-0.8.5-linux-glibc2.12-x86-64bit.tar.gz
tar zxf mysql-proxy-0.8.5-*.tar.gz
mv mysql-proxy-0.8.5 /usr/local/mysql-proxy
export PATH=$PATH:/usr/local/mysql-proxy/bin

2. 核心 Lua 腳本: rw-splitting.lua 關鍵邏輯

腳本核心函數 read_query() 攔截每條 SQL:

-- 簡化版核心邏輯
function read_query(packet)
    if packet:byte() == proxy.COM_QUERY then
        local sql = packet:sub(2)
        -- 事務控制語句路由到主庫
        if sql:match("^%s*(START TRANSACTION|BEGIN|COMMIT|ROLLBACK)") then
            proxy.connection.backend_ndx = 1  -- Master 索引
            return
        end
        -- SELECT (非事務中) 路由到從庫
        if sql:match("^%s*SELECT") and not proxy.connection.in_transaction then
            proxy.connection.backend_ndx = math.random(2, #proxy.global.backends) -- 隨機從庫
            return
        end
        -- 其他 (INSERT/UPDATE/DELETE/DDL) 路由到主庫
        proxy.connection.backend_ndx = 1
    end
end

3. 啟動命令詳解

mysql-proxy --daemon \
  --proxy-address=:3307 \                 # Proxy 監聽端口 (應用連這裡)
  --proxy-backend-addresses=192.168.100.104:3306 \  # Master (索引 1)
  --proxy-read-only-backend-addresses=192.168.100.210:3306 \ # Slave 1 (索引 2)
  --proxy-read-only-backend-addresses=192.168.100.208:3306 \ # Slave 2 (索引 3)
  --proxy-lua-script=/usr/local/mysql-proxy/share/mysql-proxy/rw-splitting.lua \
  --admin-address=:4041 \                 # 管理接口 (可查看連接池狀態)
  --admin-username=admin --admin-password=secret \
  --log-level=message --log-file=/var/log/mysql-proxy.log \
  --pid-file=/var/run/mysql-proxy.pid

4. 後端 MySQL 權限設置

-- Master & Slave 均需創建代理用戶
GRANT ALL PRIVILEGES ON `business_db`.* TO 'proxy_user'@'192.168.100.%' IDENTIFIED BY 'StrongPass!';
FLUSH PRIVILEGES;

三、 功能驗證測試

# 連接 Proxy
mysql -h127.0.0.1 -P3307 -uproxy_user -p

# 測試 1: 寫入 → 應路由到 Master (104)
CREATE TABLE test_rw (id INT PRIMARY KEY, val VARCHAR(20));
INSERT INTO test_rw VALUES (1, 'write_master');
-- 在 104 和 210/208 分別查詢:只有 104 有數據

# 測試 2: 讀取 → 應路由到 Slave (210/208)
SELECT * FROM test_rw;
-- 觀察 Proxy 日誌或管理接口確認後端連接分發

# 測試 3: 事務 → 必須路由到 Master
BEGIN;
INSERT INTO test_rw VALUES (2, 'in_tx');
COMMIT;
-- 事務內的 SELECT 也應走 Master (rw-splitting.lua 通過 in_transaction 標識保證)

四、 關鍵配置優化 (rw-splitting.lua 參數)

-- 連接池設置 (關鍵!默認值極小)
-- min_idle_connections: 每個後端保持的最小空閒連接數
-- max_idle_connections: 最大空閒連接數
-- 建議根據 max_connections 設置,如:
min_idle_connections = 4
max_idle_connections = 16

-- 連接驗證 (防止後端斷開導致報錯)
-- is_master_down() 邏輯優化
-- 自動剔除故障節點

五、 核心缺陷與生產環境風險

六、 生產級替代方案選型指南 (2024 推薦)

問題影響現狀
單線程事件循環無法利用多核 CPU,高併發下 CPU 100% 成為瓶頸,延遲飆升架構限制,無法修復
Lua 腳本阻塞複雜邏輯 (如解析 SQL、熔斷) 會阻塞事件循環,影響所有連接需極度簡化腳本
無連接池複用 (早期版本)每請求建連,極大開銷 (後版本改進但仍弱於 ProxySQL)性能上限低
官方停止維護 (2016 年後)無安全補丁、無新功能、不兼容 MySQL 8.0 新協議 (caching_sha2_password)**生產環境禁用**
單點故障Proxy 掛掉 = 全業務不可用,需 Keepalived/VIP 搭建 HA運維複雜度高
中間件語言/架構核心優勢適用場景學習曲線
ProxySQLC++ / 多線程事件循環高性能、多核、豐富路由規則 (Query Rules)、在線配置變更、Mirroring、原生支持 8.0、集群模式**首選**:讀寫分離、分庫分表、SQL 限流、緩存、遷移中
MyCatJava / NIO成熟分片邏輯、多租戶、跨庫 Join、擴展性好分庫分表 (Sharding) 核心場景較陡
ShardingSphere-ProxyJava / NettyApache 頂級項目、分片/讀寫分離/影子庫/加密、標準化 SPI 擴展雲原生、微服務治理、異構數據源中
VitessGo / gRPCYouTube 驗證、極致擴展性、K8s 原生、連接池、查詢重寫、物理備份超大規模、K8s 環境、雲廠商托管高
MaxScale (MariaDB)C / 模塊化MariaDB 生態最佳、Binlog 服務器、自動故障轉移MariaDB 叢集、CDC 需求中

七、 總結

MySQL Proxy 以 Lua 腳本靈活性開創了「可編程數據庫中間件」先河,**教科書級架構案例**。但受限於單線程、停止維護,**絕不建議用於生產核心鏈路**。現代選型首推 ProxySQL (輕量、高性能、功能全) 或 ShardingSphere-Proxy (標準化、生態強)。理解 Proxy 的「攔截-路由-連接池」三部曲,能讓你駕馭任何中間件得心應手。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved