Application
│
▼
MySQL Proxy (Lua Router)
│
├──▶ Master (Read/Write) -- 事務、寫入
│
└──▶ Slave1, Slave2... (Read Only) -- 非事務 SELECT
MySQL 協議流程:
若在收到 SELECT 才建立連線,認證延遲會嚴重影響效能。Proxy 必須預先建立並維護對每個後端的已認證連線池,查詢到達時直接從池取用、用完歸還。
-- 非事務 SELECT → 選擇負載最低的空閒 Slave
if is_in_transaction == 0 and
packet:byte() == proxy.COM_QUERY and
packet:sub(2, 7):upper() == "SELECT" then
local best_idx = 0
local min_clients = -1
for i = 1, #proxy.servers do
local s = proxy.servers[i]
if s.type == proxy.BACKEND_TYPE_RO and s.idling_connections > 0 then
if min_clients == -1 or s.connected_clients < min_clients then
min_clients = s.connected_clients
best_idx = i
end
end
end
if best_idx > 0 then
proxy.connection.backend_ndx = best_idx
end
end
return proxy.PROXY_SEND_QUERY
| 條件 | 路由目標 |
|---|---|
| 事務中 (BEGIN/START TRANSACTION 後) | Master |
| INSERT/UPDATE/DELETE/REPLACE | Master |
| 非事務 SELECT | Slave (負載均衡) |
| DDL / 管理指令 | Master |
rpl_semi_sync_master=1。pool_size、監控 idling_connections、應用端連線池配合調整。prepare_query 階段同樣判斷並綁定後端。同樣在 Lua 中解析 SQL 提取分片鍵,映射到對應分片組:
local shard_id = hash(user_id) % shard_count
proxy.connection.backend_ndx = shard_map[shard_id]
掌握基礎原理與 Lua 腳本邏輯,即可理解讀寫分離中間件的核心運作機制。