第6章:MySQL中的複製

目錄

6.1. 複製介紹
6.2. 複製實施概述
6.3. 複製實施細節
6.3.1. 複製主線程狀態
6.3.2. 複製從I/O線程狀態
6.3.3. 複製從SQL線程狀態
6.3.4. 複製傳遞和狀態檔案
6.4. 如何設置複製
6.5. 不同MySQL版本之間的複製相容性
6.6. 升級複製設置
6.6.1. 將複製升級到5.0版
6.7. 複製特性和已知問題
6.8. 複製啟動選項
6.9. 複製FAQ
6.10. 複製故障診斷與排除
6.11. 通報複製問題
6.12. 多伺服器複製中的Auto-Increment

本章描述了MySQL提供的各種複製特性。引入了複製概念,顯示如何設置複製伺服器和服務以指導相應的複製選項。還提供了FAQ(以及答案) 列資料表,以及解決複製問題的排錯建議。

關於複製相關的SQL語句的語法描述,參見13.6節,「複製語句」

我們建議您經常訪問我們的網址http://www.mysql.com,並檢查對本章的修改。複製在不斷地得到改進,我們用最新的訊息定期更新本手冊。

6.1. 複製介紹

MySQL支援單向、異步複製,複製過程中一個伺服器充當主伺服器,而一個或多個其它伺服器充當從伺服器。(這與同步複製可以進行對比,同步複製是MySQL叢集的一個特徵—參見第17章:MySQL叢集主伺服器將更新寫入二進制日誌檔案,並維護檔案的一個索引以跟蹤日誌循環。這些日誌可以記錄發送到從伺服器的更新。當一個從伺服器連接主伺服器時,它通知主伺服器從伺服器在日誌中讀取的最後一次成功更新的位置。從伺服器接收從那時起發生的任何更新,然後封鎖並等待主伺服器通知新的更新。

如果您想要設置鏈式複製伺服器,從伺服器本身也可以充當主伺服器。

請注意當您進行複製時,所有對複製中的資料表的更新必須在主伺服器上進行。否則,您必須要小心,以避免用戶對主伺服器上的資料表進行的更新與對從伺服器上的資料表所進行的更新之間的衝突。

單向複製有利於健壯性、速度和系統管理:

·         主伺服器/從伺服器設置增加了健壯性。主伺服器出現問題時,您可以切換到從伺服器作為備份。

·         通過在主伺服器和從伺服器之間切分處理客戶查詢的負荷,可以得到更好的客戶響應時間。SELECT查詢可以發送到從伺服器以降低主伺服器的查詢處理負荷。但修改數據的語句仍然應發送到主伺服器,以便主伺服器和從伺服器保持同步。如果非更新查詢為主,該負載均衡策略很有效,但一般是更新查詢。

·         使用複製的另一個好處是可以使用一個從伺服器執行備份,而不會干擾主伺服器。在備份過程中主伺服器可以繼續處理更新。參見5.9.1節,「資料庫備份」

6.2. 複製實施概述

MySQL複製基於主伺服器在二進制日誌中跟蹤所有對資料庫的更改(更新、刪除等等)。因此,要進行複製,必須在主伺服器上啟用二進制日誌。參見5.11.3節,「二進制日誌」

每個從伺服器從主伺服器接收主伺服器已經記錄到其二進制日誌的保存的更新,以便從伺服器可以對其數據拷貝執行相同的更新。

認識到二進制日誌只是一個從啟用二進制日誌的固定時間點開始的記錄非常重要。任何設置的從伺服器需要主伺服器上的在主伺服器上啟用二進制日誌時的資料庫拷貝。如果啟動從伺服器時,其資料庫與主伺服器上的啟動二進制日誌時的狀態不相同,從伺服器很可能失敗。

將主伺服器的數據拷貝到從伺服器的一個途徑是使用LOAD DATA FROM MASTER語句。請注意LOAD DATA FROM MASTER目前只在所有資料表使用MyISAM儲存引擎的主伺服器上工作。並且,該語句將獲得全局讀鎖定,因此當資料表正複製到從伺服器上時,不可能在主伺服器上進行更新。當我們執行資料表的無鎖熱備份時,則不再需要全局讀鎖定。

由於這些限制,我們建議只有主伺服器上的數據集相對較小,或者主伺服器上延遲讀鎖定已經被接受,才可以使用LOAD DATA FROM MASTER。而LOAD DATA FROM MASTER的實際速度隨系統的不同而不同,對於執行時間,最好的規則是每1MB的數據用1秒鐘。這是一個粗略的估計,但您會發現如果主伺服器和從伺服器的性能上等價於700MHz Pentium CPU,通過100Mbps的網絡進行連接,則該估計相當準確。

從伺服器設置為複製主伺服器的數據後,它連接主伺服器並等待更新過程。如果主伺服器失敗,或者從伺服器失去與主伺服器之間的連接,從伺服器保持定期嘗試連接,直到它能夠繼續幀聽更新。由--master-connect-retry選項控制重試間隔。 預設為60秒。

每個從伺服器跟蹤複製時間。主伺服器不知道有多少個從伺服器或在某一時刻有哪些被更新了。

6.3. 複製實施細節

MySQL使用3個線程來執行複製功能(其中1個在主伺服器上,另兩個在從伺服器上。當發出START SLAVE時,從伺服器建立一個I/O線程,以連接主伺服器並讓它發送記錄在其二進制日誌中的語句。主伺服器建立一個線程將二進制日誌中的內容發送到從伺服器。該線程可以識別為主伺服器上SHOW PROCESSLIST的輸出中的Binlog Dump線程。從伺服器I/O線程讀取主伺服器Binlog Dump線程發送的內容並將該數據拷貝到從伺服器數據目錄中的本地檔案中,即中繼日誌。第3個線程是SQL線程,是從伺服器建立用於讀取中繼日誌並執行日誌中包含的更新。

在前面的描述中,每個從伺服器有3個線程。有多個從伺服器的主伺服器建立為每個當前連接的從伺服器建立一個線程;每個從伺服器有自己的I/OSQL線程。

這樣讀取和執行語句被分成兩個獨立的任務。如果語句執行較慢則語句讀取任務沒有慢下來。例如,如果從伺服器有一段時間沒有運行了,當從伺服器啟動時,其I/O線程可以很快地從主伺服器索取所有二進制日誌內容,即使SQL線程遠遠滯後。如果從伺服器在SQL線程執行完所有索取的語句前停止,I/O 線程至少已經索取了所有內容,以便語句的安全拷貝保存到本地從伺服器的中繼日誌中,供從伺服器下次啟動時執行。這樣允許清空主伺服器上的二進制日誌,因為不再需要等候從伺服器來索取其內容。

SHOW PROCESSLIST語句可以提供在主伺服器上和從伺服器上發生的關於複製的訊息。

下面的例子說明了這3個線程在SHOW PROCESSLIST中的顯示。

在主伺服器上,SHOW PROCESSLIST的輸出看上去應為:

mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
     Id: 2
   User: root
   Host: localhost:32931
     db: NULL
Command: Binlog Dump
   Time: 94
  State: Has sent all binlog to slave; waiting for binlog to
         be updated
   Info: NULL

這兒,線程2是一個連接從伺服器的複製線程。該訊息資料表示所有主要更新已經被發送到從伺服器,主伺服器正等待更多的更新出現。

在從伺服器上,SHOW PROCESSLIST的輸出看上去應為:

mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
     Id: 10
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 11
  State: Waiting for master to send event
   Info: NULL
*************************** 2. row ***************************
     Id: 11
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 11
  State: Has read all relay log; waiting for the slave I/O
         thread to update it
   Info: NULL

該訊息資料表示線程10是同主伺服器通信的I/O線程,線程11是處理保存在中繼日誌中的更新的SQL線程。SHOW PROCESSLIST運行時,兩個線程均空閒,等待其它更新。

請注意Time列的值可以顯示從伺服器比主伺服器滯後多長時間。參見6.9節,「複製FAQ」

6.3.1. 複製主線程狀態

下面列出了主伺服器的Binlog Dump線程的State列的最常見的狀態。如果您沒有在主伺服器上看見任何Binlog Dump線程,這說明複製沒有在運行—即,目前沒有連接任何從伺服器。

·         Sending binlog event to slave

二進制日誌由各種事件組成,一個事件通常為一個更新加一些其它訊息。線程已經從二進制日誌讀取了一個事件並且正將它發送到從伺服器。

·         Finished reading one binlog; switching to next binlog

線程已經讀完二進制日誌檔案並且正打開下一個要發送到從伺服器的日誌檔案。

·         Has sent all binlog to slave; waiting for binlog to be updated

線程已經從二進制日誌讀取所有主要的更新並已經發送到了從伺服器。線程現在正空閒,等待由主伺服器上新的更新導致的出現在二進制日誌中的新事件。

·         Waiting to finalize termination

線程停止時發生的一個很簡單的狀態。

6.3.2. 複製從I/O線程狀態

下面列出了從伺服器的I/O線程的State列的最常見的狀態。該狀態也出現在Slave_IO_State列,由SHOW SLAVE STATUS顯示。這說明您可以只通過該語句仔細瀏覽所發生的事情。

·         Connecting to master

線程正試圖連接主伺服器。

·         Checking master version

建立同主伺服器之間的連接後立即臨時出現的狀態。

·         Registering slave on master

建立同主伺服器之間的連接後立即臨時出現的狀態。

·         Requesting binlog dump

建立同主伺服器之間的連接後立即臨時出現的狀態。線程向主伺服器發送一條請求,索取從請求的二進制日誌檔案名和位置開始的二進制日誌的內容。

·         Waiting to reconnect after a failed binlog dump request

如果二進制日誌轉儲請求失敗(由於沒有連接),線程進入睡眠狀態,然後定期嘗試重新連接。可以使用--master-connect-retry選項指定重試之間的間隔。

·         Reconnecting after a failed binlog dump request

線程正嘗試重新連接主伺服器。

·         Waiting for master to send event

線程已經連接上主伺服器,正等待二進制日誌事件到達。如果主伺服器正空閒,會持續較長的時間。如果等待持續slave_read_timeout秒,則發生超時。此時,線程認為連接被中斷並企圖重新連接。

·         Queueing master event to the relay log

線程已經讀取一個事件,正將它複製到中繼日誌供SQL線程來處理。

·         Waiting to reconnect after a failed master event read

讀取時(由於沒有連接)出現錯誤。線程企圖重新連接前將睡眠master-connect-retry秒。

·         Reconnecting after a failed master event read

線程正嘗試重新連接主伺服器。當連接重新建立後,狀態變為Waiting for master to send event

·         Waiting for the slave SQL thread to free enough relay log space

正使用一個非零relay_log_space_limit值,中繼日誌已經增長到其組合大小超過該值。I/O線程正等待直到SQL線程處理中繼日誌內容並刪除部分中繼日誌檔案來釋放足夠的空間。

·         Waiting for slave mutex on exit

線程停止時發生的一個很簡單的狀態。

6.3.3. 複製從SQL線程狀態

下面列出了從伺服器的SQL線程的State列的最常見的狀態。

·         Reading event from the relay log

線程已經從中繼日誌讀取一個事件,可以對事件進行處理了。

·         Has read all relay log; waiting for the slave I/O thread to update it

線程已經處理了中繼日誌檔案中的所有事件,現在正等待I/O線程將新事件寫入中繼日誌。

·         Waiting for slave mutex on exit

線程停止時發生的一個很簡單的狀態。

I/O線程的State列也可以顯示語句的文本。這說明線程已經從中繼日誌讀取了一個事件,從中提取了語句,並且正在執行語句。

6.3.4. 複製傳遞和狀態檔案

預設情況,中繼日誌使用host_name-relay-bin.nnnnnn形式的檔案名,其中host_name是從伺服器主機名,nnnnnn是序列號。用連續序列號來建立連續中繼日誌檔案,從000001開始從伺服器跟蹤索引檔案中目前正使用的中繼日誌。 預設中繼日誌索引檔案名為host_name-relay-bin.index。預設情況,在從伺服器的數據目錄中建立這些檔案。可以用--relay-log--relay-log-index伺服器選項覆蓋 預設檔案名。參見6.8節,「複製啟動選項」

中繼日誌與二進制日誌的格式相同,並且可以用mysqlbinlog讀取。SQL線程執行完中繼日誌中的所有事件並且不再需要之後,立即自動刪除它。沒有直接的刪除中繼日誌的機制,因為SQL線程可以負責完成。然而,FLUSH LOGS可以循環中繼日誌,當SQL線程刪除日誌時會有影響。

在下面的條件下建立新的中繼日誌:

·         每次I/O線程啟動時建立一個新的中繼日誌。

·         當日誌被刷新時;例如,用FLUSH LOGSmysqladmin flush-logs

·         當當前的中繼日誌檔案變得太大時。「太大」含義的確定方法:

o        max_relay_log_size,如果max_relay_log_size > 0

o        max_binlog_size,如果max_relay_log_size = 0

從屬複製伺服器在數據目錄中另外建立兩個小檔案。這些狀態檔案預設名為主master.inforelay-log.info。它們包含SHOW SLAVE STATUS語句的輸出所顯示的訊息(關於該語句的描述參見13.6.2節,「用於控制從伺服器的SQL語句」)。狀態檔案保存在硬盤上,從伺服器關閉時不會丟失。下次從伺服器啟動時,讀取這些檔案以確定它已經從主伺服器讀取了多少二進制日誌,以及處理自己的中繼日誌的程度。

I/O線程更新master.info檔案。檔案中的行和SHOW SLAVE STATUS顯示的列的對應關係為:

描述

1

檔案中的行號

2

Master_Log_File

3

Read_Master_Log_Pos

4

Master_Host

5

Master_User

6

密碼(不由SHOW SLAVE STATUS顯示)

7

Master_Port

8

Connect_Retry

9

Master_SSL_Allowed

10

Master_SSL_CA_File

11

Master_SSL_CA_Path

12

Master_SSL_Cert

13

Master_SSL_Cipher

14

Master_SSL_Key

SQL線程更新relay-log.info檔案。檔案中的行和SHOW SLAVE STATUS顯示的列的對應關係為:

描述

1

Relay_Log_File

2

Relay_Log_Pos

3

Relay_Master_Log_File

4

Exec_Master_Log_Pos

當備份從伺服器的數據時,您還應備份這兩個小檔案以及中繼日誌檔案。它們用來在恢復從伺服器的數據後繼續進行複製。如果丟失了中繼日誌但仍然有relay-log.info檔案,您可以通過檢查該檔案來確定SQL線程已經執行的主伺服器中二進制日誌的程度。然後可以用Master_Log_FileMaster_LOG_POS選項執行CHANGE MASTER TO來告訴從伺服器重新從該點讀取二進制日誌。當然,要求二進制日誌仍然在主伺服器上。

如果從伺服器正複製LOAD DATA INFILE語句,您應也備份該目錄內從伺服器用於該目的的任何SQL_LOAD-*檔案。從伺服器需要這些檔案繼續複製任何中斷的LOAD DATA INFILE操作。用--slave-load-tmpdir選項來指定目錄的位置。如果未指定, 預設值為tmpdir變數的值。

6.4. 如何設置複製

這裡簡單描述了如何為您當前的MySQL伺服器設置完整的複製。假設您想要複製主伺服器上的所有資料庫,並且還沒有配置的複製。您需要關閉主伺服器來完成下面所列的步驟。

下面的程式針對設置一個從伺服器,您可以用來設置多個從伺服器。

雖然該方法是設置從伺服器的最直接的途徑,它並不是唯一的一個。例如,如果您有一個主伺服器的數據快照,並且主伺服器已經設置了伺服器ID,啟用了二進制日誌,不需要關閉主伺服器或停止對它的更新也可以設置從伺服器。詳情請參見6.9節,「複製FAQ」

如果想要管理MySQL複製設置,我們建議您通讀本章,並嘗試13.6.1節,「用於控制主伺服器的SQL語句」13.6.2節,「用於控制從伺服器的SQL語句」中的所有語句。還應熟悉6.8節,「複製啟動選項」中描述的複製啟動選項。

註釋:該程式和後面章節所示的複製SQL語句需要SUPER權限。

1.    確保在伺服器和從伺服器上安裝的MySQL版本與6.5節,「不同MySQL版本之間的複製相容性」所示的資料表兼容。理想情況,應在主伺服器和從伺服器上使用最近版本的MySQL

請先證實問題不是出現在最新的MySQL版本中再通報bug

2.    在主伺服器上為伺服器設置一個連接帳號。該帳號必須授予REPLICATION SLAVE權限。如果帳號僅用於複製(推薦這樣做),則不需要再授予任何其它權限。(關於設置用戶 帳號和權限的訊息,參見5.8節,「MySQL用戶帳號管理」

假定您的域為mydomain.com,想要建立帳號為repl的一個帳號,從伺服器可以使用該帳號從您的域內的任何主機使用密碼slavepass來訪問主伺服器。要建立該 帳號,可使用GRANT語句:

mysql> GRANT REPLICATION SLAVE ON *.*
    -> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';

如果您計劃從從屬伺服器主機使用LOAD TABLE FROM MASTERLOAD DATA FROM MASTER語句,您需要授予該帳號其它權限:

·         授予帳號SUPERRELOAD全局權限。

·         為所有想要裝載的資料表授予SELECT權限。任何該 帳號不能SELECT的主伺服器上的資料表被LOAD DATA FROM MASTER忽略掉。

3.    執行FLUSH TABLES WITH READ LOCK語句清空所有資料表和塊寫入語句:

4.            mysql> FLUSH TABLES WITH READ LOCK

對於InnoDB資料表,請注意:FLUSH TABLES WITH READ LOCK還鎖定COMMIT操作。當獲得全局讀鎖定後,可以開始InnoDB資料表的檔案系統快照。快照不能保證內部(InnoDB儲存引擎內部)一致性(因為InnoDB緩存沒有刷新),但並不需要關心該問題,因為InnoDB可以在啟動時解決該問題並給出一致的結果。這說明InnoDB在啟動快照時可以進行崩潰恢復,而不會破壞。然而,當保證一致的InnoDB資料表快照時,還沒有途徑來停止MySQL伺服器。

讓客戶程式保持運行,發出FLUSH TABLES語句讓讀鎖定保持有效。(如果退出客戶程式,鎖被釋放)然後對主伺服器上的數據進行快照。

建立快照最簡單的途徑是使用歸檔程式對主伺服器上的數據目錄中的資料庫進行二進制備份。例如,在Unix中使用tar,或者在Windows中使用PowerArchiverWinRARWinZip或者類似的軟件。要使用tar來建立包括所有資料庫的歸檔檔案,進入主伺服器的數據目錄,然後執行命令:

shell> tar -cvf /tmp/mysql-snapshot.tar .

如果您想讓歸檔只包括this_db資料庫,應使用命令:

shell> tar -cvf /tmp/mysql-snapshot.tar ./this_db

然後將歸檔檔案複製到從伺服器主機的/tmp目錄。在該機器上,進入從伺服器的數據目錄,並使用下述命令解壓縮歸檔檔案:

shell> tar -xvf /tmp/mysql-snapshot.tar

如果從伺服器的用戶帳號與主伺服器的不同,您可能不想複製mysql資料庫。在這種情況下,應從歸檔中排除該資料庫。您也不需要在歸檔中包括任何日誌檔案或者master.inforelay-log.info檔案。

FLUSH TABLES WITH READ LOCK所置讀鎖定有效時,讀取主伺服器上當前的二進制日誌名和偏移量值:

mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73       | test         | manual,mysql     |
+---------------+----------+--------------+------------------+

File列顯示日誌名,而Position顯示偏移量。在該例子中,二進制日誌值為mysql-bin.003,偏移量為73。記錄該值。以後設置從伺服器時需要使用這些值。它們資料表示複製坐標,從伺服器應從該點開始從主伺服器上進行新的更新。

取得快照並記錄日誌名和偏移量後,可以在主伺服器上重新啟用寫活動:

mysql> UNLOCK TABLES

如果您正使用InnoDB資料表,理想情況應使用InnoDB Hot Backup工具,使用該工具可以獲得一致的快照而不需要在主伺服器上進行鎖定,並且可以對應從伺服器上使用的快照來記錄日誌名和偏移量。Hot Backup是一個附加的非免費(商業)工具,沒有包含在標準 MySQL分發中。詳細訊息參見http://www.innodb.com/manual.phpInnoDB Hot Backup主頁。

不使用Hot Backup工具,最快捷的途徑是使用InnoDB資料表的二進制快照來關閉主伺服器並複製InnoDB數據檔案、日誌檔案和資料表定義檔案(.frm檔案)。要記錄當前的日誌檔案名和偏移量,關閉伺服器之前應發出下面的語句:

mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;

然後記錄前面所示的SHOW MASTER STATUS的輸出中顯示的日誌名和偏移量。記錄日誌名和偏移量後,解鎖資料表關閉伺服器以確保  伺服器關閉時的快照與當前的日誌檔案和偏移量相對應:

shell> mysqladmin -u root shutdown

適合MyISAMInnoDB資料表的另一個方法是對主伺服器上的SQL進行轉儲而不是對前面討論的二進制複製進行轉儲。為了實現,可以在主伺服器上使用mysqldump --master-data,以後將SQL轉儲檔案裝入從伺服器。但是,這樣比二進制複製要慢一些。

如果主伺服器運行時沒有啟用--logs-binSHOW MASTER STATUSmysqldump --master-data顯示的日誌名和位置值為空。在這種情況下,當以後指定從伺服器的日誌檔案和位置時需要使用的值為空字串('')4.

5.    確保主伺服器主機上my.cnf檔案的[mysqld]部分包括一個log-bin選項。該部分還應有一個server-id=Master_id選項,其中master_id必須為12321之間的一個正整數值。例如:

6.            [mysqld]
7.            log-bin=mysql-bin
8.            server-id=1

如果沒有提供那些選項,應新增它們並重啟伺服器。

9.    停止用於從伺服器的伺服器並在其my.cnf檔案中新增下面的行:

10.        [mysqld]
11.        server-id=slave_id

slave_id值同Master_id值一樣,必須為12321之間的一個正整數值。並且,從伺服器的ID必須與主伺服器的ID不相同。例如:

[mysqld]
server-id=2

如果設置多個從伺服器,每個從伺服器必須有一個唯一的server-id值,必須與主伺服器的以及其它從伺服器的不相同。可以認為server-id值類似於IP地址:這些ID值能唯一識別複製伺服器群集中的每個伺服器實例。

如果不指定一個server-id值,如果沒有定義master-host,則將它設置為1;否則設置為2。請注意如果server-id太長,主伺服器 拒絕所有來自從伺服器的連接,並且從伺服器拒絕連接到主伺服器。這樣,省略server-id只適合用二進制日誌備份。

12.如果對主伺服器的數據進行二進制備份,啟動從伺服器之前將它複製到從伺服器的數據目錄中。確保對這些檔案和目錄的權限正確。伺服器 MySQL運行的用戶必須能夠讀寫檔案,如同在主伺服器上一樣。

如果使用mysqldum備份,先啟動從伺服器(看下一步)

13.啟動從伺服器。如果前面已經複製了,用--skip-slave-start選項啟動從伺服器,以便它不立即嘗試連接主伺服器。您也可能想要用--logs-warnings選項啟動從伺服器(預設設置啟用),以便在錯誤日誌中顯示更多的問題相關的訊息(例如,網絡或連接問題)。放棄的連接將記入錯誤日誌,除非其值大於1

14.如果使用mysqldump備份主伺服器的數據,將轉儲檔案裝載到從伺服器:

15.        shell> mysql -u root -p < dump_file.sql
16.        在從伺服器上執行下面的語句,用您的系統的實際值替換選項值:
17.        mysql> CHANGE MASTER TO
18.            ->     MASTER_HOST='master_host_name',
19.            ->     MASTER_USER='replication_user_name',
20.            ->     MASTER_PASSWORD='replication_password',
21.            ->     MASTER_LOG_FILE='recorded_log_file_name',
22.            ->     MASTER_LOG_POS=recorded_log_position;

下面的資料表顯示了字串選項的最大長度:

Master_Host

60

Master_USER

16

Master_PASSWORD

32

Master_Log_File

255

23.啟動從伺服器線程:

24.        mysql> START SLAVE

執行這些程式後,從伺服器應連接主伺服器,並補充自從快照以來發生的任何更新。

如果您忘記設置主伺服器的server-id值,從伺服器不能連接主伺服器。

如果您忘記設置從伺服器的server-id值,在從伺服器的錯誤日誌中會出現下面的錯誤:

Warning: You should set server-id to a non-0 value if master_host is set;
we will force server id to 2, but this MySQL server will not act as a slave.

如果由於其它原因不能複製,從伺服器的錯誤日誌中也會出現錯誤消息。

從伺服器複製時,會在其數據目錄中發現檔案dmaster.inforelay-log.info。從伺服器使用這兩個檔案跟蹤已經處理了多少主伺服器的二進制日誌。不要移除或編輯這些檔案,除非您確切知您正在做什麼並完全理解其意義。即使這樣,最好是使用CHANGE MASTER TO語句。

註釋:master.info內容會覆蓋命令行或in my.cnf中指定的部分選項。詳情參見6.8節,「複製啟動選項」

有了一個快照,您可以用它根據剛剛描述的從伺服器部分來設置其它從伺服器。您不需要主伺服器的另一個快照;每個從伺服器可以使用相同的快照。

註釋:為了保證事務InnoDB複製設置的最大可能的耐受性和一致性,應在主伺服器的my.cnf檔案中使用innodb_flush_log_at_trx_commit=1sync-binlog=1

6.5. 不同MySQL版本之間的複製相容性

MySQL 5.1中使用的二進制日誌格式與以前的版本中所使用的大大不同,特別是在字元編碼處理、LOAD DATA INFILE以及時區方面。

註釋:您不能從使用新二進制日誌格式的主伺服器向使用舊二進制日誌格式的從伺服器複製(例如,從MySQL 5.0MySQL 4.1。這樣操作在複製設置升級伺服器時後果嚴重,參見6.6節,「升級複製設置」

我們推薦使用最近的MySQL版本,因為複製功能在不斷地改進中。我們還推薦主伺服器和從伺服器使用相同的版本。我們建議升級主伺服器和從伺服器,運行alphabeta版本到新的(產品)版本。在許多情況下,從新的主伺服器向舊的從伺服器複製將會失敗。一般原則,運行MySQL 5.1.x的從伺服器可以與舊的主伺服器(可以運行MySQL 3.234.0或者4.1)一起使用,但不能反過來。

前面的訊息適合協議級複製相容性。然而,還會有一個約束條件,例如SQL級相容性問題。例如, 5.1版本的主伺服器不能複製到5.0版本的從伺服器,如果複製語句使用5.1版本的SQL特性而不是5.0版本。這些問題和其它問題均在6.7節,「複製特性和已知問題」中討論。

6.6. 升級複製設置

當在複製設置中升級伺服器時,升級過程取決於當前的伺服器版本和要升級的伺服器版本。

6.6.1. 將複製升級到5.0版

該節適用於將複製從MySQL 3.234.0或者4.1升級到5.14.0伺服器應為4.0.3或更新版。

當將早期MySQL版本系列主伺服器升級到5.1時,應先確保該主伺服器的所有從伺服器使用了相同的5.1.x版本。如果不是這樣,您應先升級從伺服器。升級從伺服器時,應先關閉從伺服器,升級到相應5.1.x版本,然後重啟從伺服器並重新開始複製。5.1版本的從伺服器能夠讀取升級前寫入的舊的中繼日誌並執行日誌中包含的語句。升級後從伺服器建立的中繼日誌為5.1格式。

從伺服器升級後,關閉主伺服器,將它升級到與從伺服器相同的5.1.x版本並重啟它。5.1主伺服器能夠讀取升級前寫入的舊的二進制日誌並將它們發送到5.1從伺服器。從伺服器可以識別舊的格式並正確處理它。升級後主伺服器建立的二進制日誌採用5.1格式。這樣也可以由5.1從伺服器識別。

換句話說,當升級到5.1時沒有什麼措施,只有將主伺服器升級到5.1之前先將從伺服器升級到5.1。請注意從5.1降級到舊版本不會如此簡單:必須確保已經完全處理所有5.1版本的二進制日誌或中繼日誌,以便在降級前可以移除它們。

6.7. 複製特性和已知問題

一般原則,SQL級複製相容性要求主伺服器和從伺服器均支援使用的特性。例如,在MySQL 5.0.0中開始使用TIMESTAMPADD()函數。如果在主伺服器上使用該函數,不能複製到MySQL 5.0.0之前的從伺服器。如果您計劃在5.1和以前版本的MySQL之間進行複製,您應查閱對應以前版本系列的MySQL參考手冊,查詢該系列複製特徵相關訊息。

下面列出了關於支援什麼和不支援什麼的詳細訊息。關於複製的其它InnoDB具體訊息參見15.2.6.5節,「InnoDB和MySQL複製」

關於保存的程式和觸發器的複製問題在20.4節,「儲存子程式和觸發程式的二進制日誌功能」中討論。

·         AUTO_INCREMENTLAST_INSERT_ID()TIMESTAMP值正確實現複製。

·         USER()UUID()LOAD_FILE()函數毫無改變地被,這樣不能可靠地在從伺服器上工作。

·         下面的限制只適合基於語句的複製,而不是基於行的複製。處理用戶級鎖定的函數GET_LOCK()RELEASE_LOCK()IS_FREE_LOCK()IS_USED_LOCK()複製時從伺服器不知道在主伺服器上同時進行的相關文本;因此如果從伺服器上的內容不同,這些函數不用來插入到主伺服器的資料表中(例如不執行INSERT INTO mytable VALUES(GET_LOCK(...)))

·         MySQL 5.1FOREIGN_KEY_CHECKSSQL_MODEUNIQUE_CHECKSSQL_AUTO_IS_NULL變數均複製。但TABLE_TYPE,即STORAGE_ENGINE變數 不複製,有利於在不同的儲存引擎之間進行複製。

·         即使主伺服器和從伺服器有不同的全局字元編碼變數,以及即使有不同的全局時區變數仍可以複製。

·         下面適合使用不同字元編碼的MySQL伺服器之間的複製:

1.    必須在主伺服器和從伺服器上總是使用相同的全局字元編碼和校對規則(--default-character-set--default-collation)。否則,會在從伺服器上遇到複製鍵值錯誤,因為在主伺服器的字元編碼中被認為是唯一的鍵值在從伺服器的字元編碼中可能不是唯一的。

2.    如果主伺服器早於MySQL 4.1.3,則會話中的字元編碼不應與其全局值不同(換句話說,不要使用SET NAMESSET CHARACTER SET等等),因為從伺服器不知道該字元編碼的更改。如果主伺服器和從伺服器均為4.1.3或更新版,可以隨便將會話的字元編碼變數設置為本地值(例如NAMESCHARACTER SETCOLLATION_CLIENTCOLLATION_SERVER),因為這些設定值被寫入二進制日誌,因此從伺服器知道。然而,禁止更改會話中這些變數的全局值;如前面所述,主伺服器和從伺服器必須具有唯一的全局字元編碼值。

3.    如果在主伺服器上的資料庫的字元編碼與全局collation_server值不同,則應設計CREATE TABLE語句,以便它們不隱含依賴資料庫的預設字元編碼(Bug #2326);一個好的解決辦法是在CREATE TABLE中明顯說明字元編碼和校對規則。

·         應在主伺服器和從伺服器上設置相同的系統時區。否則一些語句,例如使用NOW()FROM_UNIXTIME()函數的語句,將不會正確複製。可以使用指令mysqld_safe--timezone=timezone_name選項或通過設置TZ環境變數設置MySQL伺服器運行的系統的時區。主伺服器和從伺服器還應有相同的預設連接時區設置;即主伺服器和從伺服器應有相同的--default-time-zone參數值。

·         CONVERT_TZ(...,...,@global.time_zone)不能正確複製。只有主伺服器和從伺服器均為5.0.4或更新版才能正確複製CONVERT_TZ(...,...,@session.time_zone)

·         會話變數只有在更新資料表的語句中使用時才能正確複製;例如:SET MAX_JOIN_SIZE=1000INSERT INTO mytable VALUES(@MAX_JOIN_SIZE)不能將相同的數據插入到主伺服器上和從伺服器上。不適用於通用的SET TIME_ZONE=...INSERT INTO mytable VALUES(CONVERT_TZ(...,...,@time_zone))

·         可以將從伺服器上的非事務資料表復為主伺服器上的事務資料表。例如,可以將主伺服器上的InnoDB資料表複製為從伺服器上的MyISAM資料表。然而,複製過程中,如果從伺服器在BEGIN/COMMIT塊過程中停止則會產生問題,因為從伺服器在BEGIN塊開始時會重啟。該問題出現在TODO中,不久將會得到修復。

·         MySQL 5.1中可以正確複製引用用戶變數(@var_name形式的變數)的更新語句;但在4.1以前的版本中卻不可能。請注意從MySQL 5.1開始對用戶變數名的大小寫不再敏感;當在5.1和舊版本之間設置複製時應考慮該問題。

·         從伺服器可以使用SSL連接到主伺服器。

·         有一個全局系統變數slave_transaction_retries:如果因為某個InnoDB死鎖或超過 InnoDBinnodb_lock_wait_timeoutNDB叢集的TransactionDeadlockDetectionTimeoutTransactionInactiveTimeoutREPLICATION SLAVESQL線程未能執行某個事務,在給出錯誤停止前自動重試slave_transaction_retries次。 預設值是10。從MySQL 5.0.4開始,可以從SHOW STATUS的輸出中看到重試總次數;參見5.3.4節,「伺服器狀態變數」

·         如果在主伺服器上的CREATE TABLE語句中使用了DATA DIRECTORYINDEX DIRECTORY子句,子句也可以在從伺服器上使用。如果在從伺服器主機檔案系統中不存在一致的目錄或雖然存在但不能被從伺服器訪問,則會帶來問題。MySQL 5.1支援一個稱為NO_DIR_IN_CREATEsql_mode選項。如果從伺服器運行時將SQL模式設置為包括該選項,複製CREATE TABLE語句時將忽略這些子句。結果是在資料表的資料庫目錄中建立了MyISAM數據和索引檔案。

·         下面的限制只適合基於語句的複製,而不是基於行的複製:如果在查詢中數據修改不確定,主伺服器和從伺服器上的數據可以不同;也就是由查詢最佳化器確定。(這是常用的但不是很好的習慣,即使不是在複製中也不好)關於該問題的詳細解釋,參見A.8.1節,「MySQL中的打開事宜」

·         READ LOCKFLUSH LOGSFLUSH MASTERFLUSH SLAVEFLUSH TABLES不記入日誌,因為如果複製到從伺服器會造成問題。關於語法示範,參見13.5.5.2節,「FLUSH語法」FLUSH TABLESANALYZE TABLEOPTIMIZE TABLEREPAIR TABLE語句被寫入二進制日誌並會複製到從伺服器。一般情況不會造成問題,因為這些語句不修改資料表的數據。但是在某些情況下會帶來問題。如果您複製mysql資料庫中的授權資料表並且不使用GRANT直接更新那些資料表,必須在從伺服器上執行FLUSH PRIVILEGES使新的權限生效。並且,如果使用FLUSH TABLES重新命名MERGE資料表的MyISAM資料表,必須手動在從伺服器上執行FLUSH TABLES。如果不指定NO_WRITE_TO_BINLOG或其別名LOCAL,則這些語句被寫入二進制日誌。

·         MySQL只支援一個主伺服器和多個從伺服器。我們計劃將來新增一個投票算法,當前的主伺服器出現問題時自動切換。我們還計劃引入代理過程通過向不同的從伺服器發送SELECT查詢以幫助進行負載均衡。

·         當伺服器關閉、重啟時,其MEMORY資料表將變為空。主伺服器按下述方法複製該結果:啟動後第1次主伺服器使用每個MEMORY資料表,它通知從伺服器需要向資料表寫入DELETE FROM語句來清空二進制日誌的資料表。詳細訊息參見15.4節,「MEMORY (HEAP)儲存引擎」

·         除了關閉從伺服器(而不僅僅是從伺服器線程) 臨時資料表都被複製,並且還沒有在從伺服器上執行的更新所使用的臨時資料表也已經複製。如果關閉從伺服器,從伺服器重啟後更新需要的那些臨時資料表不可再用。為了避免該問題,臨時資料表打開時不要關閉從伺服器。而應遵照下面的程式:

1.    執行STOP SLAVE語句。

2.    使用SHOW STATUS檢查slave_open_temp_tables變數的值。

3.    如果值為0,使用mysqladmin shutdown命令關閉從伺服器。

4.    如果值不為0,用START SLAVE重啟從伺服器線程。

5.    後面再重複該程式看下次的運氣是否好一些。

我們計劃在不久的將來修復該問題。

·         可以很安全地連接用--logs-slave-updates選項指定的循環主伺服器/從伺服器關係中的伺服器。但請注意許多語句在這種設置中不能正確工作,除非您的客戶代碼關注了潛在的在不同的伺服器不同順序的更新中可能發生的這類問題。

這說明您可以像這樣建立設置:

A -> B -> C -> A

伺服器ID被編碼在二進制日誌事件中,因此伺服器A知道何時自己首次建立它讀取的事件並且不執行事件(除非用--replicate-same-server-id選項啟動了伺服器A,只在很少情況下有意義)。這樣,沒有無限循環。只有對資料表執行沒有衝突的更新時該類循環設置才能工作。換句話說,如果在AC中插入數據,絕對不應在A中插入鍵值可能與插入到C中的行相衝突的一行。如果更新的順序很重要,還不應更新兩個伺服器上相同的行。

·         如果從伺服器上的某個語句產生錯誤,則從伺服器上的SQL線程終止,並且從伺服器向錯誤日誌寫入一條消息。此時應手動連接從伺服器,修復該問題(例如,一個不存在的資料表),然後運行START SLAVE

·         可以很安全地關閉主伺服器並在以後重啟。如果某個從伺服器丟失與主伺服器的連接,從伺服器嘗試立即重新連接。如果失敗,從伺服器定期重試。(預設設置是每60秒重試一次。可以通過--master-connect-retry選項更改)從伺服器也能夠處理網絡連接中斷。但是,只有從伺服器超過slave_net_timeout秒沒有從主伺服器收到數據才通知網絡中斷。如果中斷時間短,可以降低slave_net_timeout。參見5.3.3節,「伺服器系統變數」

·         關閉從伺服器(淨關閉)也很安全,因為它可以跟蹤它離開的地點。不純淨的關閉操作會產生問題,特別是系統關閉前硬盤緩存未刷新到硬盤上時。如果有不間斷電源,可以大大提高系統容錯能力。不純淨的關閉主伺服器會造成主伺服器上的資料表和二進制日誌內容之間的不一致性;在主伺服器上使用InnoDB資料表和--innodb-safe-binlog選項可以避免該問題。參見5.11.3節,「二進制日誌」(註釋:MySQL 5.1中不需要--innodb-safe-binlog,由於引入了XA事務支援已經作廢了)

·         由於MyISAM資料表的非事務屬性,可以有一個語句只是更新一個資料表並返回錯誤代碼。例如,多行插入時有一個行超過鍵值約束,或者如果長的更新語句更新部分行後被殺掉了。如果發生在主伺服器上,除非錯誤代碼合法並且語句執行產生相同的錯誤代碼,從伺服器線程將退出並等待資料庫管理員決定如何做。如果該錯誤代碼驗證行為不理想,可以用--slave-skip-errors選項掩蓋(忽視)部分或全部錯誤。

·         如果從BEGIN/COMMIT系列的非事務資料表更新事務資料表,如果提交事務前更新非事務資料表,對二進制日誌的更新可能會不同步。這是因為事務提交後才被寫入二進制日誌。

·         事務混合更新事務資料表和非事務資料表時,二進制日誌中語句的順序是正確的,即使在ROLLBACK時,所有需要的語句也會寫入二進制日誌。但是如果在第1個連接的事務完成前,第2個連接更新非事務資料表,語句記入日誌時會出現順序錯誤,因為第2個連接的更新執行完後立即寫入日誌,而不管第1個連接執行的事務的狀態如何。

6.8. 複製啟動選項

在主伺服器和從伺服器上,均必須使用server-id選項為每個伺服器建立唯一的複製ID。您應為每個主伺服器和從伺服器從12321的範圍挑一個唯一的正整數。例如:server-id=3

用於主伺服器上控制二進制日誌的選項的相關描述見5.11.3節,「二進制日誌」

下資料表描述了可以用於MySQL 5.1從屬複製伺服器的選項。您可以在命令行中或在選項檔案中指定這些選項。

某些從伺服器複製選項按特殊方式處理,當從伺服器啟動時如果master.info檔案存在並且包含選項值,它們將被忽略掉。下面的選項按這種方式處理:

·         --master-host

·         --master-user

·         --master-password

·         --master-port

·         --master-connect-retry

·         --master-ssl

·         --master-ssl-ca

·         --master-ssl-capath

·         --master-ssl-cert

·         --master-ssl-cipher

·         --master-ssl-key

5.1中的master.info檔案格式包括對應SSL選項的值。並且,檔案格式包括檔案中的行號,如同第1行。如果您將舊的伺服器升級到新的版本,新伺服器啟動時自動將smaster.info檔案升級到新的格式。然而,如果將新伺服器降級到舊的版本,首次啟動舊版本的伺服器之前應刪除第1行。

如果從伺服器啟動時master.info檔案不存在,選項採用選項檔案或命令行中指定的值。首次將伺服器作為從伺服器啟動時,或者已經運行RESET SLAVE然後已經關閉並重啟從伺服器時會發生。

如果從伺服器啟動時master.info檔案存在,伺服器忽略那些選項。使用master.info檔案中發現的值。

如果您使用與master.info檔案中相對應的啟動選項的不同的值重啟從伺服器,啟動選項的不同的值不會生效,因為伺服器繼續使用master.info檔案。要想使用啟動選項的不同的值,必須刪除master.info檔案並重啟從伺服器,或(最好是)在從伺服器運行時使用CHANGE MASTER TO語句重新設置值。

假定在my.cnf檔案中指定該選項:

[mysqld]
master-host=some_host

1次作為複製從伺服器啟動伺服器時,從my.cnf檔案讀取並使用選項。伺服器然後記錄master.info檔案中的值。下次啟動伺服器時,它只從伺服器的master.info檔案讀取主伺服器主機值並忽略選項檔案中的值。如果您修改my.cnf檔案為some_other_host指定其它主伺服器主機,更改仍然不會生效。您應使用CHANGE MASTER TO

因為伺服器給已有master.info檔案的優先權高於剛剛描述的啟動選項,可以選擇不使用這些值的啟動選項,而是使用CHANGE MASTER TO語句來指定。參見13.6.2.1節,「CHANGE MASTER TO語法」

下面的例子顯示了如何更廣泛地使用啟動選項來配置從伺服器:

[mysqld]
server-id=2
master-host=db-master.mycompany.com
master-port=3306
master-user=pertinax
master-password=freitag
master-connect-retry=60
report-host=db-slave.mycompany.com

下面列出了控制複製的啟動選項:許多選項可以在伺服器運行時通過CHANGE MASTER TO語句重新進行設置。其它選項,例如--replicate-*選項,只能在從伺服器啟動時進行設置。我們計劃將修復該問題。

·         --logs-slave-updates

通常情況,從伺服器從主伺服器接收到的更新不記入它的二進制日誌。該選項告訴從伺服器將其SQL線程執行的更新記入到從伺服器自己的二進制日誌。為了使該選項生效,還必須用--logs-bin選項啟動從伺服器以啟用二進制日誌。如果想要應用鏈式複製伺服器,應使用--logs-slave-updates。例如,可能您想要這樣設置:

A -> B -> C

也就是說,A為從伺服器B的主伺服器,B為從伺服器C的主伺服器。為了能工作,B必須既為主伺服器又為從伺服器。您必須用--logs-bin啟動AB以啟用二進制日誌,並且用--logs-slave-updates選項啟動B

·         --logs-warnings

讓從伺服器向錯誤日誌輸出更詳細的關於其執行操作的消息。例如,通知您網絡/連接失敗後已經成功重新連接,並通知您每個從伺服器線程如何啟動。該選項預設啟用;要想禁用它,使用--skip-logs-warnings。放棄的連接不記入錯誤日誌,除非該值大於1

請注意該選項的效果不限於複製。可以對伺服器的部分動作產生警告。

·         --master-connect-retry=seconds

在主伺服器宕機或連接丟失的情況下,從伺服器線程重新嘗試連接主伺服器之前睡眠的秒數。如果主伺服器.info檔案中的值可以讀取則優先使用。如果未設置, 預設值為60

·         --master-host=host

主複製伺服器的主機名或IP地址。如果沒有給出該選項,從伺服器線程不啟動。如果主伺服器.info檔案中的值可以讀取則優先使用。

·         --master-info-file=file_name

從伺服器用於記錄主伺服器的相關訊息使用的檔案名。預設名為數據目錄中的mysql.info

·         --master-password=password

連接主伺服器時從伺服器線程用於鑒定的帳號的密碼。如果主伺服器.info檔案中的值可以讀取則優先使用。如果未設置,假定 密碼為空。

·         --master-port=port_number

主伺服器正幀聽的TCP/IP端口號。如果主伺服器.info檔案中的值可以讀取則優先使用。如果未設置,假定使用編譯進來的設定值。如果您未曾用configure選項進行修改,該值應為3306

·         --master-ssl--master-ssl-ca=file_name--master-ssl-capath=directory_name--master-ssl-cert=file_name--master-ssl-cipher=cipher_list--master-ssl-key=file_name

這些選項用於使用SSL設置與主伺服器的安全複製連接。它們的含義與5.8.7.6節,「SSL命令行選項」中描述的相應ssl--ssl-ca--ssl-capath--ssl-cert--ssl-cipher--ssl-key選項相同。如果主伺服器.info檔案中的值可以讀取則優先使用。

·         --master-user=username

連接主伺服器時從伺服器線程用於鑒定的帳號的帳號。該帳號必須具有REPLICATION SLAVE權限。如果主伺服器.info檔案中的值可以讀取則優先使用。如果未設置主伺服器用戶,假定使用用戶test

·         --max-relay-logs-size=size

自動循環中繼日誌。參見5.3.3節,「伺服器系統變數」

·         --read-only

該選項讓從伺服器只允許來自從伺服器線程或具有SUPER權限的用戶的更新。可以確保從伺服器不接受來自客戶的更新。

·         --relay-log=file_name

中繼日誌名。預設名為host_name-relay-bin.nnnnnn,其中host_name是從伺服器主機的名,nnnnnn資料表示中繼日誌在編號序列中建立。如果中繼日誌太大(並且您不想降低max_relay_log_size),需要將它們放到數據目錄之外的其它地方,或者如果想要通過硬盤之間的負載均衡提高速度,可以指定選項建立與主機名無關的中繼日誌名。

·         --relay-log-index=file_name

中繼日誌索引檔案使用的位置和名稱。預設名為host_name-relay-bin.index,其中host_name為從伺服器名。

·         --relay-log-info-file=file_name

從伺服器用於記錄中繼日誌相關訊息的檔案名。預設名為數據目錄中的relay-log.info

·         --relay-log-purge={0|1}

禁用或啟用不再需要中繼日誌時是否自動清空它們。預設值為1(啟用)。這是一個全局變數,可以用SET GLOBAL Relay_log_purge動態更改。

·         --relay-log-space-limit=size

限制所有中繼日誌在從伺服器上所佔用空間的上限(0值資料表示「無限制)。從伺服器主機硬盤空間有限時很有用。達到限制後,I/O線程停止從主伺服器讀取二進制日誌中的事件,直到SQL線程被閉鎖並且刪除了部分未使用的中繼日誌。請注意該限制並不是絕對的:有可能SQL線程刪除中繼日誌前需要更多的事件。在這種情況下,I/O線程將超過限制,直到SQL線程可以刪除部分中繼日誌。(不這樣做將會造成死鎖)--relay-log-space-limit的值不能小於--max-relay-logs-size(或如果--max-relay-logs-size0,選--max-binlog-size)的值的兩倍。在這種情況下,有可能I/O線程等待釋放空間,因為超過了--relay-log-space-limit,但SQL線程沒有要清空的中繼日誌,不能滿足I/O線程的需求。強制I/O線程臨時忽視--relay-log-space-limit

·         --replicate-do-db=db_name

告訴從伺服器限制預設資料庫(USE所選擇)db_name的語句的複製。要指定多個資料庫,應多次使用該選項,每個資料庫使用一次。請注意不複製跨資料庫的語句,例如當已經選擇了其它資料庫或沒有資料庫時執行UPDATE some_db.some_table SET foo='bar'。如果需要跨資料庫進行更新,使用--replicate-wild-do-table=db_name.%。請讀取該選項列資料表後面的注意事項。

一個不能按照期望工作的例子:如果用--replicate-do-db=sales啟動從伺服器,並且在主伺服器上執行下面的語句,UPDATE語句不會複製:

USE prices;
UPDATE sales.january SET amount=amount+1000;

如果需要跨資料庫進行更新,應使用--replicate-wild-do-table=db_name.%

只檢查預設資料庫」行為的主要原因是語句自己很難知道它是否應被複製(例如,如果您正使用跨資料庫的多資料表DELETE語句或多資料表UPDATE語句)。如果不需要,只檢查預設資料庫比檢查所有資料庫要快得多。

·         --replicate-do-table=db_name.tbl_name

告訴從伺服器線程限制對指定資料表的複製。要指定多個資料表,應多次使用該選項,每個資料表使用一次。同--replicate-do-db對比,允許跨資料庫更新。請讀取該選項列資料表後面的注意事項。

·         --replicate-ignore-db=db_name

告訴從伺服器不要複製預設資料庫(USE所選擇)db_name的語句。要想忽略多個資料庫,應多次使用該選項,每個資料庫使用一次。如果正進行跨資料庫更新並且不想複製這些更新,不應使用該選項。請讀取該選項後面的注意事項。

一個不能按照期望工作的例如:如果用--replicate-ignore-db=sales啟動從伺服器,並且在主伺服器上執行下面的語句,UPDATE語句不會複製:

·                USE prices;
·                UPDATE sales.january SET amount=amount+1000;

如果需要跨資料庫更新,應使用--replicate-wild-ignore-table=db_name.%

·         --replicate-ignore-table=db_name.tbl_name

告訴從伺服器線程不要複製更新指定資料表的任何語句(即使該語句可能更新其它的資料表)。要想忽略多個資料表,應多次使用該選項,每個資料表使用一次。同--replicate-ignore-db對比,該選項可以跨資料庫進行更新。請讀取該選項後面的注意事項。

·         --replicate-wild-do-table=db_name.tbl_name

告訴從伺服器線程限制複製更新的資料表匹配指定的資料庫和資料表名模式的語句。模式可以包含『%』和『_』通配符,與LIKE模式匹配操作符具有相同的含義。要指定多個資料表,應多次使用該選項,每個資料表使用一次。該選項可以跨資料庫進行更新。請讀取該選項後面的注意事項。

例如:--replicate-wild-do-table=foo%.bar%只複製資料庫名以foo開始和資料表名以bar開始的資料表的更新。

如果資料表名模式為%,可匹配任何資料表名,選項也適合資料庫級語句(CREATE DATABASEDROP DATABASEALTER DATABASE)。例如,如果使用--replicate-wild-do-table=foo%.%,如果資料庫名匹配模式foo%,則複製資料庫級語句。

要想在資料庫或資料表名模式中包括通配符,用反斜線對它們進行轉義。例如,要複製名為my_own%db的資料庫的所有資料表,但不複製my1ownAABCdb資料庫的資料表,應這樣轉義『_』和『%』字元:--replicate-wild-do-table=my\_own\%db。如果在命令行中使用選項,可能需要雙反斜線或將選項值引起來,取決於命令解釋符。例如,用bash外殼則需要輸入--replicate-wild-do-table=my\\_own\\%db

·         --replicate-wild-ignore-table=db_name.tbl_name

告訴從伺服器線程不要複製資料表匹配給出的通配符模式的語句。要想忽略多個資料表,應多次使用該選項,每個資料表使用一次。該選項可以跨資料庫進行更新。請讀取該選項後面的注意事項。

例如:--replicate-wild-ignore-table=foo%.bar%不複製資料庫名以foo開始和資料表名以bar開始的資料表的更新。

關於匹配如何工作的訊息,參見--replicate-wild-do-table選項的描述。在選項值中包括通配符的規則與--replicate-wild-ignore-table相同。

·         --replicate-rewrite-db=from_name->to_name

告訴從伺服器如果預設資料庫(USE所選擇)為主伺服器上的from_name,則翻譯為to_name。只影響含有資料表的語句(不是類似CREATE DATABASEDROP DATABASEALTER DATABASE的語句),並且只有from_name為主伺服器上的預設資料庫時。該選項不可以跨資料庫進行更新。請注意在測試--replicate-*規則之前翻譯資料庫名。

如果在命令行中使用該選項, 『>』字元專用於命令解釋符,應將選項值引起來。例如:

shell> mysqld --replicate-rewrite-db="olddb->newdb"

·         --replicate-same-server-id

將用於從伺服器上。通常可以預設設置為0以防止循環複製中的無限循環。如果設置為1,該從伺服器不跳過有自己的伺服器id的事件;通常只在有很少配置的情況下有用。如果使用--logs-slave-updates不能設置為1。請注意預設情況下如果有從伺服器的id,伺服器I/O線程不將二進制日誌事件寫入中繼日誌(該最佳化可以幫助節省硬盤的使用)。因此如果想要使用--replicate-same-server-id,讓從伺服器讀取自己的SQL線程執行的事件前,一定要用該選項啟動。

·         --report-host=slave_name

從伺服器註冊過程中報告給主伺服器的主機名或IP地址。該值出現在主伺服器上SHOW SLAVE HOSTS的輸出中。如果不想讓從伺服器自己在主伺服器上註冊,則不設置該值。請注意從伺服器連接後,主伺服器僅僅從TCP/IP套接字讀取從伺服器的IP號是不夠的。由於 NAT和其它路由問題,IP可能不合法,不能從主伺服器或其它主機連接從伺服器。

·         --report-port=slave_port

連接從伺服器的TCP/IP端口號,從伺服器註冊過程中報告給主伺服器。只有從伺服器幀聽非預設端口或如果有一個特殊隧道供主伺服器或其它客戶連接從伺服器時才設置它。如果您不確定,不設置該選項。

·         --skip-slave-start

告訴從伺服器當伺服器啟動時不啟動從伺服器線程。使用START SLAVE語句在以後啟動線程。

·         --slave_compressed_protocol={0|1}

如果該選項設置為 1,如果從伺服器和主伺服器均支援,使用壓縮從伺服器/主伺服器協議。

·         --slave-load-tmpdir=file_name

從伺服器建立臨時檔案的目錄名。該選項預設等於tmpdir系統變數的值。當從伺服器SQL線程複製LOAD DATA INFILE語句時,從中繼日誌將待裝載的檔案提取到臨時檔案,然後將這些檔案裝入到資料表中。如果裝載到主伺服器上的檔案很大,從伺服器上的臨時檔案也很大。因此,建議使用該選項告訴從伺服器將臨時檔案放到檔案系統中有大量可用空間的目錄下。在這種情況下,也可以使用--relay-log選項將中繼日誌放到該檔案系統中,因為中繼日誌也很大。--slave-load-tmpdir應指向基於硬盤的檔案系統,而非基於內存的檔案系統:從伺服器需要用臨時檔案在機器重啟時用於複製LOAD DATA INFILE。系統啟動過程中作業系統也不能清除該目錄。

·         --slave-net-timeout=seconds

放棄讀之前從主伺服器等候更多數據的秒數,考慮到連接中斷和嘗試重新連接。超時後立即開始第1次重試。由--master-connect-retry選項控制重試之間的間隔。

·         --slave-skip-errors=[err_code1,err_code2,... | all]

通常情況,當出現錯誤時複製停止,這樣給您一個機會手動解決數據中的不一致性問題。該選項告訴從伺服器SQL線程當語句返回任何選項值中所列的錯誤時繼續複製。

如果您不能完全理解為什麼發生錯誤,則不要使用該選項。如果複製設置和客戶程式中沒有bug,並且MySQL自身也沒有bug,應不會發生停止複製的錯誤。濫用該選項會使從伺服器與主伺服器不能保存同步,並且您找不到原因。

對於錯誤代碼,您應使用從伺服器錯誤日誌中錯誤消息提供的編號和SHOW SLAVE STATUS的輸出。伺服器錯誤代碼列於附錄B:錯誤代碼和消息

您也可以(但不應)使用不推薦的all值忽略所有錯誤消息,不考慮所發生的錯誤。無需而言,如果使用該值,我們不能保證數據的完整性。在這種情況下,如果從伺服器的數據與主伺服器上的不相近請不要抱怨(或編寫bug報告)已經警告您了

例如:

--slave-skip-errors=1062,1053
--slave-skip-errors=all

從伺服器按下面評估--replicate-*規則,確定是否執行或忽視語句:

1.    是否有--replicate-do-db--replicate-ignore-db規則?

·         :測試--binlog-do-db--binlog-ignore-db(參見5.11.3節,「二進制日誌」)。測試結果是什麼?

o        忽視語句:忽視並退出。

o        授權語句:不立即執行語句。推遲決策;繼續下一步。

·         沒有:繼續下一步。

2.    我們目前正執行保存的程式或函數嗎?

·         :執行查詢並退出。

·         :繼續下一步。

3.    是否有--replicate-*-table規則?

·         沒有:執行查詢並退出。

·         :繼續下一步並開始按所示順序評估資料表規則(首先是非通配規則,然後是通配規則)。只有待更新的資料表根據這些規則進行比較(INSERT INTO sales SELECT * FROM prices:只有sales根據這些規則進行比較)。如果要更新幾個資料表(多資料表語句),第1個匹配的資料表(匹配「do」或「ignore)獲贏。也就是說,根據這些規則比較第1個資料表。然後,如果不能進行決策,根據這些規則比較第2個資料表等等。

4.    是否有--replicate-do-table規則?

·         :資料表匹配嗎?

o        :執行查詢並退出。

o        :繼續下一步。

·         沒有:繼續下一步。

5.    是否有--replicate-ignore-table規則?

·         :資料表匹配嗎?

o        :忽視查詢並退出。

o        :繼續下一步。

·         沒有:繼續下一步。

6.    是否有--replicate-wild-do-table規則?

·         :資料表匹配嗎?

o        :執行查詢並退出。

o        :繼續下一步。

·         沒有:繼續下一步。

7.    是否有--replicate-wild-ignore-table規則?

·         :資料表匹配嗎?

o        :忽視查詢並退出。

o        :繼續下一步。

·         沒有:繼續下一步。

8.    沒有匹配的--replicate-*-table規則。要根據這些規則測試其它資料表嗎?

·         :執行循環。

·         :我們現在已經測試了所有待更新的資料表,結果不能匹配任何規則。是否有--replicate-do-table--replicate-wild-do-table規則?

o        :有「do」規則但不匹配。忽視查詢並退出。

o        沒有:執行查詢並退出。

6.9. 複製FAQ

Q:如果主伺服器正在運行並且不想停止主伺服器,怎樣配置一個從伺服器?

A:有多種方法。如果您在某時間點做過主伺服器備份並且記錄了相應快照的二進制日誌名和偏移量(通過SHOW MASTER STATUS命令的輸出),採用下面的步驟:

1.    確保從伺服器分配了一個唯一的伺服器ID號。

2.    在從伺服器上執行下面的語句,為每個選項填入適當的值:

            mysql> CHANGE MASTER TO

                ->     MASTER_HOST='master_host_name',
                ->     MASTER_USER='master_user_name',
                ->     MASTER_PASSWORD='master_pass',
                ->     MASTER_LOG_FILE='recorded_log_file_name',
              ->     MASTER_LOG_POS=recorded_log_position;

3.    在從伺服器上執行START SLAVE語句。

如果您沒有備份主伺服器,這裡是一個建立備份的快速程式。所有步驟都應該在主伺服器主機上執行。

1.    發出該語句:

     mysql> FLUSH TABLES WITH READ LOCK

2.    仍然加鎖時,執行該命令(或它的變體):

     shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql

3.    發出該語句並且確保記錄了以後用到的輸出:

     mysql>SHOW MASTER STATUS

4.    釋放鎖:

     mysql> UNLOCK TABLES

一個可選擇的方法是,轉儲主伺服器的SQL來代替前面步驟中的二進制複製。要這樣做,您可以在主伺服器上使用mysqldump --master-data以後裝載SQL轉儲到到您的從伺服器。然而,這比進行二進制複製速度慢。

不管您使用這兩種方法中的那一個,當您有一個快照和記錄了日誌名與偏移量時,後來根據說明操作。您可以使用相同的快照建立多個從伺服器。一旦您擁有主伺服器的一個快照,可以等待建立一個從伺服器,只要主伺服器的二進制日誌完整。兩個能夠等待的時間實際的限制是指在主伺服器上保存二進制日誌的可用硬盤空間和從伺服器同步所用的時間。

您也可以使用LOAD DATA FROM MASTER。這是一個方便的語句,它傳輸一個快照到從伺服器並且立即調整日誌名和偏移量。將來,LOAD DATA FROM MASTER將成為建立從伺服器的推薦方法。然而需要注意,它只工作在MyISAM 資料表上並且可能長時間持有讀鎖定。它並不像我們希望的那樣高效率地執行。如果您有大資料表,執行FLUSH TABLES WITH READ LOCK語句後,這時首選方法仍然是在主伺服器上製作二進制快照。

Q:從伺服器需要始終連接到主伺服器嗎?

A:不,不需要。從伺服器可以宕機或中斷連接幾個小時甚至幾天,重新連接後獲得更新訊息。例如,您可以在通過撥號的連結上設置主伺服器/從伺服器關係,其中只是偶爾短時間內進行連接。這意味著,在任何給定時間,從伺服器不能保證與主伺服器同步除非您執行某些特殊的方法。將來,我們將使用選項來阻塞主伺服器直到有一個從伺服器同步。

Q:我怎樣知道從伺服器與主伺服器的最新比較? 換句話說,我怎樣知道從伺服器複製的最後一個查詢的日期?

A:您可以查看SHOW SLAVE STATUS語句的Seconds_Behind_Master列的結果。參見6.3節,「複製實施細節」

當從伺服器SQL線程執行從主伺服器讀取的事件時,它根據事件時間戳修改自己的時間(這是TIMESTAMP能夠很好複製的原因)。在SHOW PROCESSLIST語句輸出的Time列內,為從伺服器SQL線程顯示的秒數是最後一個複製事件的時間戳和從伺服器主機的實際時間之間相差的秒數。您可以使用它來確定最後一個複製事件的日期。注意,如果您的從伺服器與主伺服器連接中斷一個小時,然後重新連接,在SHOW PROCESSLIST結果中,您可以立即看到從伺服器SQL線程的Time值為3600。這可能是因為從伺服器執行的語句是一個一小時之前的。

Q:我怎樣強制主伺服器阻塞更新直到從伺服器同步?

A:使用下面的步驟:

1.    在主伺服器上,執行這些語句:

     mysql> FLUSH TABLES WITH READ LOCK;

     mysql> SHOW MASTER STATUS;

 

記錄SHOW語句的輸出的日誌名和偏移量。這些是複製坐標。

2.    在從伺服器上,發出下面的語句,其中Master_POS_WAIT()函數的參量是前面步驟中的得到的複製坐標值:

     mysql> SELECT MASTER_POS_WAIT('log_name', log_offset);

SELECT語句阻塞直到從伺服器達到指定的日誌檔案和偏移量。此時,從伺服器與主伺服器同步,語句返回。

3.    在主伺服器上,發出下面的語句允許主伺服器重新開始處理更新:

     mysql> UNLOCK TABLES

Q:當設置雙向複製時我應該知道發出那些語句?

AMySQL複製目前不支援主伺服器和從伺服器之間的任何鎖定協議來保證分佈式(跨伺服器)更新的原子性。換句話說,這樣做是可能的:客戶A根據協作-主伺服器1更新,同時,在它傳給協作-主伺服器2之前,客戶B能夠根據協作-主伺服器2更新,這樣客戶A的更新與它在協作-主伺服器1的更新不同。這樣,當客戶A根據協作-主伺服器2更新時,它產生的資料表與在協作-主伺服器1上的不同,即使所有根據協作-主伺服器2的更新已經傳過來。這意味著,在雙向複製關係中,您不應該把兩個伺服器串連在一起,除非您確信任何順序的更新是安全的,或者除非您在客戶端代碼中注意怎樣避免更新順序錯誤。

您還必須認識到從更新角度,雙向複製實際上並不能顯著地提高性能(或者根本不能提高性能)。兩個伺服器都需要做相同數量的更新,如同在一個伺服器做的那樣。唯一的差別是鎖競爭要少,這因為源於另一個伺服器的更新在一個從線程中序列化。即使這個益處可能被網絡延遲抵消。

Q:怎樣通過複製來提高系統的性能?

A:您應將一個伺服器設置為主伺服器並且將所有寫指向該伺服器。然後根據預算配置盡可能多的從伺服器以及棧空間,並且在主伺服器和從伺服器之間分發讀取操作。您也可以用--skip-innodb--skip-bdb--low-priority-updates以及--delay-key-write=ALL選項啟動從伺服器,以便在從伺服器端提高速度。在這種情況下,為了提高速度,從伺服器使用非事務MyISAM資料表來代替InnoDBBDB資料表。

Q:為了使用高性能的複製,我應該在自己的應用程式中怎樣準備客戶端代碼?

A:如果您的代碼中資料庫訪問部分已經正確地模塊化,應該能夠平滑和容易地轉換為在複製步驟中運行的代碼。僅需要更改資料庫訪問執行部分,以便發送所有的寫操作到主伺服器,以及發送讀操作到主伺服器或某個從伺服器。如果您的代碼沒有這個級別,設置一個複製系統以便清除。應先通過下面的函數建立一個包裝庫或模塊:

·         safe_writer_connect()

·         safe_reader_connect()

·         safe_reader_statement()

·         safe_writer_statement()

每個函數名的safe_意味著函數比較小心地處理所有錯誤。您可以使用不同名的函數。重要是對於讀連接、寫連接、讀和寫有一個統一的接口。

然後,您應該轉換客戶端代碼使用包裝庫。剛開始這可能是痛苦和恐慌的過程,但從長遠來看是值得的。使用剛才討論的方法的所有應用程式都能夠利用主伺服器/從伺服器配置的優越性,即使是含有多個從伺服器的配置。代碼非常容易維護,並且新增排錯選項也很容易。您僅需要修改一兩個函數;例如,記錄每個語句執行的時間,或者您的上千個語句中哪個語句發生了錯誤。

如果您已經編寫了許多代碼,您可能想使用replace工具自動進行轉換,該工具隨標準MySQL一起發佈,或可以自己編寫轉換指令。理想情況,您的代碼使用一致的程式轉換風格。否則,可能最好重新編寫代碼,或者至少手工對其進行規則化以使用一致的風格。

QMySQL複製能夠何時和多大程度提高系統性能?

AMySQL複製對於頻繁讀和頻繁寫的系統具有最大好處。理論上,通過使用單個主伺服器/多從伺服器設置,可以通過新增更多的從伺服器來擴充系統,直到用完網絡帶寬,或者您的更新負載已經增長到主伺服器不能處理的點。

在獲得的收益開始吃平之前,為了確定可以有多少從伺服器,以及可以將您的站點的性能提高多少,需要知道查詢模式,並且要通過基準測試並根據經驗確定一個典型的主伺服器和從伺服器中的讀取(每秒鐘讀取量,或者max_reads)吞吐量和寫(max_writes)吞吐量的關係。通過一個假設的帶有複製的系統,本例給出了一個非常簡單的計算結果。

假設系統負載包括10%的寫和90%的讀取,並且我們通過基準測試確定max_reads1200 2 × max_writes。換句話說,如果沒有寫操作,系統每秒可以進行1,200次讀取操作,平均寫操作是平均讀操作所用時間的兩倍,並且關係是線性的。我們假定主伺服器和每個從伺服器具有相同的性能,並且我們有一個主伺服器和N個從伺服器。那麼,對於每個伺服器(主伺服器或從伺服器),我們有:

reads = 1200 2 × writes

reads = 9 × writes / (N + 1) (讀取是分離的, 但是寫入所有伺服器)

9 × writes / (N + 1) + 2 × writes = 1200

writes = 1200 / (2 + 9/(N+1))

最後的等式表明了N個從伺服器的最大寫操作數,假設最大可能的讀取速率是每分鐘1,200次,讀操作與寫操作的比率是9

如上分析可以得到下面的結論:

·         如果N = 0(這表明沒有複製),系統每秒可以處理大約1200/11 = 109個寫操作。

·         如果N = 1,每秒得到184個寫操作。

·         如果N = 8,每秒得到400個寫操作。

·         如果N = 17,每秒得到480個寫操作。

·         最後,當 N 趨於無窮大(以及我們預算的負無窮大)時,可以得到非常接近每秒600個寫操作,系統吞吐量增加將近5.5倍。然而,如果只用8個伺服器,增加接近4倍。

請注意,這些計算假設網絡帶寬無窮大並忽略掉了其它一些因素,那些因素可能對系統產生重要的影響。在許多情況下,不能執行與剛才類似的計算,即如果新增N台複製從伺服器,應該準確預報系統將發生哪些影響。回答下面的問題應能夠幫助您確定複製是否和在多大程度上能夠提高系統的性能:

·         系統上的讀取/寫比例是什麼?

·         如果減少讀取操作,一個伺服器可以多處理多少寫負載?

·         網絡帶寬可滿足多少從伺服器的需求?

Q:如何使用複製來提供冗余/高可用性?

A:利用目前的可用特性,必須設置一個主伺服器和一個從伺服器(或多個從伺服器),以及寫一個指令來監視主伺服器是否啟動。如果主伺服器失敗,通知應用程式和從伺服器切換主伺服器。下面是一些建議:

·         告知從伺服器更改其主伺服器,使用CHANGE MASTER TO語句。

·         通知應用程式主伺服器位置的一個很好的方法是對主伺服器提供動態DNS入口。用bind可以使用nsupdate動態更新DNS

·         應該用--logs-bin選項而不用 --logs-slave-updates選項運行從伺服器。這樣,一旦您在其它從伺服器上發出STOP SLAVE; RESET MASTER, 以及CHANGE MASTER TO語句該從伺服器可以切換為主伺服器。例如,假設有下面的設置:

·                       WC
·                        \
·                         v
·                 WC----> M
·                       / | \
·                      /  |  \
·                     v   v   v
·                    S1   S2  S3

M代資料表主伺服器,S代資料表從伺服器,WC代資料表發出資料庫寫和讀取操作的客戶;只發出資料庫讀取操作的客戶沒有給出,因為它們不需要切換。S1S2以及S3是從伺服器,用--logs-bin選項而沒有用--logs-slave-updates運行。因為從伺服器收到的主伺服器的更新沒有記錄在二進制日誌中,除非指定 --logs-slave-updates選項,每個從伺服器上的二進制日誌是空的。如果因為某些原因M 變得不可用,您可以選取一個從伺服器變為新的主伺服器。例如,如果您選取了S1,所有WC應該重新指向S1S2,並且S3然後應從S1複製

確保所有從伺服器已經處理了中繼日誌中的所有語句。在每個從伺服器上,發出STOP SLAVE IO_THREAD語句,然後檢查SHOW PROCESSLIST語句的輸出,直到您看到Has read all relay log。當所有從伺服器都執行完這些,它們可以被重新配置為一個新的設置。在被提升為主伺服器的從伺服器S1上,發出STOP SLAVERESET MASTER語句。

在其它從伺服器S2S3,使用STOP SLAVECHANGE MASTER TO MASTER_HOST='S1'(其中'S1'資料表示S1實際的主機名)。為CHANGE MASTER新增關於從S2S3如何連接到S1所有訊息(userpasswordport)。在CHANGE MASTER命令中,不需要指定從其讀取的S1的二進制日誌名或二進制日誌位置:我們知道它是第1個二進制日誌,位置是4,這是CHANGE MASTER命令的預設值。最後,在S2S3使用START SLAVE 命令。

然後,指示所有WC 把它們的語句指向S1此後,WC發出的所有發送到S1更新語句被寫入S1二進制日誌,S1則包含M死掉之後的發送到 S1的每一個更新語句。

結果是下面的配置:

       WC
      /
      |
 WC   |  M(unavailable)
  \   |
   \  |
    v v
     S1<--S2  S3
      ^       |
      +-------+

M重新啟動後,您必須在M發出相同的CHANGE MASTER語句,與在S2S3上發出的語句一樣,以便M變為S1從伺服器並且恢復在它宕機後丟失的所有WC寫操作。要把 M 再次作為主伺服器(例如,因為它是功能最強的機器),使用前面的步驟,好像S1不可用並且M變為一個新的主伺服器一樣。在這個過程中,在S1S2以及S3作為M從伺服器之前,不要忘記在M運行RESET MASTER。否則,它們可能拾取M變得不可用之前的舊WC寫操作。

我們目前正在MySQL集成自動主伺服器選擇系統,但在準備好之前,您必須建立自己的監控工具。

6.10. 複製故障診斷與排除

如果您遵從了上述說明,複製設置仍然不工作,首先檢查下面各項:

·         檢查錯誤日誌的消息。許多用戶遇到問題後沒有及時地這樣做而浪費了時間。

·         主伺服器記錄到了二進制日誌?用SHOW MASTER STATUS檢查。如果已經記錄,Position應為非零。如果沒有記錄,確認正用log-binserver-id選項運行主伺服器。

·         是否從伺服器在運行?使用SHOWSHOW SLAVE STATUS檢查是否slave_IO_Runningslave_SQL_Running的值均為Yes。如果不是,驗證當啟動從伺服器時使用的選項。

·         如果從伺服器正在運行,建立了與主伺服器的連接嗎?使用SHOW PROCESSLIST,找出I/OSQL線程並檢查它們的State列看它們如何顯示。參見6.3節,「複製實施細節」。如果I/O線程狀態為Connecting to master,驗證主伺服器上複製用戶的權限、主伺服器主機名、DNS設置,是否主伺服器真正在運行,以及是否可以從從屬伺服器訪問。

·         如果從伺服器以前在運行但是現在已經停止,原因通常是在主伺服器上成功的部分語句在從伺服器上失敗了。如果您正確快照了主伺服器,並且從來沒有不通過伺服器線程修改從伺服器上的數據,這種現象不應發生。如果發生,應為一個bug或您遇到了一個6.7節,「複製特性和已知問題」 描述的已知的複製限制。如果是一個bug,參見6.11節,「通報複製問題」查閱如何通報的說明。

·         如果某個在主伺服器上成功的語句拒絕在從伺服器上運行,並且不能執行完全的資料庫重新同步(即刪除從伺服器的資料庫並從主伺服器複製新的快照),嘗試:

1.    確定是否從伺服器的資料表與主伺服器的不同。盡力瞭解發生的原因。然後讓從伺服器的資料表與主伺服器的一樣並運行START SLAVE

2.    如果前面的步驟不工作或不適合,盡力瞭解手動更新是否安全(如果需要),然後忽視來自主伺服器的下一個語句。

3.    如果您確定可以跳過來自主伺服器的下一個語句,執行下面的語句:

4.                  mysql> SET GLOBAL SQL_slave_SKIP_COUNTER = n
5.                  mysql> START SLAVE

如果來自主伺服器的下一個語句不使用AUTO_INCREMENTLAST_INSERT_ID()n 值應為1。否則,值應為2。使用AUTO_INCREMENTLAST_INSERT_ID()的語句使用值2的原因是它們從主伺服器的二進制日誌中取兩個事件。

6.    如果您確保從伺服器啟動時完好地與主伺服器同步,並且沒有更新從伺服器線程之外的資料表,則大概詫異是由於bug。如果您正運行最近的版本,請通報該問題。如果您正運行舊版本MySQL,盡力升級到最新的產品版本。

6.11. 通報複製問題

如果您確定沒有用戶錯誤,但複製仍然不工作或不穩定,則是向我們發送bug通報的時候了。我們需要盡可能從您那兒獲得更多的訊息已跟蹤bug。請花一些時間和努力編寫一份好的bug通報。

如果您有一個重複的測試案例來說明bug,請把它輸入我們的bug資料庫,位置為http://bugs.mysql.com/。如果您有一個「phantom」問題(不能按照期望進行複製),則使用下面的程式:

1.    確認未包括用戶錯誤。例如,如果您不用從伺服器線程來更新從伺服器,數據將不同步,並且會遇到唯一的鍵值違背更新。在這種情況下,從伺服器線程停止並等待您手動清理資料表使它們同步。這不是複製問題。這是一個外部接口問題造成複製失敗。

2.    --logs-slave-updates--logs-bin選項運行從伺服器。這些選項使從伺服器將從主伺服器接收的更新記入自己的二進制日誌。

3.    重新設置複製狀態之前保存所有的證據。如果我們沒有訊息或只有粗略的訊息,則難以或不可能跟蹤問題。應搜集的證據為:

·         所有主伺服器的二進制日誌

·         所有從伺服器的二進制日誌

·         您發現問題時主伺服器的SHOW MASTER STATUS的輸出

·         您發現問題時主伺服器的SHOW SLAVE STATUS的輸出

·         主伺服器和從伺服器的錯誤日誌

4.    使用mysqlbinlog檢查二進制日誌。下面命令應有助於發現有問題的查詢,例如:

5.            shell> mysqlbinlog -j pos_from_slave_status \
6.                       /path/to/log_from_slave_status | head

搜集了問題的證據後,首先作為一個測試案例隔離開。然後將問題輸入我們的bug資料庫,位置為http://bugs.mysql.com/,應提供盡可能多的訊息。

6.12. 多伺服器複製中的Auto-Increment

當將多個伺服器配置為複製主伺服器時,使用auto_increment時應採取特殊步驟以防止鍵值衝突,否則插入行時多個主伺服器會試圖使用相同的auto_increment值。

伺服器變數auto_increment_incrementauto_increment_offset可以幫助協調多主伺服器複製和AUTO_INCREMENT列。每個變數有一個預設的(並且是最小的)1,最大值為65,535

將這些變數設置為非衝突的值,當在同一個資料表主插入新行時,多主伺服器配置主的伺服器將不會與AUTO_INCREMENT值衝突。

這兩個變數這樣影響AUTO_INCREMENT列:

·         auto_increment_increment控制列值增加的間隔。例如:

·                mysql> SHOW VARIABLES LIKE 'auto_inc%';
·                +--------------------------+-------+
·                | Variable_name            | Value |
·                +--------------------------+-------+
·                | auto_increment_increment | 1     |
·                | auto_increment_offset    | 1     |
·                +--------------------------+-------+
·                2 rows in set (0.00 sec)
·                 
·                mysql> CREATE TABLE autoinc1 (col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
·                Query OK, 0 rows affected (0.04 sec)
·                 
·                mysql> SET @auto_increment_increment=10;
·                Query OK, 0 rows affected (0.00 sec)
·                 
·                mysql> SHOW VARIABLES LIKE 'auto_inc%';
·                +--------------------------+-------+
·                | Variable_name            | Value |
·                +--------------------------+-------+
·                | auto_increment_increment | 10    |
·                | auto_increment_offset    | 1     |
·                +--------------------------+-------+
·                2 rows in set (0.01 sec)
·                 
·                mysql> INSERT INTO autoinc1 VALUES (NULL), (NULL), (NULL), (NULL);
·                Query OK, 4 rows affected (0.00 sec)
·                Records: 4  Duplicates: 0  Warnings: 0
·                 
·                mysql> SELECT col FROM autoinc1;
·                +-----+
·                | col |
·                +-----+
·                |   1 |
·                |  11 |
·                |  21 |
·                |  31 |
·                +-----+
·                4 rows in set (0.00 sec)

(這裡註明如何使用SHOW VARIABLES以獲得這些變數的當前值)

·         auto_increment_offset確定AUTO_INCREMENT列值的起點。影響到在複製設置主可以有多少主伺服器(例如將該值設置為10資料表示設置可以支援10個伺服器)

考慮下面的命令,假定在前面所示示範中的相同的會話中執行這些命令:

mysql> SET @auto_increment_offset=5;
Query OK, 0 rows affected (0.00 sec)
 
mysql> SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 10    |
| auto_increment_offset    | 5     |
+--------------------------+-------+
2 rows in set (0.00 sec)
 
mysql> CREATE TABLE autoinc2 (col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
Query OK, 0 rows affected (0.06 sec)
 
mysql> INSERT INTO autoinc2 VALUES (NULL), (NULL), (NULL), (NULL);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0
 
mysql> SELECT col FROM autoinc2;
+-----+
| col |
+-----+
|   5 |
|  15 |
|  25 |
|  35 |
+-----+
4 rows in set (0.02 sec)

詳細訊息參見5.3.3節,「伺服器系統變數」


這是MySQL參考手冊的翻譯版本,關於MySQL參考手冊,請訪問dev.mysql.com。 原始參考手冊為英文版,與英文版參考手冊相比,本翻譯版可能不是最新的。