GB | BIG5
|
| 首頁 > 數據庫 > MySQL > 正文 |
 |
| 使用MySQL內建復制功能來最佳化可用性 |
| 作者:Michael Tanoviceanu 翻譯:limodou (2001-06-25 22:08:00) |
2000年9月20日
在Soundbreak我們每天24小時不間斷地播放實況音頻和視頻,所以對MySQL的新增
的復制特性,我們
不能做出很令人信服的測試。通過測試我們發現,可以使用這個特性來與備份數據庫服
務器保持數據同步,
這樣當主服務器因為某種原因處理失效時,能夠使用備份機處理所有的查詢。對這樣
的要求,配置兩台服
務器並不困難。我將詳細討論整個處理過程,同時討論一下當主服務器失效時,如何使
用PHP來重定向查詢。
MySQL內部復制功能是建立在兩個或兩個以上服務器之間,通過設定它們之間的主-
從關系來實現的。其
中一個作為主服務器,其它的作為從服務器。我將詳細討論如何配置兩台服務器,將一
個設為主服務器,另
一個設為從服務器。並且描述一下在它們之間進行切換的處理過程。我是在MySQL的3.2
3.23版本上進行的配
置設置過程,並且也是在這個版本上進行的測試。MySQL開發人員建議最好使用最新版本
,並且主-從服務器
均使用相同的版本。同時MySQL 3.23版本仍然是beta測試版,而且這個版本可能不能向
下兼容。所以因為這
個原因,在實際的網站中,我現在還沒有使用這個版本。擁有容錯能力具有一個好處是
,在不需中斷任何查
詢的情況下,對服務器進行升級。
第一步:配置主服務器
在這篇文章的剩下篇幅中,我將指定兩台服務器。A(IP為10.1.1.1)作為主服務器
(簡稱為主機)。B
(IP為10.1.1.2)作為備服務器(簡稱為備機)。
MySQL的復制功能的實現過程為:備機(B)與主機(A)連接,然讀出主機的二進制更
新日志,再將發生
的變化合並到自已的數據庫中。備機需要一個用戶帳號來與主機連接,所以在主機上創
建一個帳號,並只給
它FILE權限,如下操作:
GRANT FILE ON *.* TO replicate@10.1.1.2 IDENTIFIED BY 'password';
為了備機能夠與主機連接,要在主機上運行'FLUSH PRIVILEGES',不過不要擔心,
因為我們將在下面的
步驟中停掉服務器。
現在我們需要主機數據庫的一個快照,並且對主機進行配置,允許生成二進制的更
新日志。首先編輯
'my.cnf'文件,以便允許二進制更新日志,所以在[mysqld]部分的下面某個地方增加一
行:'log-bin'。在
下一次服務器啟動時,主機將生成二進制更新日志(名為:<主機名>-bin.<增量序號#>)
。為了讓二進制更新
日志有效,關閉MySQL服務程序,然將主機上的所有數據庫目錄到另一個目錄中,接著
重新啟動mysqld。
請確定得到了所有數據庫,否則在進行復制時,如果一個表在主機上存在但在備機上不
存在,將因為出錯而
退出。現在你已經得到了數據的快照,和一個從建立快照以來的二進制日志,上面記錄
著任何對數據庫的修
改。請注意MySQL數據文件(*.MYD,*.MYI和*.frm)是依賴文件系統的,所以你不能僅
僅進行文件傳輸,如
從Solaris到Linux。如果你處一個異種的服務器環境,你將不得不使用mysqldump實用
程序或其它的定制
腳本來得到數據快照。
第二步:配置備機
讓我們繼續。停掉備機上的MySQL服務程序,並且把從主機上拷貝來的數據庫目錄移
到備機上的data目
錄下。請確認將目錄的擁有者和屬組改變為MySQL用戶相應值,並且修改文件模式為660
(只對擁有者和屬組
可讀、可寫),目錄本身為770(只對擁有者和屬組可讀、可寫和可執行)。
繼續。在備機上啟動MySQL服務程序,確認MySQL工作正常。運行幾個select查詢(不
要update或insert
查詢),看一看在第一步中得到的數據快照是否成功。接著,在測試成功關掉MySQL服
務程序。
在備機上配置需要訪問的主機,以便接收主機的更改。所以需要編輯務機上的'my.
cnf'文件,在[mysqld]
部分中增加下面幾行:
master-host=10.1.1.1
master-user=replicate
master-password=password
在啟動備機服務程序,備機服務程序將查看在'my.cnf'文件中所指定的主機,查
看是否有改變,並且
將這些改變合並到自已的數據庫中。備機保持了主機的更新記錄,這些記錄是從主機的
'master.info'文件中
接收下來的。備機線程的狀態可以通過sql命令'SHOW SLAVE-STATUS'看到。在備機上處
理二進制日志中如果
發生錯誤,都將導致備機線程的退出,並且在*.err的日志文件中生成一條信息。然錯
誤可以被改正,接著
可以使用sql語句'SLAVE START'來重新啟動備機線程。線程將從主機二進制日志處理中
斷的地方繼續處理。
至此,在主機上所發生的數據改變應該已經復制到備機上了,要測試它,你可以在
主機上插入或更新一
條記錄,而在備機上選擇這條記錄。
現在我們擁有了從A機到B機的這種主-從關系,這樣當A機可能當機的時候,允許我
們將所有的查詢重定
向到B機上去,但是當A機恢復時,我們沒有辦法將發生的改變恢復到A機中去。為了解決
這個問題,我們創建
從B機到A機的主-從關系。
第三步:創建相互的主從關系
首先在B機上的my.cnf文件中,在[mysqld]部分中加入'log-bin',接著重新啟動my
sqld,然創建可在
它的上面執行復制功能的用戶帳號,使用:
GRANT FILE ON *.* TO replicate@10.1.1.1 IDENTIFIED BY 'password';
在B機上運行'FLUSH PRIVILEGES'命令,以便裝入在加入復制用戶的新的授權表,
接著回到A機上,在
它的'my.cnf'中加入下面幾行:
master-host=10.1.1.2
master-user=replicate
master-password=password
在重啟A機的服務程序之,現在我們一擁有了在A機與B機之間的相互主-從關系。
不管在哪個服務器上
更新一條記錄或插入一條記錄,都將被復制到另一台服務器上。要注意的是:我不敢確
定一個備機合並二進
制日志變化的速度有多快,所以用這種方法來進行插入或更新語句的負載平衡可能不是
一個好辦法。
第四步:修改你的數據庫連接程序
既然你已經在A機和B機之間建立了一個相互的關系,你需要修改數據庫連接程序,
以便從這種方式中得
到好處。下面的函數首先試圖與A機連接,如果不能建立連接則與B機連接。
/********************************************************
function db_connect()
returns a link identifier on success, or false on error
********************************************************/
function db_connect(){
$username = "replUser";
$password = "password";
$primary = "10.1.1.1";
$backup = "10.1.1.2";
# attempt connection to primary
if(!$link_id = @mysql_connect($primary, $username, $password))
# attempt connection to secondary
$link_id = @mysql_connect($secondary, $username, $password)
return $link_id;
}
?>
我在兩種情況下對使用了上面技術的數據庫連接建立過程進行了測試,一種是主My
SQL服務程序關閉了,
但是服務器還在運行,另一種情況是主服務器關閉了。如果只是mysqld關閉了,連接會
馬上轉向備機;但是
如果整個服務器關閉了,就出現了無限地等待(兩分鐘我放棄了跟蹤 -- 很短的注意跨
度),因為PHP在查
找一個不存在的服務器。不幸地是,不象fsockopen函數,mysql_connect函數沒有一個
超時參數,然而我們
可以使用fsockopen來模擬一個超時處理。
第五步:一個改進的數據庫連接程序
/********************************************************
function db_connect_plus()
returns a link identifier on success, or false on error
********************************************************/
function db_connect_plus(){
$username = "username";
$password = "password";
$primary = "10.1.1.1";
$backup = "10.1.1.2";
$timeout = 15; // timeout in seconds
if($fp = fsockopen($primary, 3306, &$errno, &$errstr, $timeout)){
fclose($fp);
return $link = mysql_connect($primary, $username, $password);
}
if($fp = fsockopen($secondary, 3306, &$errno, &$errstr, $timeout)){
fclose($fp);
return $link = mysql_connect($secondary, $username, $password);
}
return 0;
}
?>
這個新改進的函數向我們提供了一個可調的超時特性,這正是mysql_connect函數所
缺少的。如果連接
立即失敗,這種情況如機器"活"著,但mysqld"當"掉了,函數立即移到第二個服務器。
上面的函數相當健壯,
在試圖進行連接之前先測試一下,查看服務程序是否在指定端口進行監聽,讓你的腳本
在一段可接受的時間
段超時,允許你適當地對出錯情況進行處理。如果你修改了缺省端口3306,請保証對
端口號進行修改。
結論和意見
首先,要確定得到了一個完整的數據快照。如果忘記拷貝一個表或數據庫將導致備
機線程序停止。生成
快照的時刻是很關健的。你應該確保在拷貝數據文件之前二進制日志功能是無效的。如
果在得到快照之前就
允許了二進制日志功能,備機的線程可能會停止,原因就是當線程試圖導入重要的記錄
時,可能會由主鍵
重復而停止。最好就是接照第二部分所討論的處理辦法來做:關閉-拷貝-允許二進制日
志功能重啟。
你可能想要按照最初的一種方式來配制復制處理,並且在合適的時間關注備機,確
保備機與主機保持同
步。
我沒有測試過一個使用了復制特性的系統的負載平衡處理性能,但是我會靈活地使
用這樣系統來平衡插
入和更新。例如,如果在兩台服務器上兩條記錄都給出了同一個auto_increment值,這
種情況備機線程會在
哪一條記錄上停掉呢?象這樣的問題將會讓負載平衡作為只讀的處理,一台服務器處理
所有的插入和更新,
同時一組備機(是的,你可以有多個與主機分離的備機)處理所有的選擇。
我非常高興,MySQL已經具備了復制系統的某些功能,並且配置很簡單。使用它,你
就可以開始針對失
控的事件提供額外的安全措施了。我僅僅涉及了復制特性,這個我已經測試並且使用了
,但是在MySQL的在
線文檔中的第11部分有中更詳細的說明。
----------------------------------------------------------------------------
----
譯者的話:
由我原來使用的是3.22版的MySQL,所以為了測試一下我只好下載了3.23.24版的
最新程序。而且因為
只有一台機器,我只是增加了二進制日志的設置。不過,正如本文所說,的確有文件生
成。如果大家對此感
興趣只好請自行測試了。另外,在最新的MySQL的使用手冊中,我發現這個復制功能是在
3.23.15版以才有
的,請大家檢查自已的MySQL的版本。同時,文中關二進制日志的設置是說在my.cnf中
設置的。在我使用的
3.23.24版本中,手冊上說可以有三個文件進行參數設置,分別為windows目錄下的my.i
ni文件,c:\my.cnf和
c:\mysql\data\my.cnf中可以設置。我在設置'log-bin'時(不需要先設log參數)是使
用mysql自帶的
WinMySQLadmin軟件進行設置的,並且在my.ini中設定的,與文中不同,請大家自行測試
(http://www.fanqiang.com)
進入【UNIX論壇】
|
|
| 相關文章 |
|
|
|
|
 |
★ 樊強制作 歡迎分享 ★ |