+----------------+ +------------------+ +------------------+
| 應用/客戶端 | <---> | MySQL-Proxy | <---> | Master (寫) |
| (192.168.100.106) | | (192.168.100.208) | | 192.168.100.104 |
+----------------+ +------------------+ +------------------+
| ^ |
| | |
v | v
+------------------+
| Slave (讀) |
| 192.168.100.210 |
+------------------+
mysql-proxy-0.8.x-linux-x86_64.tar.gz (官方已停止維護,建議生產用 ProxySQL/MaxScale)wget https://www.lua.org/ftp/lua-5.1.5.tar.gz tar -zxvf lua-5.1.5.tar.gz cd lua-5.1.5 make linux test make install # 驗證 lua -v # Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
tar -zxvf mysql-proxy-0.8.5-linux-x86_64.tar.gz -C /usr/local/ cd /usr/local mv mysql-proxy-0.8.5-linux-x86_64 mysql-proxy export PATH=$PATH:/usr/local/mysql-proxy/bin/ echo 'export PATH=$PATH:/usr/local/mysql-proxy/bin/' >> /etc/profile
mysql-proxy \ --proxy-address=:4040 \ # Proxy 監聽端口 --proxy-backend-addresses=192.168.100.104:3306 \ # Master (寫) --proxy-read-only-backend-addresses=192.168.100.210:3306 \ # Slave (讀) --proxy-lua-script=/usr/local/mysql-proxy/share/mysql-proxy/rw-splitting.lua \ --proxy-connection-pool-size=10 \ # 連接池大小 --daemon --pid-file=/var/run/mysql-proxy.pid --log-file=/var/log/mysql-proxy.log \ --user=mysql
--proxy-backend-addresses:**寫操作** (INSERT/UPDATE/DELETE/CREATE/DROP/事務) 路由目標,可多個 (負載均衡)。--proxy-read-only-backend-addresses:**讀操作** (SELECT) 路由目標,可多個 (輪詢/權重)。--proxy-lua-script:核心邏輯腳本 rw-splitting.lua,內建讀寫判斷、事務識別、連接池管理。-- 在 Master 和 Slave 上執行 (保持用戶同步) CREATE USER 'proxy_user'@'%' IDENTIFIED BY 'ProxyPass123!'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `business_db`.* TO 'proxy_user'@'%'; FLUSH PRIVILEGES;
# 連接 Proxy (而非直接連 MySQL) mysql -h 192.168.100.208 -P 4040 -u proxy_user -p -D business_db # 測試寫操作 -> 應路由到 Master (104) CREATE TABLE test_rw (id INT PRIMARY KEY, name VARCHAR(20)); INSERT INTO test_rw VALUES (1, 'write_master'); # 在 Master (104) 查詢 -> 有數據 # 在 Slave (210) 查詢 -> **同步延遲下可能暫無**,但最終同步會有 # 測試讀操作 -> 應路由到 Slave (210) SELECT * FROM test_rw; # 驗證:多次執行 SELECT,觀察 Proxy 日志或 SHOW PROCESSLIST 確認連接分發到 Slave
mysql-proxy \ --proxy-backend-addresses=192.168.100.104:3306 \ --proxy-backend-addresses=192.168.100.210:3306 \ --proxy-lua-script=/usr/local/mysql-proxy/share/mysql-proxy/rw-splitting.lua
此模式下,**所有 SELECT 輪詢分發到兩個後端**,寫操作**廣播到兩個後端** (需雙主復制保證一致性)。**不推薦無雙主復制時使用**。
| 問題 | 原因 | 解決 |
|---|---|---|
| Proxy 啟動報 "module 'proxy' not found" | Lua 版本不匹配 (需 5.1) 或安裝路徑錯誤 | 重裝 Lua 5.1,確認 package.cpath 包含 proxy .so 路徑 |
| 讀寫不分離,全走 Master | SQL 中包含 /* master */ 註釋 / 事務未提交 / 使用了不支持的函數 | 檢查 Lua 腳本日志,確認 is_in_transaction() 邏輯 |
| Slave 同步延遲導致讀舊數據 | 主從異步復制天然延遲 | 關鍵業務強制走 Master (SQL 註釋 /* master */) / 使用半同步復制 / 讀取前檢查 Seconds_Behind_Master=0 |
| 連接洩漏 / 連接數耗盡 | Proxy 連接池配置不當 / 客戶端未正確關閉連接 | 調整 proxy-connection-pool-size,監控 Threads_connected |
MySQL-Proxy 最後版本 0.8.5 (2014 年),官方已棄用,不再修復 Bug/安全漏洞。
生產環境強烈建議遷移至:
- ProxySQL (高性能、多線程、動態配置、原生支持讀寫分離、查詢重寫、緩存、熔斷) —— **首選**
- MaxScale (MariaDB 官方、企業級、Binlog 過濾、防火牆、監控)
- Vitess (Google 開源、分片、連接池、查詢重寫、K8s 原生)
- 應用層框架:ShardingSphere (Java)、gorm/dbr (Go)、SQLAlchemy (Python) 內建讀寫分離路由。
rw-splitting.lua 可快速實現讀寫分離原型驗證。--proxy-backend-addresses (寫) 與 --proxy-read-only-backend-addresses (讀) 分離配置。