?
This document uses PHP Chinese website manual Release
目錄
本章描述了MySQL提供的各種復(fù)制特性。引入了復(fù)制概念,顯示如何設(shè)置復(fù)制服務(wù)器和服務(wù)以指導(dǎo)相應(yīng)的復(fù)制選項(xiàng)。還提供了FAQ(以及答案) 列表,以及解決復(fù)制問(wèn)題的排錯(cuò)建議。
關(guān)于復(fù)制相關(guān)的SQL語(yǔ)句的語(yǔ)法描述,參見13.6節(jié),“復(fù)制語(yǔ)句”。
我們建議你經(jīng)常訪問(wèn)我們的網(wǎng)址http://www.mysql.com,并檢查對(duì)本章的修改。復(fù)制在不斷地得到改進(jìn),我們用最新的信息定期更新本手冊(cè)。
MySQL支持單向、異步復(fù)制,復(fù)制過(guò)程中一個(gè)服務(wù)器充當(dāng)主服務(wù)器,而一個(gè)或多個(gè)其它服務(wù)器充當(dāng)從服務(wù)器。(這與同步復(fù)制可以進(jìn)行對(duì)比,同步復(fù)制是MySQL簇的一個(gè)特征—參見第17章:MySQL簇)。主服務(wù)器將更新寫入二進(jìn)制日志文件,并維護(hù)文件的一個(gè)索引以跟蹤日志循環(huán)。這些日志可以記錄發(fā)送到從服務(wù)器的更新。當(dāng)一個(gè)從服務(wù)器連接主服務(wù)器時(shí),它通知主服務(wù)器從服務(wù)器在日志中讀取的最后一次成功更新的位置。從服務(wù)器接收從那時(shí)起發(fā)生的任何更新,然后封鎖并等待主服務(wù)器通知新的更新。
如果你想要設(shè)置鏈?zhǔn)綇?fù)制服務(wù)器,從服務(wù)器本身也可以充當(dāng)主服務(wù)器。
請(qǐng)注意當(dāng)你進(jìn)行復(fù)制時(shí),所有對(duì)復(fù)制中的表的更新必須在主服務(wù)器上進(jìn)行。否則,你必須要小心,以避免用戶對(duì)主服務(wù)器上的表進(jìn)行的更新與對(duì)從服務(wù)器上的表所進(jìn)行的更新之間的沖突。
單向復(fù)制有利于健壯性、速度和系統(tǒng)管理:
·???????? 主服務(wù)器/從服務(wù)器設(shè)置增加了健壯性。主服務(wù)器出現(xiàn)問(wèn)題時(shí),你可以切換到從服務(wù)器作為備份。
·???????? 通過(guò)在主服務(wù)器和從服務(wù)器之間切分處理客戶查詢的負(fù)荷,可以得到更好的客戶響應(yīng)時(shí)間。SELECT查詢可以發(fā)送到從服務(wù)器以降低主服務(wù)器的查詢處理負(fù)荷。但修改數(shù)據(jù)的語(yǔ)句仍然應(yīng)發(fā)送到主服務(wù)器,以便主服務(wù)器和從服務(wù)器保持同步。如果非更新查詢?yōu)橹?,該?fù)載均衡策略很有效,但一般是更新查詢。
·???????? 使用復(fù)制的另一個(gè)好處是可以使用一個(gè)從服務(wù)器執(zhí)行備份,而不會(huì)干擾主服務(wù)器。在備份過(guò)程中主服務(wù)器可以繼續(xù)處理更新。參見5.9.1節(jié),“數(shù)據(jù)庫(kù)備份”。
MySQL復(fù)制基于主服務(wù)器在二進(jìn)制日志中跟蹤所有對(duì)數(shù)據(jù)庫(kù)的更改(更新、刪除等等)。因此,要進(jìn)行復(fù)制,必須在主服務(wù)器上啟用二進(jìn)制日志。參見5.11.3節(jié),“二進(jìn)制日志”。
每個(gè)從服務(wù)器從主服務(wù)器接收主服務(wù)器已經(jīng)記錄到其二進(jìn)制日志的保存的更新,以便從服務(wù)器可以對(duì)其數(shù)據(jù)拷貝執(zhí)行相同的更新。
認(rèn)識(shí)到二進(jìn)制日志只是一個(gè)從啟用二進(jìn)制日志的固定時(shí)間點(diǎn)開始的記錄非常重要。任何設(shè)置的從服務(wù)器需要主服務(wù)器上的在主服務(wù)器上啟用二進(jìn)制日志時(shí)的數(shù)據(jù)庫(kù)拷貝。如果啟動(dòng)從服務(wù)器時(shí),其數(shù)據(jù)庫(kù)與主服務(wù)器上的啟動(dòng)二進(jìn)制日志時(shí)的狀態(tài)不相同,從服務(wù)器很可能失敗。
將主服務(wù)器的數(shù)據(jù)拷貝到從服務(wù)器的一個(gè)途徑是使用LOAD DATA FROM MASTER語(yǔ)句。請(qǐng)注意LOAD DATA FROM MASTER目前只在所有表使用MyISAM存儲(chǔ)引擎的主服務(wù)器上工作。并且,該語(yǔ)句將獲得全局讀鎖定,因此當(dāng)表正復(fù)制到從服務(wù)器上時(shí),不可能在主服務(wù)器上進(jìn)行更新。當(dāng)我們執(zhí)行表的無(wú)鎖熱備份時(shí),則不再需要全局讀鎖定。
由于這些限制,我們建議只有主服務(wù)器上的數(shù)據(jù)集相對(duì)較小,或者主服務(wù)器上延遲讀鎖定已經(jīng)被接受,才可以使用LOAD DATA FROM MASTER。而LOAD DATA FROM MASTER的實(shí)際速度隨系統(tǒng)的不同而不同,對(duì)于執(zhí)行時(shí)間,最好的規(guī)則是每1MB的數(shù)據(jù)用1秒鐘。這是一個(gè)粗略的估計(jì),但你會(huì)發(fā)現(xiàn)如果主服務(wù)器和從服務(wù)器的性能上等價(jià)于700MHz Pentium CPU,通過(guò)100Mbps的網(wǎng)絡(luò)進(jìn)行連接,則該估計(jì)相當(dāng)準(zhǔn)確。
從服務(wù)器設(shè)置為復(fù)制主服務(wù)器的數(shù)據(jù)后,它連接主服務(wù)器并等待更新過(guò)程。如果主服務(wù)器失敗,或者從服務(wù)器失去與主服務(wù)器之間的連接,從服務(wù)器保持定期嘗試連接,直到它能夠繼續(xù)幀聽更新。由--master-connect-retry選項(xiàng)控制重試間隔。 默認(rèn)為60秒。
每個(gè)從服務(wù)器跟蹤復(fù)制時(shí)間。主服務(wù)器不知道有多少個(gè)從服務(wù)器或在某一時(shí)刻有哪些被更新了。
MySQL使用3個(gè)線程來(lái)執(zhí)行復(fù)制功能(其中1個(gè)在主服務(wù)器上,另兩個(gè)在從服務(wù)器上。當(dāng)發(fā)出START SLAVE時(shí),從服務(wù)器創(chuàng)建一個(gè)I/O線程,以連接主服務(wù)器并讓它發(fā)送記錄在其二進(jìn)制日志中的語(yǔ)句。主服務(wù)器創(chuàng)建一個(gè)線程將二進(jìn)制日志中的內(nèi)容發(fā)送到從服務(wù)器。該線程可以識(shí)別為主服務(wù)器上SHOW PROCESSLIST的輸出中的Binlog Dump線程。從服務(wù)器I/O線程讀取主服務(wù)器Binlog Dump線程發(fā)送的內(nèi)容并將該數(shù)據(jù)拷貝到從服務(wù)器數(shù)據(jù)目錄中的本地文件中,即中繼日志。第3個(gè)線程是SQL線程,是從服務(wù)器創(chuàng)建用于讀取中繼日志并執(zhí)行日志中包含的更新。
在前面的描述中,每個(gè)從服務(wù)器有3個(gè)線程。有多個(gè)從服務(wù)器的主服務(wù)器創(chuàng)建為每個(gè)當(dāng)前連接的從服務(wù)器創(chuàng)建一個(gè)線程;每個(gè)從服務(wù)器有自己的I/O和SQL線程。
這樣讀取和執(zhí)行語(yǔ)句被分成兩個(gè)獨(dú)立的任務(wù)。如果語(yǔ)句執(zhí)行較慢則語(yǔ)句讀取任務(wù)沒(méi)有慢下來(lái)。例如,如果從服務(wù)器有一段時(shí)間沒(méi)有運(yùn)行了,當(dāng)從服務(wù)器啟動(dòng)時(shí),其I/O線程可以很快地從主服務(wù)器索取所有二進(jìn)制日志內(nèi)容,即使SQL線程遠(yuǎn)遠(yuǎn)滯后。如果從服務(wù)器在SQL線程執(zhí)行完所有索取的語(yǔ)句前停止,I/O 線程至少已經(jīng)索取了所有內(nèi)容,以便語(yǔ)句的安全拷貝保存到本地從服務(wù)器的中繼日志中,供從服務(wù)器下次啟動(dòng)時(shí)執(zhí)行。這樣允許清空主服務(wù)器上的二進(jìn)制日志,因?yàn)椴辉傩枰群驈姆?wù)器來(lái)索取其內(nèi)容。
SHOW PROCESSLIST語(yǔ)句可以提供在主服務(wù)器上和從服務(wù)器上發(fā)生的關(guān)于復(fù)制的信息。
下面的例子說(shuō)明了這3個(gè)線程在SHOW PROCESSLIST中的顯示。
在主服務(wù)器上,SHOW PROCESSLIST的輸出看上去應(yīng)為:
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是一個(gè)連接從服務(wù)器的復(fù)制線程。該信息表示所有主要更新已經(jīng)被發(fā)送到從服務(wù)器,主服務(wù)器正等待更多的更新出現(xiàn)。
在從服務(wù)器上,SHOW PROCESSLIST的輸出看上去應(yīng)為:
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是同主服務(wù)器通信的I/O線程,線程11是處理保存在中繼日志中的更新的SQL線程。SHOW PROCESSLIST運(yùn)行時(shí),兩個(gè)線程均空閑,等待其它更新。
請(qǐng)注意Time列的值可以顯示從服務(wù)器比主服務(wù)器滯后多長(zhǎng)時(shí)間。參見6.9節(jié),“復(fù)制FAQ”。
·???????? Sending binlog event to slave
二進(jìn)制日志由各種事件組成,一個(gè)事件通常為一個(gè)更新加一些其它信息。線程已經(jīng)從二進(jìn)制日志讀取了一個(gè)事件并且正將它發(fā)送到從服務(wù)器。
·???????? Finished reading one binlog; switching to next binlog
線程已經(jīng)讀完二進(jìn)制日志文件并且正打開下一個(gè)要發(fā)送到從服務(wù)器的日志文件。
·???????? Has sent all binlog to slave; waiting for binlog to be updated
線程已經(jīng)從二進(jìn)制日志讀取所有主要的更新并已經(jīng)發(fā)送到了從服務(wù)器。線程現(xiàn)在正空閑,等待由主服務(wù)器上新的更新導(dǎo)致的出現(xiàn)在二進(jìn)制日志中的新事件。
·???????? Waiting to finalize termination
線程停止時(shí)發(fā)生的一個(gè)很簡(jiǎn)單的狀態(tài)。
·???????? Connecting to master
線程正試圖連接主服務(wù)器。
·???????? Checking master version
建立同主服務(wù)器之間的連接后立即臨時(shí)出現(xiàn)的狀態(tài)。
·???????? Registering slave on master
建立同主服務(wù)器之間的連接后立即臨時(shí)出現(xiàn)的狀態(tài)。
·???????? Requesting binlog dump
建立同主服務(wù)器之間的連接后立即臨時(shí)出現(xiàn)的狀態(tài)。線程向主服務(wù)器發(fā)送一條請(qǐng)求,索取從請(qǐng)求的二進(jìn)制日志文件名和位置開始的二進(jìn)制日志的內(nèi)容。
·???????? Waiting to reconnect after a failed binlog dump request
如果二進(jìn)制日志轉(zhuǎn)儲(chǔ)請(qǐng)求失敗(由于沒(méi)有連接),線程進(jìn)入睡眠狀態(tài),然后定期嘗試重新連接??梢允褂?span>--master-connect-retry選項(xiàng)指定重試之間的間隔。
·???????? Reconnecting after a failed binlog dump request
線程正嘗試重新連接主服務(wù)器。
·???????? Waiting for master to send event
線程已經(jīng)連接上主服務(wù)器,正等待二進(jìn)制日志事件到達(dá)。如果主服務(wù)器正空閑,會(huì)持續(xù)較長(zhǎng)的時(shí)間。如果等待持續(xù)slave_read_timeout秒,則發(fā)生超時(shí)。此時(shí),線程認(rèn)為連接被中斷并企圖重新連接。
·???????? Queueing master event to the relay log
線程已經(jīng)讀取一個(gè)事件,正將它復(fù)制到中繼日志供SQL線程來(lái)處理。
·???????? Waiting to reconnect after a failed master event read
讀取時(shí)(由于沒(méi)有連接)出現(xiàn)錯(cuò)誤。線程企圖重新連接前將睡眠master-connect-retry秒。
·???????? Reconnecting after a failed master event read
線程正嘗試重新連接主服務(wù)器。當(dāng)連接重新建立后,狀態(tài)變?yōu)?span>Waiting for master to send event。
·???????? Waiting for the slave SQL thread to free enough relay log space
正使用一個(gè)非零relay_log_space_limit值,中繼日志已經(jīng)增長(zhǎng)到其組合大小超過(guò)該值。I/O線程正等待直到SQL線程處理中繼日志內(nèi)容并刪除部分中繼日志文件來(lái)釋放足夠的空間。
·???????? Waiting for slave mutex on exit
線程停止時(shí)發(fā)生的一個(gè)很簡(jiǎn)單的狀態(tài)。
·???????? Reading event from the relay log
線程已經(jīng)從中繼日志讀取一個(gè)事件,可以對(duì)事件進(jìn)行處理了。
·???????? Has read all relay log; waiting for the slave I/O thread to update it
線程已經(jīng)處理了中繼日志文件中的所有事件,現(xiàn)在正等待I/O線程將新事件寫入中繼日志。
·???????? Waiting for slave mutex on exit
線程停止時(shí)發(fā)生的一個(gè)很簡(jiǎn)單的狀態(tài)。
I/O線程的State列也可以顯示語(yǔ)句的文本。這說(shuō)明線程已經(jīng)從中繼日志讀取了一個(gè)事件,從中提取了語(yǔ)句,并且正在執(zhí)行語(yǔ)句。
默認(rèn)情況,中繼日志使用host_name-relay-bin.nnnnnn形式的文件名,其中host_name是從服務(wù)器主機(jī)名,nnnnnn是序列號(hào)。用連續(xù)序列號(hào)來(lái)創(chuàng)建連續(xù)中繼日志文件,從000001開始。從服務(wù)器跟蹤索引文件中目前正使用的中繼日志。 默認(rèn)中繼日志索引文件名為host_name-relay-bin.index。默認(rèn)情況,在從服務(wù)器的數(shù)據(jù)目錄中創(chuàng)建這些文件??梢杂?span>--relay-log和--relay-log-index服務(wù)器選項(xiàng)覆蓋 默認(rèn)文件名。參見6.8節(jié),“復(fù)制啟動(dòng)選項(xiàng)”。
中繼日志與二進(jìn)制日志的格式相同,并且可以用mysqlbinlog讀取。SQL線程執(zhí)行完中繼日志中的所有事件并且不再需要之后,立即自動(dòng)刪除它。沒(méi)有直接的刪除中繼日志的機(jī)制,因?yàn)?span>SQL線程可以負(fù)責(zé)完成。然而,FLUSH LOGS可以循環(huán)中繼日志,當(dāng)SQL線程刪除日志時(shí)會(huì)有影響。
在下面的條件下創(chuàng)建新的中繼日志:
·???????? 每次I/O線程啟動(dòng)時(shí)創(chuàng)建一個(gè)新的中繼日志。
·???????? 當(dāng)日志被刷新時(shí);例如,用FLUSH LOGS或mysqladmin flush-logs。
·???????? 當(dāng)當(dāng)前的中繼日志文件變得太大時(shí)。“太大”含義的確定方法:
o??????? max_relay_log_size,如果max_relay_log_size > 0
o??????? max_binlog_size,如果max_relay_log_size = 0
從屬?gòu)?fù)制服務(wù)器在數(shù)據(jù)目錄中另外創(chuàng)建兩個(gè)小文件。這些狀態(tài)文件默認(rèn)名為主master.info和relay-log.info。它們包含SHOW SLAVE STATUS語(yǔ)句的輸出所顯示的信息(關(guān)于該語(yǔ)句的描述參見13.6.2節(jié),“用于控制從服務(wù)器的SQL語(yǔ)句”)。狀態(tài)文件保存在硬盤上,從服務(wù)器關(guān)閉時(shí)不會(huì)丟失。下次從服務(wù)器啟動(dòng)時(shí),讀取這些文件以確定它已經(jīng)從主服務(wù)器讀取了多少二進(jìn)制日志,以及處理自己的中繼日志的程度。
由I/O線程更新master.info文件。文件中的行和SHOW SLAVE STATUS顯示的列的對(duì)應(yīng)關(guān)系為:
行 |
描述 |
1 |
文件中的行號(hào) |
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顯示的列的對(duì)應(yīng)關(guān)系為:
行 |
描述 |
1 |
Relay_Log_File |
2 |
Relay_Log_Pos |
3 |
Relay_Master_Log_File |
4 |
Exec_Master_Log_Pos |
當(dāng)備份從服務(wù)器的數(shù)據(jù)時(shí),你還應(yīng)備份這兩個(gè)小文件以及中繼日志文件。它們用來(lái)在恢復(fù)從服務(wù)器的數(shù)據(jù)后繼續(xù)進(jìn)行復(fù)制。如果丟失了中繼日志但仍然有relay-log.info文件,你可以通過(guò)檢查該文件來(lái)確定SQL線程已經(jīng)執(zhí)行的主服務(wù)器中二進(jìn)制日志的程度。然后可以用Master_Log_File和Master_LOG_POS選項(xiàng)執(zhí)行CHANGE MASTER TO來(lái)告訴從服務(wù)器重新從該點(diǎn)讀取二進(jìn)制日志。當(dāng)然,要求二進(jìn)制日志仍然在主服務(wù)器上。
如果從服務(wù)器正復(fù)制LOAD DATA INFILE語(yǔ)句,你應(yīng)也備份該目錄內(nèi)從服務(wù)器用于該目的的任何SQL_LOAD-*文件。從服務(wù)器需要這些文件繼續(xù)復(fù)制任何中斷的LOAD DATA INFILE操作。用--slave-load-tmpdir選項(xiàng)來(lái)指定目錄的位置。如果未指定, 默認(rèn)值為tmpdir變量的值。
這里簡(jiǎn)單描述了如何為你當(dāng)前的MySQL服務(wù)器設(shè)置完整的復(fù)制。假設(shè)你想要復(fù)制主服務(wù)器上的所有數(shù)據(jù)庫(kù),并且還沒(méi)有配置的復(fù)制。你需要關(guān)閉主服務(wù)器來(lái)完成下面所列的步驟。
下面的程序針對(duì)設(shè)置一個(gè)從服務(wù)器,你可以用來(lái)設(shè)置多個(gè)從服務(wù)器。
雖然該方法是設(shè)置從服務(wù)器的最直接的途徑,它并不是唯一的一個(gè)。例如,如果你有一個(gè)主服務(wù)器的數(shù)據(jù)快照,并且主服務(wù)器已經(jīng)設(shè)置了服務(wù)器ID,啟用了二進(jìn)制日志,不需要關(guān)閉主服務(wù)器或停止對(duì)它的更新也可以設(shè)置從服務(wù)器。詳情請(qǐng)參見6.9節(jié),“復(fù)制FAQ”。
如果想要管理MySQL復(fù)制設(shè)置,我們建議你通讀本章,并嘗試13.6.1節(jié),“用于控制主服務(wù)器的SQL語(yǔ)句”和13.6.2節(jié),“用于控制從服務(wù)器的SQL語(yǔ)句”中的所有語(yǔ)句。還應(yīng)熟悉6.8節(jié),“復(fù)制啟動(dòng)選項(xiàng)”中描述的復(fù)制啟動(dòng)選項(xiàng)。
注釋:該程序和后面章節(jié)所示的復(fù)制SQL語(yǔ)句需要SUPER權(quán)限。
1.??? 確保在服務(wù)器和從服務(wù)器上安裝的MySQL版本與6.5節(jié),“不同MySQL版本之間的復(fù)制兼容性”所示的表兼容。理想情況,應(yīng)在主服務(wù)器和從服務(wù)器上使用最近版本的MySQL。
請(qǐng)先證實(shí)問(wèn)題不是出現(xiàn)在最新的MySQL版本中再通報(bào)bug。
2.??? 在主服務(wù)器上為服務(wù)器設(shè)置一個(gè)連接賬戶。該賬戶必須授予REPLICATION SLAVE權(quán)限。如果賬戶僅用于復(fù)制(推薦這樣做),則不需要再授予任何其它權(quán)限。(關(guān)于設(shè)置用戶 賬戶和權(quán)限的信息,參見5.8節(jié),“MySQL用戶賬戶管理”)。
假定你的域?yàn)?span>mydomain.com,想要?jiǎng)?chuàng)建用戶名為repl的一個(gè)賬戶,從服務(wù)器可以使用該賬戶從你的域內(nèi)的任何主機(jī)使用密碼slavepass來(lái)訪問(wèn)主服務(wù)器。要?jiǎng)?chuàng)建該 賬戶,可使用GRANT語(yǔ)句:
mysql> GRANT REPLICATION SLAVE ON *.*
??? -> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
如果你計(jì)劃從從屬服務(wù)器主機(jī)使用LOAD TABLE FROM MASTER或LOAD DATA FROM MASTER語(yǔ)句,你需要授予該賬戶其它權(quán)限:
·???????? 授予賬戶SUPER和RELOAD全局權(quán)限。
·???????? 為所有想要裝載的表授予SELECT權(quán)限。任何該 賬戶不能SELECT的主服務(wù)器上的表被LOAD DATA FROM MASTER忽略掉。
3.??? 執(zhí)行FLUSH TABLES WITH READ LOCK語(yǔ)句清空所有表和塊寫入語(yǔ)句:
4.??????????? mysql> FLUSH TABLES WITH READ LOCK;
對(duì)于InnoDB表,請(qǐng)注意:FLUSH TABLES WITH READ LOCK還鎖定COMMIT操作。當(dāng)獲得全局讀鎖定后,可以開始InnoDB表的文件系統(tǒng)快照??煺詹荒鼙WC內(nèi)部(在InnoDB存儲(chǔ)引擎內(nèi)部)一致性(因?yàn)?span>InnoDB緩存沒(méi)有刷新),但并不需要關(guān)心該問(wèn)題,因?yàn)?span>InnoDB可以在啟動(dòng)時(shí)解決該問(wèn)題并給出一致的結(jié)果。這說(shuō)明InnoDB在啟動(dòng)快照時(shí)可以進(jìn)行崩潰恢復(fù),而不會(huì)破壞。然而,當(dāng)保證一致的InnoDB表快照時(shí),還沒(méi)有途徑來(lái)停止MySQL服務(wù)器。
讓客戶程序保持運(yùn)行,發(fā)出FLUSH TABLES語(yǔ)句讓讀鎖定保持有效。(如果退出客戶程序,鎖被釋放)。然后對(duì)主服務(wù)器上的數(shù)據(jù)進(jìn)行快照。
創(chuàng)建快照最簡(jiǎn)單的途徑是使用歸檔程序?qū)χ鞣?wù)器上的數(shù)據(jù)目錄中的數(shù)據(jù)庫(kù)進(jìn)行二進(jìn)制備份。例如,在Unix中使用tar,或者在Windows中使用PowerArchiver、WinRAR、WinZip或者類似的軟件。要使用tar來(lái)創(chuàng)建包括所有數(shù)據(jù)庫(kù)的歸檔文件,進(jìn)入主服務(wù)器的數(shù)據(jù)目錄,然后執(zhí)行命令:
shell> tar -cvf /tmp/mysql-snapshot.tar .
如果你想讓歸檔只包括this_db數(shù)據(jù)庫(kù),應(yīng)使用命令:
shell> tar -cvf /tmp/mysql-snapshot.tar ./this_db
然后將歸檔文件復(fù)制到從服務(wù)器主機(jī)的/tmp目錄。在該機(jī)器上,進(jìn)入從服務(wù)器的數(shù)據(jù)目錄,并使用下述命令解壓縮歸檔文件:
shell> tar -xvf /tmp/mysql-snapshot.tar
如果從服務(wù)器的用戶賬戶與主服務(wù)器的不同,你可能不想復(fù)制mysql數(shù)據(jù)庫(kù)。在這種情況下,應(yīng)從歸檔中排除該數(shù)據(jù)庫(kù)。你也不需要在歸檔中包括任何日志文件或者master.info或relay-log.info文件。
當(dāng)FLUSH TABLES WITH READ LOCK所置讀鎖定有效時(shí),讀取主服務(wù)器上當(dāng)前的二進(jìn)制日志名和偏移量值:
mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File????????? | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73?????? | test???????? | manual,mysql???? |
+---------------+----------+--------------+------------------+
File列顯示日志名,而Position顯示偏移量。在該例子中,二進(jìn)制日志值為mysql-bin.003,偏移量為73。記錄該值。以后設(shè)置從服務(wù)器時(shí)需要使用這些值。它們表示復(fù)制坐標(biāo),從服務(wù)器應(yīng)從該點(diǎn)開始從主服務(wù)器上進(jìn)行新的更新。
取得快照并記錄日志名和偏移量后,可以在主服務(wù)器上重新啟用寫活動(dòng):
mysql> UNLOCK TABLES;
如果你正使用InnoDB表,理想情況應(yīng)使用InnoDB Hot Backup工具,使用該工具可以獲得一致的快照而不需要在主服務(wù)器上進(jìn)行鎖定,并且可以對(duì)應(yīng)從服務(wù)器上使用的快照來(lái)記錄日志名和偏移量。Hot Backup是一個(gè)附加的非免費(fèi)(商業(yè))工具,沒(méi)有包含在標(biāo)準(zhǔn) MySQL分發(fā)中。詳細(xì)信息參見http://www.innodb.com/manual.php的InnoDB Hot Backup主頁(yè)。
不使用Hot Backup工具,最快捷的途徑是使用InnoDB表的二進(jìn)制快照來(lái)關(guān)閉主服務(wù)器并復(fù)制InnoDB數(shù)據(jù)文件、日志文件和表定義文件(.frm文件)。要記錄當(dāng)前的日志文件名和偏移量,關(guān)閉服務(wù)器之前應(yīng)發(fā)出下面的語(yǔ)句:
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
然后記錄前面所示的SHOW MASTER STATUS的輸出中顯示的日志名和偏移量。記錄日志名和偏移量后,不解鎖表關(guān)閉服務(wù)器以確保? 服務(wù)器關(guān)閉時(shí)的快照與當(dāng)前的日志文件和偏移量相對(duì)應(yīng):
shell> mysqladmin -u root shutdown
適合MyISAM和InnoDB表的另一個(gè)方法是對(duì)主服務(wù)器上的SQL進(jìn)行轉(zhuǎn)儲(chǔ)而不是對(duì)前面討論的二進(jìn)制復(fù)制進(jìn)行轉(zhuǎn)儲(chǔ)。為了實(shí)現(xiàn),可以在主服務(wù)器上使用mysqldump --master-data,以后將SQL轉(zhuǎn)儲(chǔ)文件裝入從服務(wù)器。但是,這樣比二進(jìn)制復(fù)制要慢一些。
如果主服務(wù)器運(yùn)行時(shí)沒(méi)有啟用--logs-bin,SHOW MASTER STATUS或mysqldump --master-data顯示的日志名和位置值為空。在這種情況下,當(dāng)以后指定從服務(wù)器的日志文件和位置時(shí)需要使用的值為空字符串('')和4.
5.??? 確保主服務(wù)器主機(jī)上my.cnf文件的[mysqld]部分包括一個(gè)log-bin選項(xiàng)。該部分還應(yīng)有一個(gè)server-id=Master_id選項(xiàng),其中master_id必須為1到232–1之間的一個(gè)正整數(shù)值。例如:
6.??????????? [mysqld]
7.??????????? log-bin=mysql-bin
8.??????????? server-id=1
如果沒(méi)有提供那些選項(xiàng),應(yīng)添加它們并重啟服務(wù)器。
9.??? 停止用于從服務(wù)器的服務(wù)器并在其my.cnf文件中添加下面的行:
10.??????? [mysqld]
11.??????? server-id=slave_id
slave_id值同Master_id值一樣,必須為1到232–1之間的一個(gè)正整數(shù)值。并且,從服務(wù)器的ID必須與主服務(wù)器的ID不相同。例如:
[mysqld]
server-id=2
如果設(shè)置多個(gè)從服務(wù)器,每個(gè)從服務(wù)器必須有一個(gè)唯一的server-id值,必須與主服務(wù)器的以及其它從服務(wù)器的不相同??梢哉J(rèn)為server-id值類似于IP地址:這些ID值能唯一識(shí)別復(fù)制服務(wù)器群集中的每個(gè)服務(wù)器實(shí)例。
如果不指定一個(gè)server-id值,如果沒(méi)有定義master-host,則將它設(shè)置為1;否則設(shè)置為2。請(qǐng)注意如果server-id太長(zhǎng),主服務(wù)器 拒絕所有來(lái)自從服務(wù)器的連接,并且從服務(wù)器拒絕連接到主服務(wù)器。這樣,省略server-id只適合用二進(jìn)制日志備份。
12.如果對(duì)主服務(wù)器的數(shù)據(jù)進(jìn)行二進(jìn)制備份,啟動(dòng)從服務(wù)器之前將它復(fù)制到從服務(wù)器的數(shù)據(jù)目錄中。確保對(duì)這些文件和目錄的權(quán)限正確。服務(wù)器 MySQL運(yùn)行的用戶必須能夠讀寫文件,如同在主服務(wù)器上一樣。
如果使用mysqldum備份,先啟動(dòng)從服務(wù)器(看下一步)。
13.啟動(dòng)從服務(wù)器。如果前面已經(jīng)復(fù)制了,用--skip-slave-start選項(xiàng)啟動(dòng)從服務(wù)器,以便它不立即嘗試連接主服務(wù)器。你也可能想要用--logs-warnings選項(xiàng)啟動(dòng)從服務(wù)器(默認(rèn)設(shè)置啟用),以便在錯(cuò)誤日志中顯示更多的問(wèn)題相關(guān)的信息(例如,網(wǎng)絡(luò)或連接問(wèn)題)。放棄的連接將記入錯(cuò)誤日志,除非其值大于1。
14.如果使用mysqldump備份主服務(wù)器的數(shù)據(jù),將轉(zhuǎn)儲(chǔ)文件裝載到從服務(wù)器:
15.??????? shell> mysql -u root -p < dump_file.sql
16.??????? 在從服務(wù)器上執(zhí)行下面的語(yǔ)句,用你的系統(tǒng)的實(shí)際值替換選項(xiàng)值:
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;
下面的表顯示了字符串選項(xiàng)的最大長(zhǎng)度:
Master_Host |
60 |
Master_USER |
16 |
Master_PASSWORD |
32 |
Master_Log_File |
255 |
23.啟動(dòng)從服務(wù)器線程:
24.??????? mysql> START SLAVE;
執(zhí)行這些程序后,從服務(wù)器應(yīng)連接主服務(wù)器,并補(bǔ)充自從快照以來(lái)發(fā)生的任何更新。
如果你忘記設(shè)置主服務(wù)器的server-id值,從服務(wù)器不能連接主服務(wù)器。
如果你忘記設(shè)置從服務(wù)器的server-id值,在從服務(wù)器的錯(cuò)誤日志中會(huì)出現(xiàn)下面的錯(cuò)誤:
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.
如果由于其它原因不能復(fù)制,從服務(wù)器的錯(cuò)誤日志中也會(huì)出現(xiàn)錯(cuò)誤消息。
從服務(wù)器復(fù)制時(shí),會(huì)在其數(shù)據(jù)目錄中發(fā)現(xiàn)文件dmaster.info和relay-log.info。從服務(wù)器使用這兩個(gè)文件跟蹤已經(jīng)處理了多少主服務(wù)器的二進(jìn)制日志。不要移除或編輯這些文件,除非你確切知你正在做什么并完全理解其意義。即使這樣,最好是使用CHANGE MASTER TO語(yǔ)句。
注釋:master.info的內(nèi)容會(huì)覆蓋命令行或in my.cnf中指定的部分選項(xiàng)。詳情參見6.8節(jié),“復(fù)制啟動(dòng)選項(xiàng)”。
有了一個(gè)快照,你可以用它根據(jù)剛剛描述的從服務(wù)器部分來(lái)設(shè)置其它從服務(wù)器。你不需要主服務(wù)器的另一個(gè)快照;每個(gè)從服務(wù)器可以使用相同的快照。
注釋:為了保證事務(wù)InnoDB復(fù)制設(shè)置的最大可能的耐受性和一致性,應(yīng)在主服務(wù)器的my.cnf文件中使用innodb_flush_log_at_trx_commit=1和sync-binlog=1。
MySQL 5.1中使用的二進(jìn)制日志格式與以前的版本中所使用的大大不同,特別是在字符集處理、LOAD DATA INFILE以及時(shí)區(qū)方面。
注釋:你不能從使用新二進(jìn)制日志格式的主服務(wù)器向使用舊二進(jìn)制日志格式的從服務(wù)器復(fù)制(例如,從MySQL 5.0到MySQL 4.1)。。這樣操作在復(fù)制設(shè)置升級(jí)服務(wù)器時(shí)后果嚴(yán)重,參見6.6節(jié),“升級(jí)復(fù)制設(shè)置”。
我們推薦使用最近的MySQL版本,因?yàn)閺?fù)制功能在不斷地改進(jìn)中。我們還推薦主服務(wù)器和從服務(wù)器使用相同的版本。我們建議升級(jí)主服務(wù)器和從服務(wù)器,運(yùn)行alpha或beta版本到新的(產(chǎn)品)版本。在許多情況下,從新的主服務(wù)器向舊的從服務(wù)器復(fù)制將會(huì)失敗。一般原則,運(yùn)行MySQL 5.1.x的從服務(wù)器可以與舊的主服務(wù)器(可以運(yùn)行MySQL 3.23、4.0或者4.1)一起使用,但不能反過(guò)來(lái)。
前面的信息適合協(xié)議級(jí)復(fù)制兼容性。然而,還會(huì)有一個(gè)約束條件,例如SQL級(jí)兼容性問(wèn)題。例如, 5.1版本的主服務(wù)器不能復(fù)制到5.0版本的從服務(wù)器,如果復(fù)制語(yǔ)句使用5.1版本的SQL特性而不是5.0版本。這些問(wèn)題和其它問(wèn)題均在6.7節(jié),“復(fù)制特性和已知問(wèn)題”中討論。
當(dāng)將早期MySQL版本系列主服務(wù)器升級(jí)到5.1時(shí),應(yīng)先確保該主服務(wù)器的所有從服務(wù)器使用了相同的5.1.x版本。如果不是這樣,你應(yīng)先升級(jí)從服務(wù)器。升級(jí)從服務(wù)器時(shí),應(yīng)先關(guān)閉從服務(wù)器,升級(jí)到相應(yīng)5.1.x版本,然后重啟從服務(wù)器并重新開始復(fù)制。5.1版本的從服務(wù)器能夠讀取升級(jí)前寫入的舊的中繼日志并執(zhí)行日志中包含的語(yǔ)句。升級(jí)后從服務(wù)器創(chuàng)建的中繼日志為5.1格式。
從服務(wù)器升級(jí)后,關(guān)閉主服務(wù)器,將它升級(jí)到與從服務(wù)器相同的5.1.x版本并重啟它。5.1主服務(wù)器能夠讀取升級(jí)前寫入的舊的二進(jìn)制日志并將它們發(fā)送到5.1從服務(wù)器。從服務(wù)器可以識(shí)別舊的格式并正確處理它。升級(jí)后主服務(wù)器創(chuàng)建的二進(jìn)制日志采用5.1格式。這樣也可以由5.1從服務(wù)器識(shí)別。
換句話說(shuō),當(dāng)升級(jí)到5.1時(shí)沒(méi)有什么措施,只有將主服務(wù)器升級(jí)到5.1之前先將從服務(wù)器升級(jí)到5.1。請(qǐng)注意從5.1降級(jí)到舊版本不會(huì)如此簡(jiǎn)單:必須確保已經(jīng)完全處理所有5.1版本的二進(jìn)制日志或中繼日志,以便在降級(jí)前可以移除它們。
一般原則,SQL級(jí)復(fù)制兼容性要求主服務(wù)器和從服務(wù)器均支持使用的特性。例如,在MySQL 5.0.0中開始使用TIMESTAMPADD()函數(shù)。如果在主服務(wù)器上使用該函數(shù),不能復(fù)制到MySQL 5.0.0之前的從服務(wù)器。如果你計(jì)劃在5.1和以前版本的MySQL之間進(jìn)行復(fù)制,你應(yīng)查閱對(duì)應(yīng)以前版本系列的MySQL參考手冊(cè),查詢?cè)撓盗袕?fù)制特征相關(guān)信息。
下面列出了關(guān)于支持什么和不支持什么的詳細(xì)信息。關(guān)于復(fù)制的其它InnoDB具體信息參見15.2.6.5節(jié),“InnoDB和MySQL復(fù)制”。
關(guān)于保存的程序和觸發(fā)器的復(fù)制問(wèn)題在20.4節(jié),“存儲(chǔ)子程序和觸發(fā)程序的二進(jìn)制日志功能”中討論。
·???????? 用AUTO_INCREMENT、LAST_INSERT_ID()和TIMESTAMP值正確實(shí)現(xiàn)復(fù)制。
·???????? USER()、UUID()和LOAD_FILE()函數(shù)毫無(wú)改變地被,這樣不能可靠地在從服務(wù)器上工作。
·???????? 下面的限制只適合基于語(yǔ)句的復(fù)制,而不是基于行的復(fù)制。處理用戶級(jí)鎖定的函數(shù)GET_LOCK()、RELEASE_LOCK()、IS_FREE_LOCK()、IS_USED_LOCK()復(fù)制時(shí)從服務(wù)器不知道在主服務(wù)器上同時(shí)進(jìn)行的相關(guān)文本;因此如果從服務(wù)器上的內(nèi)容不同,這些函數(shù)不用來(lái)插入到主服務(wù)器的表中(例如不執(zhí)行INSERT INTO mytable VALUES(GET_LOCK(...)))。
·???????? 在MySQL 5.1中FOREIGN_KEY_CHECKS、SQL_MODE、UNIQUE_CHECKS和SQL_AUTO_IS_NULL變量均復(fù)制。但TABLE_TYPE,即STORAGE_ENGINE變量 不復(fù)制,有利于在不同的存儲(chǔ)引擎之間進(jìn)行復(fù)制。
·???????? 即使主服務(wù)器和從服務(wù)器有不同的全局字符集變量,以及即使有不同的全局時(shí)區(qū)變量仍可以復(fù)制。
·???????? 下面適合使用不同字符集的MySQL服務(wù)器之間的復(fù)制:
1.??? 必須在主服務(wù)器和從服務(wù)器上總是使用相同的全局字符集和校對(duì)規(guī)則(--default-character-set、--default-collation)。否則,會(huì)在從服務(wù)器上遇到復(fù)制鍵值錯(cuò)誤,因?yàn)樵谥鞣?wù)器的字符集中被認(rèn)為是唯一的鍵值在從服務(wù)器的字符集中可能不是唯一的。
2.??? 如果主服務(wù)器早于MySQL 4.1.3,則會(huì)話中的字符集不應(yīng)與其全局值不同(換句話說(shuō),不要使用SET NAMES、SET CHARACTER SET等等),因?yàn)閺姆?wù)器不知道該字符集的更改。如果主服務(wù)器和從服務(wù)器均為4.1.3或更新版,可以隨便將會(huì)話的字符集變量設(shè)置為本地值(例如NAMES、CHARACTER SET、COLLATION_CLIENT和COLLATION_SERVER),因?yàn)檫@些設(shè)定值被寫入二進(jìn)制日志,因此從服務(wù)器知道。然而,禁止更改會(huì)話中這些變量的全局值;如前面所述,主服務(wù)器和從服務(wù)器必須具有唯一的全局字符集值。
3.??? 如果在主服務(wù)器上的數(shù)據(jù)庫(kù)的字符集與全局collation_server值不同,則應(yīng)設(shè)計(jì)CREATE TABLE語(yǔ)句,以便它們不隱含依賴數(shù)據(jù)庫(kù)的默認(rèn)字符集(Bug #2326);一個(gè)好的解決辦法是在CREATE TABLE中明顯說(shuō)明字符集和校對(duì)規(guī)則。
·???????? 應(yīng)在主服務(wù)器和從服務(wù)器上設(shè)置相同的系統(tǒng)時(shí)區(qū)。否則一些語(yǔ)句,例如使用NOW()或FROM_UNIXTIME()函數(shù)的語(yǔ)句,將不會(huì)正確復(fù)制。可以使用腳本mysqld_safe的--timezone=timezone_name選項(xiàng)或通過(guò)設(shè)置TZ環(huán)境變量設(shè)置MySQL服務(wù)器運(yùn)行的系統(tǒng)的時(shí)區(qū)。主服務(wù)器和從服務(wù)器還應(yīng)有相同的默認(rèn)連接時(shí)區(qū)設(shè)置;即主服務(wù)器和從服務(wù)器應(yīng)有相同的--default-time-zone參數(shù)值。
·???????? CONVERT_TZ(...,...,@global.time_zone)不能正確復(fù)制。只有主服務(wù)器和從服務(wù)器均為5.0.4或更新版才能正確復(fù)制CONVERT_TZ(...,...,@session.time_zone)。
·???????? 會(huì)話變量只有在更新表的語(yǔ)句中使用時(shí)才能正確復(fù)制;例如:SET MAX_JOIN_SIZE=1000;INSERT INTO mytable VALUES(@MAX_JOIN_SIZE)不能將相同的數(shù)據(jù)插入到主服務(wù)器上和從服務(wù)器上。不適用于通用的SET TIME_ZONE=...;INSERT INTO mytable VALUES(CONVERT_TZ(...,...,@time_zone))。
·???????? 可以將從服務(wù)器上的非事務(wù)表復(fù)為主服務(wù)器上的事務(wù)表。例如,可以將主服務(wù)器上的InnoDB表復(fù)制為從服務(wù)器上的MyISAM表。然而,復(fù)制過(guò)程中,如果從服務(wù)器在BEGIN/COMMIT塊過(guò)程中停止則會(huì)產(chǎn)生問(wèn)題,因?yàn)閺姆?wù)器在BEGIN塊開始時(shí)會(huì)重啟。該問(wèn)題出現(xiàn)在TODO中,不久將會(huì)得到修復(fù)。
·???????? 在MySQL 5.1中可以正確復(fù)制引用用戶變量(即@var_name形式的變量)的更新語(yǔ)句;但在4.1以前的版本中卻不可能。請(qǐng)注意從MySQL 5.1開始對(duì)用戶變量名的大小寫不再敏感;當(dāng)在5.1和舊版本之間設(shè)置復(fù)制時(shí)應(yīng)考慮該問(wèn)題。
·???????? 從服務(wù)器可以使用SSL連接到主服務(wù)器。
·???????? 有一個(gè)全局系統(tǒng)變量slave_transaction_retries:如果因?yàn)槟硞€(gè)InnoDB死鎖或超過(guò) InnoDB的innodb_lock_wait_timeout或NDB簇的TransactionDeadlockDetectionTimeout或TransactionInactiveTimeout,REPLICATION SLAVESQL線程未能執(zhí)行某個(gè)事務(wù),在給出錯(cuò)誤停止前自動(dòng)重試slave_transaction_retries次。 默認(rèn)值是10。從MySQL 5.0.4開始,可以從SHOW STATUS的輸出中看到重試總次數(shù);參見5.3.4節(jié),“服務(wù)器狀態(tài)變量”。
·???????? 如果在主服務(wù)器上的CREATE TABLE語(yǔ)句中使用了DATA DIRECTORY或INDEX DIRECTORY子句,子句也可以在從服務(wù)器上使用。如果在從服務(wù)器主機(jī)文件系統(tǒng)中不存在一致的目錄或雖然存在但不能被從服務(wù)器訪問(wèn),則會(huì)帶來(lái)問(wèn)題。MySQL 5.1支持一個(gè)稱為NO_DIR_IN_CREATE的sql_mode選項(xiàng)。如果從服務(wù)器運(yùn)行時(shí)將SQL模式設(shè)置為包括該選項(xiàng),復(fù)制CREATE TABLE語(yǔ)句時(shí)將忽略這些子句。結(jié)果是在表的數(shù)據(jù)庫(kù)目錄中創(chuàng)建了MyISAM數(shù)據(jù)和索引文件。
·???????? 下面的限制只適合基于語(yǔ)句的復(fù)制,而不是基于行的復(fù)制:如果在查詢中數(shù)據(jù)修改不確定,主服務(wù)器和從服務(wù)器上的數(shù)據(jù)可以不同;也就是由查詢優(yōu)化器確定。(這是常用的但不是很好的習(xí)慣,即使不是在復(fù)制中也不好)。關(guān)于該問(wèn)題的詳細(xì)解釋,參見A.8.1節(jié),“MySQL中的打開事宜”。
·???????? 帶READ LOCK的FLUSH LOGS、FLUSH MASTER、FLUSH SLAVE和FLUSH TABLES不記入日志,因?yàn)槿绻麖?fù)制到從服務(wù)器會(huì)造成問(wèn)題。關(guān)于語(yǔ)法示例,參見13.5.5.2節(jié),“FLUSH語(yǔ)法”。FLUSH TABLES、ANALYZE TABLE、OPTIMIZE TABLE和REPAIR TABLE語(yǔ)句被寫入二進(jìn)制日志并會(huì)復(fù)制到從服務(wù)器。一般情況不會(huì)造成問(wèn)題,因?yàn)檫@些語(yǔ)句不修改表的數(shù)據(jù)。但是在某些情況下會(huì)帶來(lái)問(wèn)題。如果你復(fù)制mysql數(shù)據(jù)庫(kù)中的授權(quán)表并且不使用GRANT直接更新那些表,必須在從服務(wù)器上執(zhí)行FLUSH PRIVILEGES使新的權(quán)限生效。并且,如果使用FLUSH TABLES重新命名MERGE表的MyISAM表,必須手動(dòng)在從服務(wù)器上執(zhí)行FLUSH TABLES。如果不指定NO_WRITE_TO_BINLOG或其別名LOCAL,則這些語(yǔ)句被寫入二進(jìn)制日志。
·???????? MySQL只支持一個(gè)主服務(wù)器和多個(gè)從服務(wù)器。我們計(jì)劃將來(lái)添加一個(gè)投票算法,當(dāng)前的主服務(wù)器出現(xiàn)問(wèn)題時(shí)自動(dòng)切換。我們還計(jì)劃引入代理過(guò)程通過(guò)向不同的從服務(wù)器發(fā)送SELECT查詢以幫助進(jìn)行負(fù)載均衡。
·???????? 當(dāng)服務(wù)器關(guān)閉、重啟時(shí),其MEMORY表將變?yōu)榭?。主服?wù)器按下述方法復(fù)制該結(jié)果:?jiǎn)?dòng)后第1次主服務(wù)器使用每個(gè)MEMORY表,它通知從服務(wù)器需要向表寫入DELETE FROM語(yǔ)句來(lái)清空二進(jìn)制日志的表。詳細(xì)信息參見15.4節(jié),“MEMORY (HEAP)存儲(chǔ)引擎”。
·???????? 除了關(guān)閉從服務(wù)器(而不僅僅是從服務(wù)器線程) 臨時(shí)表都被復(fù)制,并且還沒(méi)有在從服務(wù)器上執(zhí)行的更新所使用的臨時(shí)表也已經(jīng)復(fù)制。如果關(guān)閉從服務(wù)器,從服務(wù)器重啟后更新需要的那些臨時(shí)表不可再用。為了避免該問(wèn)題,臨時(shí)表打開時(shí)不要關(guān)閉從服務(wù)器。而應(yīng)遵照下面的程序:
1.??? 執(zhí)行STOP SLAVE語(yǔ)句。
2.??? 使用SHOW STATUS檢查slave_open_temp_tables變量的值。
3.??? 如果值為0,使用mysqladmin shutdown命令關(guān)閉從服務(wù)器。
4.??? 如果值不為0,用START SLAVE重啟從服務(wù)器線程。
5.??? 后面再重復(fù)該程序看下次的運(yùn)氣是否好一些。
我們計(jì)劃在不久的將來(lái)修復(fù)該問(wèn)題。
·???????? 可以很安全地連接用--logs-slave-updates選項(xiàng)指定的循環(huán)主服務(wù)器/從服務(wù)器關(guān)系中的服務(wù)器。但請(qǐng)注意許多語(yǔ)句在這種設(shè)置中不能正確工作,除非你的客戶代碼關(guān)注了潛在的在不同的服務(wù)器不同順序的更新中可能發(fā)生的這類問(wèn)題。
這說(shuō)明你可以象這樣創(chuàng)建設(shè)置:
A -> B -> C -> A
服務(wù)器ID被編碼在二進(jìn)制日志事件中,因此服務(wù)器A知道何時(shí)自己首次創(chuàng)建它讀取的事件并且不執(zhí)行事件(除非用--replicate-same-server-id選項(xiàng)啟動(dòng)了服務(wù)器A,只在很少情況下有意義)。這樣,沒(méi)有無(wú)限循環(huán)。只有對(duì)表執(zhí)行沒(méi)有沖突的更新時(shí)該類循環(huán)設(shè)置才能工作。換句話說(shuō),如果在A和C中插入數(shù)據(jù),絕對(duì)不應(yīng)在A中插入鍵值可能與插入到C中的行相沖突的一行。如果更新的順序很重要,還不應(yīng)更新兩個(gè)服務(wù)器上相同的行。
·???????? 如果從服務(wù)器上的某個(gè)語(yǔ)句產(chǎn)生錯(cuò)誤,則從服務(wù)器上的SQL線程終止,并且從服務(wù)器向錯(cuò)誤日志寫入一條消息。此時(shí)應(yīng)手動(dòng)連接從服務(wù)器,修復(fù)該問(wèn)題(例如,一個(gè)不存在的表),然后運(yùn)行START SLAVE。
·???????? 可以很安全地關(guān)閉主服務(wù)器并在以后重啟。如果某個(gè)從服務(wù)器丟失與主服務(wù)器的連接,從服務(wù)器嘗試立即重新連接。如果失敗,從服務(wù)器定期重試。(默認(rèn)設(shè)置是每60秒重試一次??梢酝ㄟ^(guò)--master-connect-retry選項(xiàng)更改)。從服務(wù)器也能夠處理網(wǎng)絡(luò)連接中斷。但是,只有從服務(wù)器超過(guò)slave_net_timeout秒沒(méi)有從主服務(wù)器收到數(shù)據(jù)才通知網(wǎng)絡(luò)中斷。如果中斷時(shí)間短,可以降低slave_net_timeout。參見5.3.3節(jié),“服務(wù)器系統(tǒng)變量”。
·???????? 關(guān)閉從服務(wù)器(凈關(guān)閉)也很安全,因?yàn)樗梢愿櫵x開的地點(diǎn)。不純凈的關(guān)閉操作會(huì)產(chǎn)生問(wèn)題,特別是系統(tǒng)關(guān)閉前硬盤緩存未刷新到硬盤上時(shí)。如果有不間斷電源,可以大大提高系統(tǒng)容錯(cuò)能力。不純凈的關(guān)閉主服務(wù)器會(huì)造成主服務(wù)器上的表和二進(jìn)制日志內(nèi)容之間的不一致性;在主服務(wù)器上使用InnoDB表和--innodb-safe-binlog選項(xiàng)可以避免該問(wèn)題。參見5.11.3節(jié),“二進(jìn)制日志”。(注釋:MySQL 5.1中不需要--innodb-safe-binlog,由于引入了XA事務(wù)支持已經(jīng)作廢了)。
·???????? 由于MyISAM表的非事務(wù)屬性,可以有一個(gè)語(yǔ)句只是更新一個(gè)表并返回錯(cuò)誤代碼。例如,多行插入時(shí)有一個(gè)行超過(guò)鍵值約束,或者如果長(zhǎng)的更新語(yǔ)句更新部分行后被殺掉了。如果發(fā)生在主服務(wù)器上,除非錯(cuò)誤代碼合法并且語(yǔ)句執(zhí)行產(chǎn)生相同的錯(cuò)誤代碼,從服務(wù)器線程將退出并等待數(shù)據(jù)庫(kù)管理員決定如何做。如果該錯(cuò)誤代碼驗(yàn)證行為不理想,可以用--slave-skip-errors選項(xiàng)掩蓋(忽視)部分或全部錯(cuò)誤。
·???????? 如果從BEGIN/COMMIT系列的非事務(wù)表更新事務(wù)表,如果提交事務(wù)前更新非事務(wù)表,對(duì)二進(jìn)制日志的更新可能會(huì)不同步。這是因?yàn)槭聞?wù)提交后才被寫入二進(jìn)制日志。
·???????? 事務(wù)混合更新事務(wù)表和非事務(wù)表時(shí),二進(jìn)制日志中語(yǔ)句的順序是正確的,即使在ROLLBACK時(shí),所有需要的語(yǔ)句也會(huì)寫入二進(jìn)制日志。但是如果在第1個(gè)連接的事務(wù)完成前,第2個(gè)連接更新非事務(wù)表,語(yǔ)句記入日志時(shí)會(huì)出現(xiàn)順序錯(cuò)誤,因?yàn)榈?span>2個(gè)連接的更新執(zhí)行完后立即寫入日志,而不管第1個(gè)連接執(zhí)行的事務(wù)的狀態(tài)如何。
在主服務(wù)器和從服務(wù)器上,均必須使用server-id選項(xiàng)為每個(gè)服務(wù)器建立唯一的復(fù)制ID。你應(yīng)為每個(gè)主服務(wù)器和從服務(wù)器從1到232–1的范圍挑一個(gè)唯一的正整數(shù)。例如:server-id=3
用于主服務(wù)器上控制二進(jìn)制日志的選項(xiàng)的相關(guān)描述見5.11.3節(jié),“二進(jìn)制日志”。
下表描述了可以用于MySQL 5.1從屬?gòu)?fù)制服務(wù)器的選項(xiàng)。你可以在命令行中或在選項(xiàng)文件中指定這些選項(xiàng)。
某些從服務(wù)器復(fù)制選項(xiàng)按特殊方式處理,當(dāng)從服務(wù)器啟動(dòng)時(shí)如果master.info文件存在并且包含選項(xiàng)值,它們將被忽略掉。下面的選項(xiàng)按這種方式處理:
·???????? --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文件格式包括對(duì)應(yīng)SSL選項(xiàng)的值。并且,文件格式包括文件中的行號(hào),如同第1行。如果你將舊的服務(wù)器升級(jí)到新的版本,新服務(wù)器啟動(dòng)時(shí)自動(dòng)將smaster.info文件升級(jí)到新的格式。然而,如果將新服務(wù)器降級(jí)到舊的版本,首次啟動(dòng)舊版本的服務(wù)器之前應(yīng)刪除第1行。
如果從服務(wù)器啟動(dòng)時(shí)master.info文件不存在,選項(xiàng)采用選項(xiàng)文件或命令行中指定的值。首次將服務(wù)器作為從服務(wù)器啟動(dòng)時(shí),或者已經(jīng)運(yùn)行RESET SLAVE然后已經(jīng)關(guān)閉并重啟從服務(wù)器時(shí)會(huì)發(fā)生。
如果從服務(wù)器啟動(dòng)時(shí)master.info文件存在,服務(wù)器忽略那些選項(xiàng)。使用master.info文件中發(fā)現(xiàn)的值。
如果你使用與master.info文件中相對(duì)應(yīng)的啟動(dòng)選項(xiàng)的不同的值重啟從服務(wù)器,啟動(dòng)選項(xiàng)的不同的值不會(huì)生效,因?yàn)榉?wù)器繼續(xù)使用master.info文件。要想使用啟動(dòng)選項(xiàng)的不同的值,必須刪除master.info文件并重啟從服務(wù)器,或(最好是)在從服務(wù)器運(yùn)行時(shí)使用CHANGE MASTER TO語(yǔ)句重新設(shè)置值。
假定在my.cnf文件中指定該選項(xiàng):
[mysqld]
master-host=some_host
第1次作為復(fù)制從服務(wù)器啟動(dòng)服務(wù)器時(shí),從my.cnf文件讀取并使用選項(xiàng)。服務(wù)器然后記錄master.info文件中的值。下次啟動(dòng)服務(wù)器時(shí),它只從服務(wù)器的master.info文件讀取主服務(wù)器主機(jī)值并忽略選項(xiàng)文件中的值。如果你修改my.cnf文件為some_other_host指定其它主服務(wù)器主機(jī),更改仍然不會(huì)生效。你應(yīng)使用CHANGE MASTER TO。
因?yàn)榉?wù)器給已有master.info文件的優(yōu)先權(quán)高于剛剛描述的啟動(dòng)選項(xiàng),可以選擇不使用這些值的啟動(dòng)選項(xiàng),而是使用CHANGE MASTER TO語(yǔ)句來(lái)指定。參見13.6.2.1節(jié),“CHANGE MASTER TO語(yǔ)法”。
下面的例子顯示了如何更廣泛地使用啟動(dòng)選項(xiàng)來(lái)配置從服務(wù)器:
[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
下面列出了控制復(fù)制的啟動(dòng)選項(xiàng):許多選項(xiàng)可以在服務(wù)器運(yùn)行時(shí)通過(guò)CHANGE MASTER TO語(yǔ)句重新進(jìn)行設(shè)置。其它選項(xiàng),例如--replicate-*選項(xiàng),只能在從服務(wù)器啟動(dòng)時(shí)進(jìn)行設(shè)置。我們計(jì)劃將修復(fù)該問(wèn)題。
·???????? --logs-slave-updates
通常情況,從服務(wù)器從主服務(wù)器接收到的更新不記入它的二進(jìn)制日志。該選項(xiàng)告訴從服務(wù)器將其SQL線程執(zhí)行的更新記入到從服務(wù)器自己的二進(jìn)制日志。為了使該選項(xiàng)生效,還必須用--logs-bin選項(xiàng)啟動(dòng)從服務(wù)器以啟用二進(jìn)制日志。如果想要應(yīng)用鏈?zhǔn)綇?fù)制服務(wù)器,應(yīng)使用--logs-slave-updates。例如,可能你想要這樣設(shè)置:
A -> B -> C
也就是說(shuō),A為從服務(wù)器B的主服務(wù)器,B為從服務(wù)器C的主服務(wù)器。為了能工作,B必須既為主服務(wù)器又為從服務(wù)器。你必須用--logs-bin啟動(dòng)A和B以啟用二進(jìn)制日志,并且用--logs-slave-updates選項(xiàng)啟動(dòng)B。
·???????? --logs-warnings
讓從服務(wù)器向錯(cuò)誤日志輸出更詳細(xì)的關(guān)于其執(zhí)行操作的消息。例如,通知你網(wǎng)絡(luò)/連接失敗后已經(jīng)成功重新連接,并通知你每個(gè)從服務(wù)器線程如何啟動(dòng)。該選項(xiàng)默認(rèn)啟用;要想禁用它,使用--skip-logs-warnings。放棄的連接不記入錯(cuò)誤日志,除非該值大于1。
請(qǐng)注意該選項(xiàng)的效果不限于復(fù)制??梢詫?duì)服務(wù)器的部分動(dòng)作產(chǎn)生警告。
·???????? --master-connect-retry=seconds
在主服務(wù)器宕機(jī)或連接丟失的情況下,從服務(wù)器線程重新嘗試連接主服務(wù)器之前睡眠的秒數(shù)。如果主服務(wù)器.info文件中的值可以讀取則優(yōu)先使用。如果未設(shè)置, 默認(rèn)值為60。
·???????? --master-host=host
主復(fù)制服務(wù)器的主機(jī)名或IP地址。如果沒(méi)有給出該選項(xiàng),從服務(wù)器線程不啟動(dòng)。如果主服務(wù)器.info文件中的值可以讀取則優(yōu)先使用。
·???????? --master-info-file=file_name
從服務(wù)器用于記錄主服務(wù)器的相關(guān)信息使用的文件名。默認(rèn)名為數(shù)據(jù)目錄中的mysql.info。
·???????? --master-password=password
連接主服務(wù)器時(shí)從服務(wù)器線程用于鑒定的賬戶的密碼。如果主服務(wù)器.info文件中的值可以讀取則優(yōu)先使用。如果未設(shè)置,假定 密碼為空。
·???????? --master-port=port_number
主服務(wù)器正幀聽的TCP/IP端口號(hào)。如果主服務(wù)器.info文件中的值可以讀取則優(yōu)先使用。如果未設(shè)置,假定使用編譯進(jìn)來(lái)的設(shè)定值。如果你未曾用configure選項(xiàng)進(jìn)行修改,該值應(yīng)為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
這些選項(xiàng)用于使用SSL設(shè)置與主服務(wù)器的安全復(fù)制連接。它們的含義與5.8.7.6節(jié),“SSL命令行選項(xiàng)”中描述的相應(yīng)—ssl、--ssl-ca、--ssl-capath、--ssl-cert、--ssl-cipher、--ssl-key選項(xiàng)相同。如果主服務(wù)器.info文件中的值可以讀取則優(yōu)先使用。
·???????? --master-user=username
連接主服務(wù)器時(shí)從服務(wù)器線程用于鑒定的賬戶的用戶名。該賬戶必須具有REPLICATION SLAVE權(quán)限。如果主服務(wù)器.info文件中的值可以讀取則優(yōu)先使用。如果未設(shè)置主服務(wù)器用戶,假定使用用戶test。
·???????? --max-relay-logs-size=size
自動(dòng)循環(huán)中繼日志。參見5.3.3節(jié),“服務(wù)器系統(tǒng)變量”。
·???????? --read-only
該選項(xiàng)讓從服務(wù)器只允許來(lái)自從服務(wù)器線程或具有SUPER權(quán)限的用戶的更新。可以確保從服務(wù)器不接受來(lái)自客戶的更新。
·???????? --relay-log=file_name
中繼日志名。默認(rèn)名為host_name-relay-bin.nnnnnn,其中host_name是從服務(wù)器主機(jī)的名,nnnnnn表示中繼日志在編號(hào)序列中創(chuàng)建。如果中繼日志太大(并且你不想降低max_relay_log_size),需要將它們放到數(shù)據(jù)目錄之外的其它地方,或者如果想要通過(guò)硬盤之間的負(fù)載均衡提高速度,可以指定選項(xiàng)創(chuàng)建與主機(jī)名無(wú)關(guān)的中繼日志名。
·???????? --relay-log-index=file_name
中繼日志索引文件使用的位置和名稱。默認(rèn)名為host_name-relay-bin.index,其中host_name為從服務(wù)器名。
·???????? --relay-log-info-file=file_name
從服務(wù)器用于記錄中繼日志相關(guān)信息的文件名。默認(rèn)名為數(shù)據(jù)目錄中的relay-log.info。
·???????? --relay-log-purge={0|1}
禁用或啟用不再需要中繼日志時(shí)是否自動(dòng)清空它們。默認(rèn)值為1(啟用)。這是一個(gè)全局變量,可以用SET GLOBAL Relay_log_purge動(dòng)態(tài)更改。
·???????? --relay-log-space-limit=size
限制所有中繼日志在從服務(wù)器上所占用空間的上限(0值表示“無(wú)限制”)。從服務(wù)器主機(jī)硬盤空間有限時(shí)很有用。達(dá)到限制后,I/O線程停止從主服務(wù)器讀取二進(jìn)制日志中的事件,直到SQL線程被閉鎖并且刪除了部分未使用的中繼日志。請(qǐng)注意該限制并不是絕對(duì)的:有可能SQL線程刪除中繼日志前需要更多的事件。在這種情況下,I/O線程將超過(guò)限制,直到SQL線程可以刪除部分中繼日志。(不這樣做將會(huì)造成死鎖)。--relay-log-space-limit的值不能小于--max-relay-logs-size(或如果--max-relay-logs-size為0,選--max-binlog-size)的值的兩倍。在這種情況下,有可能I/O線程等待釋放空間,因?yàn)槌^(guò)了--relay-log-space-limit,但SQL線程沒(méi)有要清空的中繼日志,不能滿足I/O線程的需求。強(qiáng)制I/O線程臨時(shí)忽視--relay-log-space-limit。
·???????? --replicate-do-db=db_name
告訴從服務(wù)器限制默認(rèn)數(shù)據(jù)庫(kù)(由USE所選擇)為db_name的語(yǔ)句的復(fù)制。要指定多個(gè)數(shù)據(jù)庫(kù),應(yīng)多次使用該選項(xiàng),每個(gè)數(shù)據(jù)庫(kù)使用一次。請(qǐng)注意不復(fù)制跨數(shù)據(jù)庫(kù)的語(yǔ)句,例如當(dāng)已經(jīng)選擇了其它數(shù)據(jù)庫(kù)或沒(méi)有數(shù)據(jù)庫(kù)時(shí)執(zhí)行UPDATE some_db.some_table SET foo='bar'。如果需要跨數(shù)據(jù)庫(kù)進(jìn)行更新,使用--replicate-wild-do-table=db_name.%。請(qǐng)讀取該選項(xiàng)列表后面的注意事項(xiàng)。
一個(gè)不能按照期望工作的例子:如果用--replicate-do-db=sales啟動(dòng)從服務(wù)器,并且在主服務(wù)器上執(zhí)行下面的語(yǔ)句,UPDATE語(yǔ)句不會(huì)復(fù)制:
USE prices;
UPDATE sales.january SET amount=amount+1000;
如果需要跨數(shù)據(jù)庫(kù)進(jìn)行更新,應(yīng)使用--replicate-wild-do-table=db_name.%。
“只檢查默認(rèn)數(shù)據(jù)庫(kù)”行為的主要原因是語(yǔ)句自己很難知道它是否應(yīng)被復(fù)制(例如,如果你正使用跨數(shù)據(jù)庫(kù)的多表DELETE語(yǔ)句或多表UPDATE語(yǔ)句)。如果不需要,只檢查默認(rèn)數(shù)據(jù)庫(kù)比檢查所有數(shù)據(jù)庫(kù)要快得多。
·???????? --replicate-do-table=db_name.tbl_name
告訴從服務(wù)器線程限制對(duì)指定表的復(fù)制。要指定多個(gè)表,應(yīng)多次使用該選項(xiàng),每個(gè)表使用一次。同--replicate-do-db對(duì)比,允許跨數(shù)據(jù)庫(kù)更新。請(qǐng)讀取該選項(xiàng)列表后面的注意事項(xiàng)。
·???????? --replicate-ignore-db=db_name
告訴從服務(wù)器不要復(fù)制默認(rèn)數(shù)據(jù)庫(kù)(由USE所選擇)為db_name的語(yǔ)句。要想忽略多個(gè)數(shù)據(jù)庫(kù),應(yīng)多次使用該選項(xiàng),每個(gè)數(shù)據(jù)庫(kù)使用一次。如果正進(jìn)行跨數(shù)據(jù)庫(kù)更新并且不想復(fù)制這些更新,不應(yīng)使用該選項(xiàng)。請(qǐng)讀取該選項(xiàng)后面的注意事項(xiàng)。
一個(gè)不能按照期望工作的例如:如果用--replicate-ignore-db=sales啟動(dòng)從服務(wù)器,并且在主服務(wù)器上執(zhí)行下面的語(yǔ)句,UPDATE語(yǔ)句不會(huì)復(fù)制:
·??????????????? USE prices;
·??????????????? UPDATE sales.january SET amount=amount+1000;
如果需要跨數(shù)據(jù)庫(kù)更新,應(yīng)使用--replicate-wild-ignore-table=db_name.%。
·???????? --replicate-ignore-table=db_name.tbl_name
告訴從服務(wù)器線程不要復(fù)制更新指定表的任何語(yǔ)句(即使該語(yǔ)句可能更新其它的表)。要想忽略多個(gè)表,應(yīng)多次使用該選項(xiàng),每個(gè)表使用一次。同--replicate-ignore-db對(duì)比,該選項(xiàng)可以跨數(shù)據(jù)庫(kù)進(jìn)行更新。請(qǐng)讀取該選項(xiàng)后面的注意事項(xiàng)。
·???????? --replicate-wild-do-table=db_name.tbl_name
告訴從服務(wù)器線程限制復(fù)制更新的表匹配指定的數(shù)據(jù)庫(kù)和表名模式的語(yǔ)句。模式可以包含‘%’和‘_’通配符,與LIKE模式匹配操作符具有相同的含義。要指定多個(gè)表,應(yīng)多次使用該選項(xiàng),每個(gè)表使用一次。該選項(xiàng)可以跨數(shù)據(jù)庫(kù)進(jìn)行更新。請(qǐng)讀取該選項(xiàng)后面的注意事項(xiàng)。
例如:--replicate-wild-do-table=foo%.bar%只復(fù)制數(shù)據(jù)庫(kù)名以foo開始和表名以bar開始的表的更新。
如果表名模式為%,可匹配任何表名,選項(xiàng)也適合數(shù)據(jù)庫(kù)級(jí)語(yǔ)句(CREATE DATABASE、DROP DATABASE和ALTER DATABASE)。例如,如果使用--replicate-wild-do-table=foo%.%,如果數(shù)據(jù)庫(kù)名匹配模式foo%,則復(fù)制數(shù)據(jù)庫(kù)級(jí)語(yǔ)句。
要想在數(shù)據(jù)庫(kù)或表名模式中包括通配符,用反斜線對(duì)它們進(jìn)行轉(zhuǎn)義。例如,要復(fù)制名為my_own%db的數(shù)據(jù)庫(kù)的所有表,但不復(fù)制my1ownAABCdb數(shù)據(jù)庫(kù)的表,應(yīng)這樣轉(zhuǎn)義‘_’和‘%’字符:--replicate-wild-do-table=my\_own\%db。如果在命令行中使用選項(xiàng),可能需要雙反斜線或?qū)⑦x項(xiàng)值引起來(lái),取決于命令解釋符。例如,用bash外殼則需要輸入--replicate-wild-do-table=my\\_own\\%db。
·???????? --replicate-wild-ignore-table=db_name.tbl_name
告訴從服務(wù)器線程不要復(fù)制表匹配給出的通配符模式的語(yǔ)句。要想忽略多個(gè)表,應(yīng)多次使用該選項(xiàng),每個(gè)表使用一次。該選項(xiàng)可以跨數(shù)據(jù)庫(kù)進(jìn)行更新。請(qǐng)讀取該選項(xiàng)后面的注意事項(xiàng)。
例如:--replicate-wild-ignore-table=foo%.bar%不復(fù)制數(shù)據(jù)庫(kù)名以foo開始和表名以bar開始的表的更新。
關(guān)于匹配如何工作的信息,參見--replicate-wild-do-table選項(xiàng)的描述。在選項(xiàng)值中包括通配符的規(guī)則與--replicate-wild-ignore-table相同。
·???????? --replicate-rewrite-db=from_name->to_name
告訴從服務(wù)器如果默認(rèn)數(shù)據(jù)庫(kù)(由USE所選擇)為主服務(wù)器上的from_name,則翻譯為to_name。只影響含有表的語(yǔ)句(不是類似CREATE DATABASE、DROP DATABASE和ALTER DATABASE的語(yǔ)句),并且只有from_name為主服務(wù)器上的默認(rèn)數(shù)據(jù)庫(kù)時(shí)。該選項(xiàng)不可以跨數(shù)據(jù)庫(kù)進(jìn)行更新。請(qǐng)注意在測(cè)試--replicate-*規(guī)則之前翻譯數(shù)據(jù)庫(kù)名。
如果在命令行中使用該選項(xiàng), ‘>’字符專用于命令解釋符,應(yīng)將選項(xiàng)值引起來(lái)。例如:
shell> mysqld --replicate-rewrite-db="olddb->newdb"
·???????? --replicate-same-server-id
將用于從服務(wù)器上。通??梢阅J(rèn)設(shè)置為0以防止循環(huán)復(fù)制中的無(wú)限循環(huán)。如果設(shè)置為1,該從服務(wù)器不跳過(guò)有自己的服務(wù)器id的事件;通常只在有很少配置的情況下有用。如果使用--logs-slave-updates不能設(shè)置為1。請(qǐng)注意默認(rèn)情況下如果有從服務(wù)器的id,服務(wù)器I/O線程不將二進(jìn)制日志事件寫入中繼日志(該優(yōu)化可以幫助節(jié)省硬盤的使用)。因此如果想要使用--replicate-same-server-id,讓從服務(wù)器讀取自己的SQL線程執(zhí)行的事件前,一定要用該選項(xiàng)啟動(dòng)。
·???????? --report-host=slave_name
從服務(wù)器注冊(cè)過(guò)程中報(bào)告給主服務(wù)器的主機(jī)名或IP地址。該值出現(xiàn)在主服務(wù)器上SHOW SLAVE HOSTS的輸出中。如果不想讓從服務(wù)器自己在主服務(wù)器上注冊(cè),則不設(shè)置該值。請(qǐng)注意從服務(wù)器連接后,主服務(wù)器僅僅從TCP/IP套接字讀取從服務(wù)器的IP號(hào)是不夠的。由于 NAT和其它路由問(wèn)題,IP可能不合法,不能從主服務(wù)器或其它主機(jī)連接從服務(wù)器。
·???????? --report-port=slave_port
連接從服務(wù)器的TCP/IP端口號(hào),從服務(wù)器注冊(cè)過(guò)程中報(bào)告給主服務(wù)器。只有從服務(wù)器幀聽非默認(rèn)端口或如果有一個(gè)特殊隧道供主服務(wù)器或其它客戶連接從服務(wù)器時(shí)才設(shè)置它。如果你不確定,不設(shè)置該選項(xiàng)。
·???????? --skip-slave-start
告訴從服務(wù)器當(dāng)服務(wù)器啟動(dòng)時(shí)不啟動(dòng)從服務(wù)器線程。使用START SLAVE語(yǔ)句在以后啟動(dòng)線程。
·???????? --slave_compressed_protocol={0|1}
如果該選項(xiàng)設(shè)置為 1,如果從服務(wù)器和主服務(wù)器均支持,使用壓縮從服務(wù)器/主服務(wù)器協(xié)議。
·???????? --slave-load-tmpdir=file_name
從服務(wù)器創(chuàng)建臨時(shí)文件的目錄名。該選項(xiàng)默認(rèn)等于tmpdir系統(tǒng)變量的值。當(dāng)從服務(wù)器SQL線程復(fù)制LOAD DATA INFILE語(yǔ)句時(shí),從中繼日志將待裝載的文件提取到臨時(shí)文件,然后將這些文件裝入到表中。如果裝載到主服務(wù)器上的文件很大,從服務(wù)器上的臨時(shí)文件也很大。因此,建議使用該選項(xiàng)告訴從服務(wù)器將臨時(shí)文件放到文件系統(tǒng)中有大量可用空間的目錄下。在這種情況下,也可以使用--relay-log選項(xiàng)將中繼日志放到該文件系統(tǒng)中,因?yàn)橹欣^日志也很大。--slave-load-tmpdir應(yīng)指向基于硬盤的文件系統(tǒng),而非基于內(nèi)存的文件系統(tǒng):從服務(wù)器需要用臨時(shí)文件在機(jī)器重啟時(shí)用于復(fù)制LOAD DATA INFILE。系統(tǒng)啟動(dòng)過(guò)程中操作系統(tǒng)也不能清除該目錄。
·???????? --slave-net-timeout=seconds
放棄讀之前從主服務(wù)器等候更多數(shù)據(jù)的秒數(shù),考慮到連接中斷和嘗試重新連接。超時(shí)后立即開始第1次重試。由--master-connect-retry選項(xiàng)控制重試之間的間隔。
·???????? --slave-skip-errors=[err_code1,err_code2,... | all]
通常情況,當(dāng)出現(xiàn)錯(cuò)誤時(shí)復(fù)制停止,這樣給你一個(gè)機(jī)會(huì)手動(dòng)解決數(shù)據(jù)中的不一致性問(wèn)題。該選項(xiàng)告訴從服務(wù)器SQL線程當(dāng)語(yǔ)句返回任何選項(xiàng)值中所列的錯(cuò)誤時(shí)繼續(xù)復(fù)制。
如果你不能完全理解為什么發(fā)生錯(cuò)誤,則不要使用該選項(xiàng)。如果復(fù)制設(shè)置和客戶程序中沒(méi)有bug,并且MySQL自身也沒(méi)有bug,應(yīng)不會(huì)發(fā)生停止復(fù)制的錯(cuò)誤。濫用該選項(xiàng)會(huì)使從服務(wù)器與主服務(wù)器不能保存同步,并且你找不到原因。
對(duì)于錯(cuò)誤代碼,你應(yīng)使用從服務(wù)器錯(cuò)誤日志中錯(cuò)誤消息提供的編號(hào)和SHOW SLAVE STATUS的輸出。服務(wù)器錯(cuò)誤代碼列于附錄B:錯(cuò)誤代碼和消息。
你也可以(但不應(yīng))使用不推薦的all值忽略所有錯(cuò)誤消息,不考慮所發(fā)生的錯(cuò)誤。無(wú)需而言,如果使用該值,我們不能保證數(shù)據(jù)的完整性。在這種情況下,如果從服務(wù)器的數(shù)據(jù)與主服務(wù)器上的不相近請(qǐng)不要抱怨(或編寫bug報(bào)告)。已經(jīng)警告你了。
例如:
--slave-skip-errors=1062,1053
--slave-skip-errors=all
從服務(wù)器按下面評(píng)估--replicate-*規(guī)則,確定是否執(zhí)行或忽視語(yǔ)句:
1.??? 是否有--replicate-do-db或--replicate-ignore-db規(guī)則?
·???????? 有:測(cè)試--binlog-do-db和--binlog-ignore-db(參見5.11.3節(jié),“二進(jìn)制日志”)。測(cè)試結(jié)果是什么?
o??????? 忽視語(yǔ)句:忽視并退出。
o??????? 許可語(yǔ)句:不立即執(zhí)行語(yǔ)句。推遲決策;繼續(xù)下一步。
·???????? 沒(méi)有:繼續(xù)下一步。
2.??? 我們目前正執(zhí)行保存的程序或函數(shù)嗎?
·???????? 是:執(zhí)行查詢并退出。
·???????? 否:繼續(xù)下一步。
3.??? 是否有--replicate-*-table規(guī)則?
·???????? 沒(méi)有:執(zhí)行查詢并退出。
·???????? 有:繼續(xù)下一步并開始按所示順序評(píng)估表規(guī)則(首先是非通配規(guī)則,然后是通配規(guī)則)。只有待更新的表根據(jù)這些規(guī)則進(jìn)行比較(INSERT INTO sales SELECT * FROM prices:只有sales根據(jù)這些規(guī)則進(jìn)行比較)。如果要更新幾個(gè)表(多表語(yǔ)句),第1個(gè)匹配的表(匹配“do”或“ignore”)獲贏。也就是說(shuō),根據(jù)這些規(guī)則比較第1個(gè)表。然后,如果不能進(jìn)行決策,根據(jù)這些規(guī)則比較第2個(gè)表等等。
4.??? 是否有--replicate-do-table規(guī)則?
·???????? 有:表匹配嗎?
o??????? 是:執(zhí)行查詢并退出。
o??????? 否:繼續(xù)下一步。
·???????? 沒(méi)有:繼續(xù)下一步。
5.??? 是否有--replicate-ignore-table規(guī)則?
·???????? 有:表匹配嗎?
o??????? 是:忽視查詢并退出。
o??????? 否:繼續(xù)下一步。
·???????? 沒(méi)有:繼續(xù)下一步。
6.??? 是否有--replicate-wild-do-table規(guī)則?
·???????? 有:表匹配嗎?
o??????? 是:執(zhí)行查詢并退出。
o??????? 否:繼續(xù)下一步。
·???????? 沒(méi)有:繼續(xù)下一步。
7.??? 是否有--replicate-wild-ignore-table規(guī)則?
·???????? 有:表匹配嗎?
o??????? 是:忽視查詢并退出。
o??????? 否:繼續(xù)下一步。
·???????? 沒(méi)有:繼續(xù)下一步。
8.??? 沒(méi)有匹配的--replicate-*-table規(guī)則。要根據(jù)這些規(guī)則測(cè)試其它表嗎?
·???????? 是:執(zhí)行循環(huán)。
·???????? 否:我們現(xiàn)在已經(jīng)測(cè)試了所有待更新的表,結(jié)果不能匹配任何規(guī)則。是否有--replicate-do-table或--replicate-wild-do-table規(guī)則?
o??????? 有:有“do”規(guī)則但不匹配。忽視查詢并退出。
o??????? 沒(méi)有:執(zhí)行查詢并退出。
Q:如果主服務(wù)器正在運(yùn)行并且不想停止主服務(wù)器,怎樣配置一個(gè)從服務(wù)器?
A:有多種方法。如果你在某時(shí)間點(diǎn)做過(guò)主服務(wù)器備份并且記錄了相應(yīng)快照的二進(jìn)制日志名和偏移量(通過(guò)SHOW MASTER STATUS命令的輸出),采用下面的步驟:
1.??? 確保從服務(wù)器分配了一個(gè)唯一的服務(wù)器ID號(hào)。
2.??? 在從服務(wù)器上執(zhí)行下面的語(yǔ)句,為每個(gè)選項(xiàng)填入適當(dāng)?shù)闹担?/p>
??????????? 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.??? 在從服務(wù)器上執(zhí)行START SLAVE語(yǔ)句。
如果你沒(méi)有備份主服務(wù)器,這里是一個(gè)創(chuàng)建備份的快速程序。所有步驟都應(yīng)該在主服務(wù)器主機(jī)上執(zhí)行。
1.??? 發(fā)出該語(yǔ)句:
???? mysql> FLUSH TABLES WITH READ LOCK;
2.??? 仍然加鎖時(shí),執(zhí)行該命令(或它的變體):
???? shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql
3.??? 發(fā)出該語(yǔ)句并且確保記錄了以后用到的輸出:
???? mysql>SHOW MASTER STATUS;
4.??? 釋放鎖:
???? mysql> UNLOCK TABLES;
一個(gè)可選擇的方法是,轉(zhuǎn)儲(chǔ)主服務(wù)器的SQL來(lái)代替前面步驟中的二進(jìn)制復(fù)制。要這樣做,你可以在主服務(wù)器上使用mysqldump --master-data,以后裝載SQL轉(zhuǎn)儲(chǔ)到到你的從服務(wù)器。然而,這比進(jìn)行二進(jìn)制復(fù)制速度慢。
不管你使用這兩種方法中的那一個(gè),當(dāng)你有一個(gè)快照和記錄了日志名與偏移量時(shí),后來(lái)根據(jù)說(shuō)明操作。你可以使用相同的快照建立多個(gè)從服務(wù)器。一旦你擁有主服務(wù)器的一個(gè)快照,可以等待創(chuàng)建一個(gè)從服務(wù)器,只要主服務(wù)器的二進(jìn)制日志完整。兩個(gè)能夠等待的時(shí)間實(shí)際的限制是指在主服務(wù)器上保存二進(jìn)制日志的可用硬盤空間和從服務(wù)器同步所用的時(shí)間。
你也可以使用LOAD DATA FROM MASTER。這是一個(gè)方便的語(yǔ)句,它傳輸一個(gè)快照到從服務(wù)器并且立即調(diào)整日志名和偏移量。將來(lái),LOAD DATA FROM MASTER將成為創(chuàng)建從服務(wù)器的推薦方法。然而需要注意,它只工作在MyISAM 表上并且可能長(zhǎng)時(shí)間持有讀鎖定。它并不象我們希望的那樣高效率地執(zhí)行。如果你有大表,執(zhí)行FLUSH TABLES WITH READ LOCK語(yǔ)句后,這時(shí)首選方法仍然是在主服務(wù)器上制作二進(jìn)制快照。
Q:從服務(wù)器需要始終連接到主服務(wù)器嗎?
A:不,不需要。從服務(wù)器可以宕機(jī)或斷開連接幾個(gè)小時(shí)甚至幾天,重新連接后獲得更新信息。例如,你可以在通過(guò)撥號(hào)的鏈接上設(shè)置主服務(wù)器/從服務(wù)器關(guān)系,其中只是偶爾短時(shí)間內(nèi)進(jìn)行連接。這意味著,在任何給定時(shí)間,從服務(wù)器不能保證與主服務(wù)器同步除非你執(zhí)行某些特殊的方法。將來(lái),我們將使用選項(xiàng)來(lái)阻塞主服務(wù)器直到有一個(gè)從服務(wù)器同步。
Q:我怎樣知道從服務(wù)器與主服務(wù)器的最新比較? 換句話說(shuō),我怎樣知道從服務(wù)器復(fù)制的最后一個(gè)查詢的日期?
A:你可以查看SHOW SLAVE STATUS語(yǔ)句的Seconds_Behind_Master列的結(jié)果。參見6.3節(jié),“復(fù)制實(shí)施細(xì)節(jié)”。
當(dāng)從服務(wù)器SQL線程執(zhí)行從主服務(wù)器讀取的事件時(shí),它根據(jù)事件時(shí)間戳修改自己的時(shí)間(這是TIMESTAMP能夠很好復(fù)制的原因)。在SHOW PROCESSLIST語(yǔ)句輸出的Time列內(nèi),為從服務(wù)器SQL線程顯示的秒數(shù)是最后一個(gè)復(fù)制事件的時(shí)間戳和從服務(wù)器主機(jī)的實(shí)際時(shí)間之間相差的秒數(shù)。你可以使用它來(lái)確定最后一個(gè)復(fù)制事件的日期。注意,如果你的從服務(wù)器與主服務(wù)器連接斷開一個(gè)小時(shí),然后重新連接,在SHOW PROCESSLIST結(jié)果中,你可以立即看到從服務(wù)器SQL線程的Time值為3600。這可能是因?yàn)閺姆?wù)器執(zhí)行的語(yǔ)句是一個(gè)一小時(shí)之前的。
Q:我怎樣強(qiáng)制主服務(wù)器阻塞更新直到從服務(wù)器同步?
A:使用下面的步驟:
1.??? 在主服務(wù)器上,執(zhí)行這些語(yǔ)句:
???? mysql> FLUSH TABLES WITH READ LOCK;
???? mysql> SHOW MASTER STATUS;
?
記錄SHOW語(yǔ)句的輸出的日志名和偏移量。這些是復(fù)制坐標(biāo)。
2.??? 在從服務(wù)器上,發(fā)出下面的語(yǔ)句,其中Master_POS_WAIT()函數(shù)的參量是前面步驟中的得到的復(fù)制坐標(biāo)值:
???? mysql> SELECT MASTER_POS_WAIT('log_name', log_offset);
SELECT語(yǔ)句阻塞直到從服務(wù)器達(dá)到指定的日志文件和偏移量。此時(shí),從服務(wù)器與主服務(wù)器同步,語(yǔ)句返回。
3.??? 在主服務(wù)器上,發(fā)出下面的語(yǔ)句允許主服務(wù)器重新開始處理更新:
???? mysql> UNLOCK TABLES;
Q:當(dāng)設(shè)置雙向復(fù)制時(shí)我應(yīng)該知道發(fā)出那些語(yǔ)句?
A:MySQL復(fù)制目前不支持主服務(wù)器和從服務(wù)器之間的任何鎖定協(xié)議來(lái)保證分布式(跨服務(wù)器)更新的原子性。換句話說(shuō),這樣做是可能的:客戶A根據(jù)協(xié)作-主服務(wù)器1更新,同時(shí),在它傳給協(xié)作-主服務(wù)器2之前,客戶B能夠根據(jù)協(xié)作-主服務(wù)器2更新,這樣客戶A的更新與它在協(xié)作-主服務(wù)器1的更新不同。這樣,當(dāng)客戶A根據(jù)協(xié)作-主服務(wù)器2更新時(shí),它產(chǎn)生的表與在協(xié)作-主服務(wù)器1上的不同,即使所有根據(jù)協(xié)作-主服務(wù)器2的更新已經(jīng)傳過(guò)來(lái)。這意味著,在雙向復(fù)制關(guān)系中,你不應(yīng)該把兩個(gè)服務(wù)器串連在一起,除非你確信任何順序的更新是安全的,或者除非你在客戶端代碼中注意怎樣避免更新順序錯(cuò)誤。
你還必須認(rèn)識(shí)到從更新角度,雙向復(fù)制實(shí)際上并不能顯著地提高性能(或者根本不能提高性能)。兩個(gè)服務(wù)器都需要做相同數(shù)量的更新,如同在一個(gè)服務(wù)器做的那樣。唯一的差別是鎖競(jìng)爭(zhēng)要少,這因?yàn)樵从诹硪粋€(gè)服務(wù)器的更新在一個(gè)從線程中序列化。即使這個(gè)益處可能被網(wǎng)絡(luò)延遲抵消。
Q:怎樣通過(guò)復(fù)制來(lái)提高系統(tǒng)的性能?
A:你應(yīng)將一個(gè)服務(wù)器設(shè)置為主服務(wù)器并且將所有寫指向該服務(wù)器。然后根據(jù)預(yù)算配置盡可能多的從服務(wù)器以及??臻g,并且在主服務(wù)器和從服務(wù)器之間分發(fā)讀取操作。你也可以用--skip-innodb、--skip-bdb、--low-priority-updates以及--delay-key-write=ALL選項(xiàng)啟動(dòng)從服務(wù)器,以便在從服務(wù)器端提高速度。在這種情況下,為了提高速度,從服務(wù)器使用非事務(wù)MyISAM表來(lái)代替InnoDB和BDB表。
Q:為了使用高性能的復(fù)制,我應(yīng)該在自己的應(yīng)用程序中怎樣準(zhǔn)備客戶端代碼?
A:如果你的代碼中數(shù)據(jù)庫(kù)訪問(wèn)部分已經(jīng)正確地模塊化,應(yīng)該能夠平滑和容易地轉(zhuǎn)換為在復(fù)制步驟中運(yùn)行的代碼。僅需要更改數(shù)據(jù)庫(kù)訪問(wèn)執(zhí)行部分,以便發(fā)送所有的寫操作到主服務(wù)器,以及發(fā)送讀操作到主服務(wù)器或某個(gè)從服務(wù)器。如果你的代碼沒(méi)有這個(gè)級(jí)別,設(shè)置一個(gè)復(fù)制系統(tǒng)以便清除。應(yīng)先通過(guò)下面的函數(shù)創(chuàng)建一個(gè)包裝庫(kù)或模塊:
·???????? safe_writer_connect()
·???????? safe_reader_connect()
·???????? safe_reader_statement()
·???????? safe_writer_statement()
每個(gè)函數(shù)名的safe_意味著函數(shù)比較小心地處理所有錯(cuò)誤。你可以使用不同名的函數(shù)。重要是對(duì)于讀連接、寫連接、讀和寫有一個(gè)統(tǒng)一的接口。
然后,你應(yīng)該轉(zhuǎn)換客戶端代碼使用包裝庫(kù)。剛開始這可能是痛苦和恐慌的過(guò)程,但從長(zhǎng)遠(yuǎn)來(lái)看是值得的。使用剛才討論的方法的所有應(yīng)用程序都能夠利用主服務(wù)器/從服務(wù)器配置的優(yōu)越性,即使是含有多個(gè)從服務(wù)器的配置。代碼非常容易維護(hù),并且添加排錯(cuò)選項(xiàng)也很容易。你僅需要修改一兩個(gè)函數(shù);例如,記錄每個(gè)語(yǔ)句執(zhí)行的時(shí)間,或者你的上千個(gè)語(yǔ)句中哪個(gè)語(yǔ)句發(fā)生了錯(cuò)誤。
如果你已經(jīng)編寫了許多代碼,你可能想使用replace工具自動(dòng)進(jìn)行轉(zhuǎn)換,該工具隨標(biāo)準(zhǔn)MySQL一起發(fā)布,或可以自己編寫轉(zhuǎn)換腳本。理想情況,你的代碼使用一致的程序轉(zhuǎn)換風(fēng)格。否則,可能最好重新編寫代碼,或者至少手工對(duì)其進(jìn)行規(guī)則化以使用一致的風(fēng)格。
Q:MySQL復(fù)制能夠何時(shí)和多大程度提高系統(tǒng)性能?
A:MySQL復(fù)制對(duì)于頻繁讀和頻繁寫的系統(tǒng)具有最大好處。理論上,通過(guò)使用單個(gè)主服務(wù)器/多從服務(wù)器設(shè)置,可以通過(guò)添加更多的從服務(wù)器來(lái)擴(kuò)充系統(tǒng),直到用完網(wǎng)絡(luò)帶寬,或者你的更新負(fù)載已經(jīng)增長(zhǎng)到主服務(wù)器不能處理的點(diǎn)。
在獲得的收益開始吃平之前,為了確定可以有多少?gòu)姆?wù)器,以及可以將你的站點(diǎn)的性能提高多少,需要知道查詢模式,并且要通過(guò)基準(zhǔn)測(cè)試并根據(jù)經(jīng)驗(yàn)確定一個(gè)典型的主服務(wù)器和從服務(wù)器中的讀?。棵腌娮x取量,或者max_reads)吞吐量和寫(max_writes)吞吐量的關(guān)系。通過(guò)一個(gè)假設(shè)的帶有復(fù)制的系統(tǒng),本例給出了一個(gè)非常簡(jiǎn)單的計(jì)算結(jié)果。
假設(shè)系統(tǒng)負(fù)載包括10%的寫和90%的讀取,并且我們通過(guò)基準(zhǔn)測(cè)試確定max_reads是1200 –2 × max_writes。換句話說(shuō),如果沒(méi)有寫操作,系統(tǒng)每秒可以進(jìn)行1,200次讀取操作,平均寫操作是平均讀操作所用時(shí)間的兩倍,并且關(guān)系是線性的。我們假定主服務(wù)器和每個(gè)從服務(wù)器具有相同的性能,并且我們有一個(gè)主服務(wù)器和N個(gè)從服務(wù)器。那么,對(duì)于每個(gè)服務(wù)器(主服務(wù)器或從服務(wù)器),我們有:
reads = 1200 – 2 × writes
reads = 9 × writes / (N + 1) (讀取是分離的, 但是寫入所有服務(wù)器)
9 × writes / (N + 1) + 2 × writes = 1200
writes = 1200 / (2 + 9/(N+1))
最后的等式表明了N個(gè)從服務(wù)器的最大寫操作數(shù),假設(shè)最大可能的讀取速率是每分鐘1,200次,讀操作與寫操作的比率是9。
如上分析可以得到下面的結(jié)論:
·???????? 如果N = 0(這表明沒(méi)有復(fù)制),系統(tǒng)每秒可以處理大約1200/11 = 109個(gè)寫操作。
·???????? 如果N = 1,每秒得到184個(gè)寫操作。
·???????? 如果N = 8,每秒得到400個(gè)寫操作。
·???????? 如果N = 17,每秒得到480個(gè)寫操作。
·???????? 最后,當(dāng) N 趨于無(wú)窮大(以及我們預(yù)算的負(fù)無(wú)窮大)時(shí),可以得到非常接近每秒600個(gè)寫操作,系統(tǒng)吞吐量增加將近5.5倍。然而,如果只用8個(gè)服務(wù)器,增加接近4倍。
請(qǐng)注意,這些計(jì)算假設(shè)網(wǎng)絡(luò)帶寬無(wú)窮大并忽略掉了其它一些因素,那些因素可能對(duì)系統(tǒng)產(chǎn)生重要的影響。在許多情況下,不能執(zhí)行與剛才類似的計(jì)算,即如果添加N臺(tái)復(fù)制從服務(wù)器,應(yīng)該準(zhǔn)確預(yù)報(bào)系統(tǒng)將發(fā)生哪些影響?;卮鹣旅娴膯?wèn)題應(yīng)能夠幫助你確定復(fù)制是否和在多大程度上能夠提高系統(tǒng)的性能:
·???????? 系統(tǒng)上的讀取/寫比例是什么?
·???????? 如果減少讀取操作,一個(gè)服務(wù)器可以多處理多少寫負(fù)載?
·???????? 網(wǎng)絡(luò)帶寬可滿足多少?gòu)姆?wù)器的需求?
Q:如何使用復(fù)制來(lái)提供冗余/高可用性?
A:利用目前的可用特性,必須設(shè)置一個(gè)主服務(wù)器和一個(gè)從服務(wù)器(或多個(gè)從服務(wù)器),以及寫一個(gè)腳本來(lái)監(jiān)視主服務(wù)器是否啟動(dòng)。如果主服務(wù)器失敗,通知應(yīng)用程序和從服務(wù)器切換主服務(wù)器。下面是一些建議:
·???????? 告知從服務(wù)器更改其主服務(wù)器,使用CHANGE MASTER TO語(yǔ)句。
·???????? 通知應(yīng)用程序主服務(wù)器位置的一個(gè)很好的方法是對(duì)主服務(wù)器提供動(dòng)態(tài)DNS入口。用bind可以使用nsupdate動(dòng)態(tài)更新DNS。
·???????? 應(yīng)該用--logs-bin選項(xiàng)而不用 --logs-slave-updates選項(xiàng)運(yùn)行從服務(wù)器。這樣,一旦你在其它從服務(wù)器上發(fā)出STOP SLAVE; RESET MASTER, 以及CHANGE MASTER TO語(yǔ)句,該從服務(wù)器可以切換為主服務(wù)器。例如,假設(shè)有下面的設(shè)置:
·??????????????? ???????WC
·??????????????? ????????\
·??????????????? ?????????v
·??????????????? ?WC----> M
·??????????????? ???????/ | \
·??????????????? ??????/? |? \
·??????????????? ?????v?? v?? v
·??????????????? ????S1?? S2? S3
M代表主服務(wù)器,S代表從服務(wù)器,WC代表發(fā)出數(shù)據(jù)庫(kù)寫和讀取操作的客戶;只發(fā)出數(shù)據(jù)庫(kù)讀取操作的客戶沒(méi)有給出,因?yàn)樗鼈儾恍枰袚Q。S1、S2以及S3是從服務(wù)器,用--logs-bin選項(xiàng)而沒(méi)有用--logs-slave-updates運(yùn)行。因?yàn)閺姆?wù)器收到的主服務(wù)器的更新沒(méi)有記錄在二進(jìn)制日志中,除非指定 --logs-slave-updates選項(xiàng),每個(gè)從服務(wù)器上的二進(jìn)制日志是空的。如果因?yàn)槟承┰?strong>M 變得不可用,你可以選取一個(gè)從服務(wù)器變?yōu)樾碌闹鞣?wù)器。例如,如果你選取了S1,所有WC應(yīng)該重新指向S1和S2,并且S3然后應(yīng)從S1復(fù)制。
確保所有從服務(wù)器已經(jīng)處理了中繼日志中的所有語(yǔ)句。在每個(gè)從服務(wù)器上,發(fā)出STOP SLAVE IO_THREAD語(yǔ)句,然后檢查SHOW PROCESSLIST語(yǔ)句的輸出,直到你看到Has read all relay log。當(dāng)所有從服務(wù)器都執(zhí)行完這些,它們可以被重新配置為一個(gè)新的設(shè)置。在被提升為主服務(wù)器的從服務(wù)器S1上,發(fā)出STOP SLAVE和RESET MASTER語(yǔ)句。
在其它從服務(wù)器S2和S3上,使用STOP SLAVE和CHANGE MASTER TO MASTER_HOST='S1'(其中'S1'表示S1實(shí)際的主機(jī)名)。為CHANGE MASTER添加關(guān)于從S2或S3如何連接到S1的所有信息(user、password、port)。在CHANGE MASTER命令中,不需要指定從其讀取的S1的二進(jìn)制日志名或二進(jìn)制日志位置:我們知道它是第1個(gè)二進(jìn)制日志,位置是4,這是CHANGE MASTER命令的默認(rèn)值。最后,在S2和S3上使用START SLAVE 命令。
然后,指示所有WC 把它們的語(yǔ)句指向S1。此后,WC發(fā)出的所有發(fā)送到S1的更新語(yǔ)句被寫入S1的二進(jìn)制日志,S1則包含M死掉之后的發(fā)送到 S1的每一個(gè)更新語(yǔ)句。
結(jié)果是下面的配置:
?????? WC
????? /
????? |
WC?? |? M(unavailable)
? \?? |
?? \? |
??? v v
???? S1<--S2? S3
????? ^?????? |
????? +-------+
當(dāng) M重新啟動(dòng)后,你必須在M上發(fā)出相同的CHANGE MASTER語(yǔ)句,與在S2和S3上發(fā)出的語(yǔ)句一樣,以便M變?yōu)?strong>S1的從服務(wù)器并且恢復(fù)在它宕機(jī)后丟失的所有WC寫操作。要把 M 再次作為主服務(wù)器(例如,因?yàn)樗枪δ茏顝?qiáng)的機(jī)器),使用前面的步驟,好像S1不可用并且M變?yōu)橐粋€(gè)新的主服務(wù)器一樣。在這個(gè)過(guò)程中,在S1、S2以及S3作為M的從服務(wù)器之前,不要忘記在M上運(yùn)行RESET MASTER。否則,它們可能拾取M變得不可用之前的舊WC寫操作。
我們目前正在MySQL集成自動(dòng)主服務(wù)器選擇系統(tǒng),但在準(zhǔn)備好之前,你必須創(chuàng)建自己的監(jiān)控工具。
如果你遵從了上述說(shuō)明,復(fù)制設(shè)置仍然不工作,首先檢查下面各項(xiàng):
·???????? 檢查錯(cuò)誤日志的消息。許多用戶遇到問(wèn)題后沒(méi)有及時(shí)地這樣做而浪費(fèi)了時(shí)間。
·???????? 主服務(wù)器記錄到了二進(jìn)制日志?用SHOW MASTER STATUS檢查。如果已經(jīng)記錄,Position應(yīng)為非零。如果沒(méi)有記錄,確認(rèn)正用log-bin和server-id選項(xiàng)運(yùn)行主服務(wù)器。
·???????? 是否從服務(wù)器在運(yùn)行?使用SHOWSHOW SLAVE STATUS檢查是否slave_IO_Running和slave_SQL_Running的值均為Yes。如果不是,驗(yàn)證當(dāng)啟動(dòng)從服務(wù)器時(shí)使用的選項(xiàng)。
·???????? 如果從服務(wù)器正在運(yùn)行,建立了與主服務(wù)器的連接嗎?使用SHOW PROCESSLIST,找出I/O和SQL線程并檢查它們的State列看它們?nèi)绾物@示。參見6.3節(jié),“復(fù)制實(shí)施細(xì)節(jié)”。如果I/O線程狀態(tài)為Connecting to master,驗(yàn)證主服務(wù)器上復(fù)制用戶的權(quán)限、主服務(wù)器主機(jī)名、DNS設(shè)置,是否主服務(wù)器真正在運(yùn)行,以及是否可以從從屬服務(wù)器訪問(wèn)。
·???????? 如果從服務(wù)器以前在運(yùn)行但是現(xiàn)在已經(jīng)停止,原因通常是在主服務(wù)器上成功的部分語(yǔ)句在從服務(wù)器上失敗了。如果你正確快照了主服務(wù)器,并且從來(lái)沒(méi)有不通過(guò)服務(wù)器線程修改從服務(wù)器上的數(shù)據(jù),這種現(xiàn)象不應(yīng)發(fā)生。如果發(fā)生,應(yīng)為一個(gè)bug或你遇到了一個(gè)6.7節(jié),“復(fù)制特性和已知問(wèn)題” 描述的已知的復(fù)制限制。如果是一個(gè)bug,參見6.11節(jié),“通報(bào)復(fù)制缺陷”查閱如何通報(bào)的說(shuō)明。
·???????? 如果某個(gè)在主服務(wù)器上成功的語(yǔ)句拒絕在從服務(wù)器上運(yùn)行,并且不能執(zhí)行完全的數(shù)據(jù)庫(kù)重新同步(即刪除從服務(wù)器的數(shù)據(jù)庫(kù)并從主服務(wù)器復(fù)制新的快照),嘗試:
1.??? 確定是否從服務(wù)器的表與主服務(wù)器的不同。盡力了解發(fā)生的原因。然后讓從服務(wù)器的表與主服務(wù)器的一樣并運(yùn)行START SLAVE。
2.??? 如果前面的步驟不工作或不適合,盡力了解手動(dòng)更新是否安全(如果需要),然后忽視來(lái)自主服務(wù)器的下一個(gè)語(yǔ)句。
3.??? 如果你確定可以跳過(guò)來(lái)自主服務(wù)器的下一個(gè)語(yǔ)句,執(zhí)行下面的語(yǔ)句:
4.????????????????? mysql> SET GLOBAL SQL_slave_SKIP_COUNTER = n;
5.????????????????? mysql> START SLAVE;
如果來(lái)自主服務(wù)器的下一個(gè)語(yǔ)句不使用AUTO_INCREMENT或LAST_INSERT_ID(),n 值應(yīng)為1。否則,值應(yīng)為2。使用AUTO_INCREMENT或LAST_INSERT_ID()的語(yǔ)句使用值2的原因是它們從主服務(wù)器的二進(jìn)制日志中取兩個(gè)事件。
6.??? 如果你確保從服務(wù)器啟動(dòng)時(shí)完好地與主服務(wù)器同步,并且沒(méi)有更新從服務(wù)器線程之外的表,則大概詫異是由于bug。如果你正運(yùn)行最近的版本,請(qǐng)通報(bào)該問(wèn)題。如果你正運(yùn)行舊版本MySQL,盡力升級(jí)到最新的產(chǎn)品版本。
如果你確定沒(méi)有用戶錯(cuò)誤,但復(fù)制仍然不工作或不穩(wěn)定,則是向我們發(fā)送bug通報(bào)的時(shí)候了。我們需要盡可能從你那兒獲得更多的信息已跟蹤bug。請(qǐng)花一些時(shí)間和努力編寫一份好的bug通報(bào)。
如果你有一個(gè)重復(fù)的測(cè)試案例來(lái)說(shuō)明bug,請(qǐng)把它輸入我們的bug數(shù)據(jù)庫(kù),位置為http://bugs.mysql.com/。如果你有一個(gè)“phantom”問(wèn)題(不能按照期望進(jìn)行復(fù)制),則使用下面的程序:
1.??? 確認(rèn)未包括用戶錯(cuò)誤。例如,如果你不用從服務(wù)器線程來(lái)更新從服務(wù)器,數(shù)據(jù)將不同步,并且會(huì)遇到唯一的鍵值違背更新。在這種情況下,從服務(wù)器線程停止并等待你手動(dòng)清理表使它們同步。這不是復(fù)制問(wèn)題。這是一個(gè)外部接口問(wèn)題造成復(fù)制失敗。
2.??? 用--logs-slave-updates和--logs-bin選項(xiàng)運(yùn)行從服務(wù)器。這些選項(xiàng)使從服務(wù)器將從主服務(wù)器接收的更新記入自己的二進(jìn)制日志。
3.??? 重新設(shè)置復(fù)制狀態(tài)之前保存所有的證據(jù)。如果我們沒(méi)有信息或只有粗略的信息,則難以或不可能跟蹤問(wèn)題。應(yīng)搜集的證據(jù)為:
·???????? 所有主服務(wù)器的二進(jìn)制日志
·???????? 所有從服務(wù)器的二進(jìn)制日志
·???????? 你發(fā)現(xiàn)問(wèn)題時(shí)主服務(wù)器的SHOW MASTER STATUS的輸出
·???????? 你發(fā)現(xiàn)問(wèn)題時(shí)主服務(wù)器的SHOW SLAVE STATUS的輸出
·???????? 主服務(wù)器和從服務(wù)器的錯(cuò)誤日志
4.??? 使用mysqlbinlog檢查二進(jìn)制日志。下面命令應(yīng)有助于發(fā)現(xiàn)有問(wèn)題的查詢,例如:
5.??????????? shell> mysqlbinlog -j pos_from_slave_status \
6.??????????? ???????????/path/to/log_from_slave_status | head
搜集了問(wèn)題的證據(jù)后,首先作為一個(gè)測(cè)試案例隔離開。然后將問(wèn)題輸入我們的bug數(shù)據(jù)庫(kù),位置為http://bugs.mysql.com/,應(yīng)提供盡可能多的信息。
當(dāng)將多個(gè)服務(wù)器配置為復(fù)制主服務(wù)器時(shí),使用auto_increment時(shí)應(yīng)采取特殊步驟以防止鍵值沖突,否則插入行時(shí)多個(gè)主服務(wù)器會(huì)試圖使用相同的auto_increment值。
服務(wù)器變量auto_increment_increment和auto_increment_offset可以幫助協(xié)調(diào)多主服務(wù)器復(fù)制和AUTO_INCREMENT列。每個(gè)變量有一個(gè)默認(rèn)的(并且是最小的)值1,最大值為65,535。
將這些變量設(shè)置為非沖突的值,當(dāng)在同一個(gè)表主插入新行時(shí),多主服務(wù)器配置主的服務(wù)器將不會(huì)與AUTO_INCREMENT值沖突。
這兩個(gè)變量這樣影響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以獲得這些變量的當(dāng)前值)。
·???????? auto_increment_offset確定AUTO_INCREMENT列值的起點(diǎn)。影響到在復(fù)制設(shè)置主可以有多少主服務(wù)器(例如將該值設(shè)置為10表示設(shè)置可以支持10個(gè)服務(wù)器)。
考慮下面的命令,假定在前面所示示例中的相同的會(huì)話中執(zhí)行這些命令:
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)
詳細(xì)信息參見5.3.3節(jié),“服務(wù)器系統(tǒng)變量”。
這是MySQL參考手冊(cè)的翻譯版本,關(guān)于MySQL參考手冊(cè),請(qǐng)?jiān)L問(wèn)dev.mysql.com。 原始參考手冊(cè)為英文版,與英文版參考手冊(cè)相比,本翻譯版可能不是最新的。