基於 UCHome 核心資料庫類改造,實現透明的 MySQL 讀寫分離:SELECT 查詢自動路由到從庫,寫入操作走主庫,支援多從庫隨機負載均衡,失效自動降級。
SELECT 語句路由到從庫,其餘走主庫。class mysql_rw_php {
var $link_rw; // 主庫連線
var $link_ro; // 從庫連線
var $ro_exist; // 從庫是否可用
// ...
function connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect, $halt) { /* 建立主庫連線 */ }
function connect_ro($dbhost, $dbuser, $dbpw, $dbname, $pconnect) { /* 建立從庫連線,失敗不報錯 */ }
function set_ro_list($ro_list) { /* 隨機選一個從庫連線 */ }
function query($sql, $type) {
$this->link = &$this->link_rw; // 預設主庫
if ($this->ro_exist && preg_match("/^\s*select/i", $sql)) {
$this->link = &$this->link_ro; // SELECT 走從庫
}
// 執行查詢...
}
// 其他封裝方法:fetch_array, fetch_one_array, affected_rows, insert_id 等
}
<?php
$db = new mysql_rw_php();
// 連主庫
$db->connect('master_host', 'user', 'pass', 'dbname');
// 設定從庫列表並自動連一個
$db->set_ro_list(array(
array('dbhost'=>'slave1', 'dbuser'=>'user', 'dbpw'=>'pass'),
array('dbhost'=>'slave2', 'dbuser'=>'user', 'dbpw'=>'pass'),
));
// 後續查詢自動分流
$res = $db->query("SELECT * FROM users WHERE id=1"); // 走從庫
$db->query("UPDATE users SET name='a' WHERE id=1"); // 走主庫
?>
| 優點 | 缺點/待改進 |
|---|---|
| 極簡接入,零侵入業務代碼 | 每次請求同時持有主從兩個連線,連線數翻倍 |
| 支援多從庫隨機負載 | 未實現從庫健康檢查與自動剔除 |
| 失效自動降級保可用性 | 未支援事務跨主從、延遲檢測、權重分配 |
| 兼容舊 mysql_* API | 建議遷移至 mysqli/PDO 版本 |
原作者託管於 Google Code:https://code.google.com/p/mysql-rw-php/(現已遷移至 GitHub 等平台)。
此類適合中小型 PHP 專案快速引入讀寫分離,大型高併發系統建議使用成熟中間件(MyCat、ProxySQL、Atlas)或資料庫叢集方案。