6. MySql中的複製

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。 原始參考手冊爲英文版,與英文版參考手冊相比,本翻譯版可能不是最新的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章