19 用MySQL解決一些常見問題
19.1 數據庫復制
一方面復制可以用來增加健壯性和速度。對健壯性,你有2個系統,而如果你出了問題,切換到備份即可。額外的速度通過把非更新查詢的一部分送到復制服務器來達到。當然,這只在非更新查詢為主時有用,但是這正是一般的情形。
一方面復制計劃在不久的未來實現。這將被實現,使得從服務器將以較低優先級的更新和延遲插入被同步到最新數據(這將給讀者以比寫者更高的優先級)。
MySQL(至今)沒有數據庫復制,但是有一些如何實現的信息。
復制一個數據庫最一般的方法是使用更新日志。見9.2 更新日志。這要求充當一個主數據庫(進行數據改變的)並且另一個或多個充當從數據庫。要更新一個從數據庫,只要運行MySQL < update_log。提供對於從數據庫適當的主機、用戶和口令選項,並且將主數據庫的更新日志作為輸入。
如果你從未從一張表中刪除任何東西,你可以使用一個TIMESTAMP列找出自上一次復制以來(通過比較作你上次做復制的時間)表中哪個行被插入和被改變,且僅拷貝這些行到鏡像中。
有可能使用更新日志(對刪除)和時間戳記(在兩端)做成一個雙向更新系統統,但是在這種情況下,當同一數據在兩端被改變時,你必須能處理沖突。你可能想保持舊版本以幫助決定什麼被更新了。
因為在這種情況中復制用SQL語句進行,你不應該在更新數據庫的語句中使用下列函數;他們不能返回與原數據庫相同的值:
* DATABASE()
* GET_LOCK()和RELEASE_LOCK()
* RAND()
* USER(), SYSTEM_USER()或SESSION_USER()
* VERSION()
所有的時間函數可安全地使用,比如如果需要,時間戳記被送到鏡像。LAST_INSERT_ID()也可安全地使用。
19.2 數據庫備份
因為MySQL表作為文件存儲,做一個備份是容易的。為了得到一個一致的備份,在相關的表上做一個LOCK TABLES。見7.24 LOCK TABLES/UNLOCK TABLES句法。你只需一個讀鎖定;當你在數據庫目錄中做文件的一個拷貝時,這允許其他線程繼續查詢該表。如果你想要做一個SQL級的備份,你可以SELECT INTO OUTFILE。
備份一個數據庫的另一個方法是使用MySQLdump程序:
1. 為你的數據庫做一個完整的備份:
shell> MySQLdump --tab=/path/to/some/dir --opt --full
你也可以簡單地拷貝所有的表文件(“*.frm”、“*.MYD”和“*.MYI”文件),只要服務器不在更新任何東西。
2. 停止mysqld如果它正在運行,然後以--log-update選項啟動它。你將得到一個名為“hostname.n”形式的日志文件, 這裡n是隨著你每次執行mysqladmin refresh或mysqladmin flush-logs、FLUSH LOGS語句、或重啟服務器而遞增的一個數字。這些日志文件向你提供了在你執行MySQLdump處後面進行的復制數據庫改變的所需信息。
如果你必須恢復一些東西,嘗試首先用myisamchk -r恢復你的表。這應該處理所有情況的99.9%。如果myisamchk失敗,嘗試下列過程:
1. 恢復原來的MySQLdump備份。
2. 執行下列命令以再次運行更新日志中的更改:
shell> ls -1 -t -r hostname.[0-9]* | xargs cat | MySQL
ls被用來以正確的順序得到所有的日志文件。
你也可以與SELECT * INTO OUTFILE 'file_name' FROM tbl_name做有選擇的備份並且用LOAD DATA INFILE 'file_name' REPLACE ...恢復。為了避免重復記錄,在表中你需要一個PRIMARY KEY或UNIQUE鍵。當在唯一鍵值上一個新記錄與一個老記錄重復時,REPLACE關鍵詞使得老記錄用一個新記錄替代。