一。複製的原理
MySQL複製基於主服務器在二進制日誌中跟蹤所有對數據庫的更改(更新、刪除等等)。每個從服務器從主服務器接收主服務器已經記錄到其二進制日誌的保存的更新,以便從服務器可以對其數據拷貝執行相同的更新。
將主服務器的數據拷貝到從服務器的一個途徑是使用LOAD DATA FROM MASTER語句。請注意LOAD DATA FROM MASTER目前只在所有表使用MyISAM存儲引擎的主服務器上工作。並且,該語句將獲得全局讀鎖定。
主服務器創建一個線程將二進制日誌中的內容發送到從服務器。該線程可以識別爲主服務器上SHOW PROCESSLIST的輸出中的Binlog Dump線程。
從服務器I/O線程讀取主服務器Binlog Dump線程發送的內容並將該數據拷貝到從服務器數據目錄中的本地文件中,即中繼日誌。
第3個線程是SQL線程,是從服務器創建用於讀取中繼日誌並執行日誌中包含的更新。
有多個從服務器的主服務器創建爲每個當前連接的從服務器創建一個線程;每個從服務器有自己的I/O和SQL線程。
二。複製線程的狀態
Sending binlog event to slave
二進制日誌由各種事件組成,一個事件通常爲一個更新加一些其它信息。線程已經從二進制日誌讀取了一個事件並且正將它發送到從服務器。
線程已經讀完二進制日誌文件並且正打開下一個要發送到從服務器的日誌文件。
線程已經從二進制日誌讀取所有主要的更新並已經發送到了從服務器。線程現在正空閒,等待由主服務器上新的更新導致的出現在二進制日誌中的新事件。
線程停止時發生的一個很簡單的狀態。
Connecting to master
線程正試圖連接主服務器。
建立同主服務器之間的連接後立即臨時出現的狀態。
建立同主服務器之間的連接後立即臨時出現的狀態。
建立同主服務器之間的連接後立即臨時出現的狀態。線程向主服務器發送一條請求,索取從請求的二進制日誌文件名和位置開始的二進制日誌的內容。
如果二進制日誌轉儲請求失敗(由於沒有連接),線程進入睡眠狀態,然後定期嘗試重新連接。可以使用–master-connect-retry選項指定重試之間的間隔。
線程正嘗試重新連接主服務器。
線程已經連接上主服務器,正等待二進制日誌事件到達。如果主服務器正空閒,會持續較長的時間。如果等待持續slave_read_timeout秒,則發生超時。此時,線程認爲連接被中斷並企圖重新連接。
線程已經讀取一個事件,正將它複製到中繼日誌供SQL線程來處理。
讀取時(由於沒有連接)出現錯誤。線程企圖重新連接前將睡眠master-connect-retry秒。
線程正嘗試重新連接主服務器。當連接重新建立後,狀態變爲Waiting for master to send event。
正使用一個非零relay_log_space_limit值,中繼日誌已經增長到其組合大小超過該值。I/O線程正等待直到SQL線程處理中繼日誌內容並刪除部分中繼日誌文件來釋放足夠的空間。
線程停止時發生的一個很簡單的狀態。
Reading event from the relay log
線程已經從中繼日誌讀取一個事件,可以對事件進行處理了。
線程已經處理了中繼日誌文件中的所有事件,現在正等待I/O線程將新事件寫入中繼日誌。
線程停止時發生的一個很簡單的狀態。
三。複製傳遞和狀態文件
從服務器靠中繼日誌來接收從主服務器上傳回來的日誌。並依靠狀態文件來記錄已經從主服務器接收了哪些日誌,已經恢復了哪些日誌。
1.每次I/O線程啓動時創建一個新的中繼日誌。
2.當日志被刷新時;例如,用FLUSH LOGS或mysqladmin flush-logs。
3.噹噹前的中繼日誌文件變得太大時。“太大”含義的確定方法:
max_relay_log_size,如果max_relay_log_size > 0
max_binlog_size,如果max_relay_log_size = 0
狀態文件名默認爲master.info和relay-log.info。其中IO線程更新master.info文件,SQL線程更新relay-log.info文件。
文件中的行和SHOW SLAVE STATUS顯示的列的對應關係爲:
master.info文件:
行 描述
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
行 描述
1 Relay_Log_File
2 Relay_Log_Pos
3 Relay_Master_Log_File
4 Exec_Master_Log_Pos
四。複製的配置步驟
GRANT REPLICATION SLAVE ON *.* TO ‘rep’@'%’ IDENTIFIED BY ‘logzgh’;
授予賬戶SUPER和RELOAD全局權限。
爲所有想要裝載的表授予SELECT權限。任何該 賬戶不能SELECT的主服務器上的表被LOAD DATA FROM MASTER忽略掉。
情況一:若只用到MyISAM表
mysql> FLUSH TABLES WITH READ LOCK;
(刷新所有表並且阻止其它寫入,不要退出該客戶端,以保持讀鎖有效。若退出,讀鎖就會釋放。)
比較簡單的辦法就是把數據目錄打包壓縮。
$ tar -cvf /home/mysql/snapshot.tar ./data (在master上)
$ tar -xvf /home/mysql/snapshot.tar (在slave上)
可能不需要同步 mysql 數據庫,因爲在slave上的權限表和master不一樣。這時,解開壓縮包的時候要排除它。
同時在壓縮包中也不要包含任何日誌文件,和狀態文件master.info、relay-log.info。
mysql> SHOW MASTER STATUS;
+——————+———-+————–+——————+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+——————+———-+————–+——————+
| mysql-bin.000058 | 45036137 | | |
+——————+———-+————–+——————+
情況二:若用到InnoDB表
方法一:使用InnoDB Hot Backup工具。它無需在master上請求任何鎖就能做到快照的一致性,並且在後面中在slave上要用到的快照中已經記錄了日誌文件名以及偏移位置。 ([url]http://www.innodb.com/manual.php[/url])
方法二:記錄當前日誌文件及偏移位置,在master關閉前執行:
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
儘快記下顯示結果中的日誌文件及偏移位置。然後,在不解鎖的情況下關閉master,確保master上的快照和記錄的結果一致。
關閉master服務器,$ mysqladmin -u root shutdown
拷貝 InnoDB 數據文件,日誌文件,以及表結構定義文件(.frm文件)。
情況三:可以同時用於MyISAM和InnoDB表
在master上做SQL轉儲而無需如上所述備份二進制日誌。運行mysqldump –master-data命令,然後把結果文件轉儲到slave上。
不過,這比拷貝二進制日誌慢點。
在master上my.cnf文件:(重啓生效)
[mysqld]
log_bin
server_id=1 (值是 1 到 2^32-1 之間的正整數)
在slave上my.cnf文件:
[mysqld]
server_id=2 (ID必須和master的ID不同。若有多個slave,則每個slave都必須有唯一的id。)
master_host=db-master.mycompany.com
master_port=3306
master_user=rep
master_password=freitag
master_connect_retry=60 (若master宕機或者slave連接斷開,slave會定期嘗試連接到master上,重試的間隔由該選項來控制,默認值是60秒。)
report_host=db-slave.mycompany.com
slave_net_timeout=3600 (slave默認會在3600秒後,若還沒收到來自master的數據,則會當作網絡斷開的情況來處理。)
第一次啓動slave時,master.info不存在,它從my.cnf中讀取選項值,然後把它們保存在master.info中。
下次重啓slave時,它只讀取master.info的內容,而不會讀取my.cnf中的選項值。
想要使用不同的選項值,可以刪除master.info後重啓slave,或者使用CHANGE MASTER TO語句(推薦)重置選項值。
4.啓動從服務器線程
mysqld_safe –user=mysql –skip-slave-start & (啓動MySQL服務器,但不啓動slave)
設置master_log_file等參數
mysql> CHANGE MASTER TO MASTER_HOST=’qa-sandbox-1′,
MASTER_USER=’rep’,
MASTER_PASSWORD=’logzgh’,
MASTER_LOG_FILE=’mysql-bin.000007′,
MASTER_LOG_POS=471632;
執行這些程序後,從服務器應連接主服務器,並補充自從快照以來發生的任何更新。
如果你忘記設置主服務器的server-id值,從服務器不能連接主服務器。
應在主服務器的my.cnf文件中使用innodb_flush_log_at_trx_commit=1和sync-binlog=1。
mysql> show processlist; (檢查是否slave-start)
mysqld_safe –user=mysql –read-only & (啓動MySQL服務器,同時啓動slave的I/O線程)
mysql> STOP SLAVE;
mysql> RESET MASTER;
五.複製啓動選項
該選項讓從服務器只允許來自從服務器線程或具有SUPER權限的用戶的更新。可以確保從服務器不接受來自客戶的更新。
告訴從服務器只做默認數據庫(由USE所選擇)爲db_name的語句的複製。要指定多個數據庫,應多次使用該選項,每個數據庫使用一次。請注意不復制跨數據庫的語句
告訴從服務器線程只做對指定表的複製。要指定多個表,應多次使用該選項,每個表使用一次。同–replicate-do-db對比,允許跨數據庫更新。
告訴從服務器不要複製默認數據庫(由USE所選擇)爲db_name的語句。要想忽略多個數據庫,應多次使用該選項,每個數據庫使用一次。
告訴從服務器線程不要複製更新指定表的任何語句(即使該語句可能更新其它的表)。要想忽略多個表,應多次使用該選項,每個表使用一次。
告訴從服務器線程限制複製更新的表匹配指定的數據庫和表名模式的語句。模式可以包含‘%’和‘_’通配符,與LIKE模式匹配操作符具有相同的含義。要指定多個表,應多次使用該選項,每個表使用一次。該選項可以跨數據庫進行更新。
告訴從服務器線程不要複製表匹配給出的通配符模式的語句。要想忽略多個表,應多次使用該選項,每個表使用一次。該選項可以跨數據庫進行更新。
告訴從服務器如果默認數據庫(由USE所選擇)爲主服務器上的from_name,則翻譯爲to_name。隻影響含有表的語句
從服務器註冊過程中報告給主服務器的主機名或IP地址。該值出現在主服務器上SHOW SLAVE HOSTS的輸出中。如果不想讓從服務器自己在主服務器上註冊,則不設置該值。
連接從服務器的TCP/IP端口號,從服務器註冊過程中報告給主服務器。
告訴從服務器當服務器啓動時不啓動從服務器線程。使用START SLAVE語句在以後啓動線程。
通常情況,當出現錯誤時複製停止,這樣給你一個機會手動解決數據中的不一致性問題。該選項告訴從服務器SQL線程當語句返回任何選項值中所列的錯誤時繼續複製。
例如:
–slave-skip-errors=1062,1053
–slave-skip-errors=all
如果你在某時間點做過主服務器備份並且記錄了相應快照的二進制日誌名和偏移量(通過SHOW MASTER STATUS命令的輸出),採用下面的步驟:
2. 將備份文件拷到從服務器上。
3. 在從服務器上執行下面的語句,爲每個選項填入適當的值:
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;
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轉儲到到你的從服務器。然而,這比進行二進制複製速度慢。
2.升級從服務器時,應先關閉從服務器,升級到相應5.1.x版本,然後重啓從服務器並重新開始複製。5.1版本的從服務器能夠讀取升級前寫入的舊的中繼日誌並執行日誌中包含的語句。升級後從服務器創建的中繼日誌爲5.1格式。
4.Q:從服務器需要始終連接到主服務器嗎?
A:不,不需要。從服務器可以宕機或斷開連接幾個小時甚至幾天,重新連接後獲得更新信息。
A:你可以查看SHOW SLAVE STATUS語句的Seconds_Behind_Master列的結果。
A:使用下面的步驟:
1. 在主服務器上,執行這些語句:
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
記錄SHOW語句的輸出的日誌名和偏移量。這些是複製座標。
mysql> SELECT MASTER_POS_WAIT(’log_name’, log_offset);
SELECT語句阻塞直到從服務器達到指定的日誌文件和偏移量。此時,從服務器與主服務器同步,語句返回。
mysql> UNLOCK TABLES;
A:你應將一個服務器設置爲主服務器並且將所有寫指向該服務器。然後根據預算配置儘可能多的從服務器以及棧空間,並且在主服務器和從服務器之間分發讀取操作。你也可以用–skip-innodb、–skip-bdb、–low-priority-updates以及–delay-key- write=ALL選項啓動從服務器,以便在從服務器端提高速度。在這種情況下,爲了提高速度,從服務器使用非事務MyISAM表來代替InnoDB和 BDB表。