MySQL支持單向、異步複製,複製過程當中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。MySQL複製基於主服務器在二進制日誌中跟蹤全部對數據庫的更改(更新、刪除等等)。所以,要進行復制,必須在主服務器上啓用二進制日誌。每一個從服務器從主服務器接收主服務器上已經記錄到其二進制日誌的保存的更新。當一個從服務器鏈接主服務器時,它通知主服務器定位到從服務器在日誌中讀取的最後一次成功更新的位置。從服務器接收從那時起發生的任何更新,並在本機上執行相同的更新。而後封鎖並等待主服務器通知新的更新。從服務器執行備份不會干擾主服務器,在備份過程當中主服務器能夠繼續處理更新。
2、複製實現細節
MySQL使用3個線程來執行復制功能,其中兩個線程(Sql線程和IO線程)在從服務器,另一個線程(IO線程)在主服務器。當發出START SLAVE時,從服務器建立一個I/O線程,以鏈接主服務器並讓它發送記錄在其二進制日誌中的語句。主服務器建立一個線程將二進制日誌中的內容發送到從服務器。該線程能夠即爲主服務器上SHOW PROCESSLIST的輸出中的Binlog Dump線程。從服務器I/O線程讀取主服務器Binlog Dump線程發送的內容並將該數據拷貝到從服務器數據目錄中的本地文件中,即中繼日誌。第3個線程是SQL線程,由從服務器建立,用於讀取中繼日誌並執行日誌中包含的更新。在從服務器上,讀取和執行更新語句被分紅兩個獨立的任務。當從服務器啓動時,其I/O線程能夠很快地從主服務器索取全部二進制日誌內容,即便SQL線程執行更新的遠遠滯後。
一、複製線程狀態
經過show slave status\G和show master status能夠查看複製線程狀態。常見的線程狀態有:
(1)主服務器Binlog Dump線程
Has sent all binlog to slave; waiting for binlog to be updated
線程已經從二進制日誌讀取全部主要的更新並已經發送到了從服務器。線程如今正空閒,等待由主服務器上新的更新致使的出如今二進制日誌中的新事件。
(2)從服務器I/O線程狀態
Waiting for master to send event
線程已經鏈接上主服務器,正等待二進制日誌事件到達。若是主服務器正空閒,會持續較長的時間。若是等待持續slave_read_timeout秒,則發生超時。此時,線程認爲鏈接被中斷並企圖從新鏈接。
(3)從服務器SQL線程狀態
Reading event from the relay log
線程已經從中繼日誌讀取一個事件,能夠對事件進行處理了。
Has read all relay log; waiting for the slave I/O thread to update it
線程已經處理了中繼日誌文件中的全部事件,如今正等待I/O線程將新事件寫入中繼日誌。
二、複製過程當中使用的傳遞和狀態文件
默認狀況,中繼日誌使用host_name-relay-bin.nnnnnn形式的文件名,其中host_name是從服務器主機名,nnnnnn是序列號。中繼日誌與二進制日誌的格式相同,而且能夠用mysqlbinlog讀取。
從服務器在data目錄中另外建立兩個小文件。這些狀態文件默認名爲主master.info和relay-log.info。狀態文件保存在硬盤上,從服務器關閉時不會丟失。下次從服務器啓動時,讀取這些文件以肯定它已經從主服務器讀取了多少二進制日誌,以及處理本身的中繼日誌的程度。
若是要備份從服務器的數據,還應備份這兩個小文件以及中繼日誌文件。它們用來在恢復從服務器的數據後繼續進行復制。若是丟失了中繼日誌但仍然有relay-log.info文件,能夠經過檢查該文件來肯定SQL線程已經執行的主服務器中二進制日誌的程度。而後能夠用Master_Log_File和Master_LOG_POS選項執行CHANGE MASTER TO來告訴從服務器從新從該點讀取二進制日誌。
3、MySQL創建主從服務器配置方法
A、環境描述
服務器A(主) 192.168.1.106
服務器B(從) 192.168.1.107
Mysql版本:5.5.11
System OS:CentOS 5.6 X64
主從需同步的數據庫內容保持一致。
B、主從配置過程
主服務器
a)建立同步用戶
在主服務器上爲從服務器創建一個鏈接賬戶,該賬戶必須授予REPLICAITON SLAVE權限。
服務器A:
添加一個有 slave權限etuy
grant replication slave on *.* to 'replication'@'192.168.1.%' identified by '000000';
flush privileges;
b)修改mysql配置文件
[mysqld]
server-id = 1
log-bin=/data0/mysql/binlog/binlog
binlog-do-db = test
binlog-ignore-db=mysql
c)重啓mysql服務
# /data0/mysql/mysql restart
Restarting MySQL...
Stoping MySQL...
Starting MySQL...
d)、查看主服務器狀態
ysql>flush tables with read lock;
mysql>show master status\G
*************************** 1. row ***************************
File: binlog.000006
Position: 107
Binlog_Do_DB: test
Binlog_Ignore_DB: mysql
1 row in set (0.00 sec)
mysql>unlock tables;
注:這裏鎖表的目的是爲了生產環境中不讓進新的數據,好讓從服務器定位同步位置。初次同步完成後,記得解鎖。 php
從服務器
a)修改mysql配置文件 html
[mysqld]
server-id = 2
log-bin = /data0/mysql/binlog/binlog
replicate-do-db = test
replicate-ignore-db = mysql,information_schema
replicate-ignore-table=test.table_name#排除表
b)重啓mysql服務
# /data0/mysql/mysql restart
Restarting MySQL...
Stoping MySQL...
Starting MySQL...
c)用change master語句指定同步位置
mysql>change master to master_host='192.168.1.106', master_user='replication', master_password='000000', master_log_file='binlog.000006', master_log_pos=107;
注:master_log_file,master_log_pos由上面主服務器查出的狀態值中肯定。master_log_file對應File,master_log_pos對應Position。
mysql 5.x以上版本已經不支持在配置文件中指定主服務器相關選項。
d)啓動從服務器線程 mysql
mysql>start slave;
我在實際操做中出現了啓動不了的狀況,錯誤提示出下: mysql> start slave; ERROR 2006 (HY000): MySQL server has gone away No connection. Trying to reconnect... Connection id: 3 Current database: data_center ERROR 1200 (HY000): The server is not configured as slave; fix in config file or with CHANGE MASTER TO 使用show slave status查看狀態時發現有這樣的錯誤提示: Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work (or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it). GOOGLE說是從服務器配置文件裏的server_id沒有生效,使用set global server_id=2;動態修改server_id,而後start slave;成功
e)查看從服務器狀態
mysql>show slave status\G;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
查看以上兩項的值,均爲Yes則表示狀態正常。
C、測試主從同步 web
先在主庫中插入一條新的數據 sql
mysql> use test
Database changed
mysql> desc wp_terms;
+------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra
+------------+---------------------+------+-----+---------+----------------+
| term_id | bigint(20) unsigned | NO | PRI | NULL | auto_increment
| name | varchar(200) | NO | MUL |
| slug | varchar(200) | NO | UNI |
| term_group | bigint(10) | NO | | 0
+------------+---------------------+------+-----+---------+----------------+
4 rows in set (0.02 sec)
mysql> insert wp_terms values(1116,'MikeTestMySQL','Mike-Test-Mysql-Repli',0);
Query OK, 1 row affected (0.03 sec)
在從庫中查詢,看到以前主庫新增的數據就成功了。
mysql> select * from test.wp_terms where term_id=1116;
+---------+---------------+-----------------------+------------+
| term_id | name | slug | term_group
+---------+---------------+-----------------------+------------+
| 1116 | MikeTestMySQL | Mike-Test-Mysql-Repli | 0
+---------+---------------+-----------------------+------------+
1 row in set (0.00 sec)
4、MySQL創建主主服務器配置方法
MySQL主主服務器的思路和主從差很少,本質就是讓多臺MySQL服務器間互爲主從。
下面的是完整配置過程,如已按上面配置了主從架構,只需調整差別部分就行了。 shell
A、環境描述 數據庫
服務器A(主) 192.168.1.106
服務器B(主) 192.168.1.107
Mysql版本:5.5.11
System OS:CentOS 5.6 X64
主從需同步的數據庫內容保持一致。 緩存
B、主主配置過程 安全
a)建立同步用戶 服務器
在主服務器上爲從服務器創建一個鏈接賬戶,該賬戶必須授予REPLICAITON SLAVE權限。
這裏服務器A和服務器B互爲主從,因此都要分別創建一個同步用戶。
服務器A和B:
grant replication slave on *.* to 'replication'@'192.168.1.%' identified by '000000';
flush privileges;
b)修改mysql配置文件
[mysqld]
server-id = 1
log-bin=/data0/mysql/binlog/binlog
binlog-do-db = test
binlog-ignore-db=mysql
#主主需加入的部分
log-slave-updates
sync_binlog=1
auto_increment_offset=1
auto_increment_increment=2
replicate-do-db = test
replicate-ignore-db = mysql,information_schema
服務器B
[mysqld]
server-id = 2
log-bin = /data0/mysql/binlog/binlog
replicate-do-db = test
replicate-ignore-db = mysql,information_schema
#主主須要加入部分
binlog-do-db = test
binlog-ignore-db=mysql
log-slave-updates
sync_binlog=1
auto_increment_offset=2
auto_increment_increment=2
c)分別重啓服務器A、B上的mysql服務
# /data0/mysql/mysql restart
Restarting MySQL...
Stoping MySQL...
Starting MySQL...
d)、分別在服務器A、B上查看作爲主服務器狀態
A服務器
mysql>flush tables with read lock;
mysql> show master status\G
*************************** 1. row ***************************
File: binlog.000007
Position: 107
Binlog_Do_DB: test
Binlog_Ignore_DB: mysql
1 row in set (0.00 sec)
mysql>unlock tables;
B服務器
mysql> show master status\G
*************************** 1. row ***************************
File: binlog.000005
Position: 107
Binlog_Do_DB: test
Binlog_Ignore_DB: mysql
1 row in set (0.00 sec)
注:這裏鎖表的目的是爲了生產環境中不讓進新的數據,好讓從服務器定位同步位置。初次同步完成後,記得解鎖。
c)分別在服務器A、B上用change master語句指定同步位置
A、服務器
mysql>change master to master_host='192.168.1.107', master_user='replication', master_password='000000', master_log_file='binlog.000005', master_log_pos=107;
B、服務器
mysql>change master to master_host='192.168.1.106', master_user='replication', master_password='000000', master_log_file='binlog.000007', master_log_pos=107;
注:master_log_file,master_log_pos由上面主服務器查出的狀態值中肯定。master_log_file對應File,master_log_pos對應Position。
mysql 5.x以上版本已經不支持在配置文件中指定主服務器相關選項。
d)分別在服務器A、B上啓動從服務器線程
mysql>start slave;
e)分別在服務器A、B上查看從服務器狀態
mysql>show slave status\G;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
查看以上兩項的值,均爲Yes則表示狀態正常。
C、測試主主同步
5、配置參數說明
server-id
ID值惟一的標識了複製羣集中的主從服務器,所以它們必須各不相同。master_id必須爲1到232–1之間的一個正整數值,slave_id值必須爲2到232–1之間的一個正整數值。
log-bin
表示打開binlog,打開該選項才能夠經過I/O寫到Slave的relay-log,也是能夠進行replication的前提;
binlog-do-db
表示須要記錄進制日誌的數據庫。若是有多個數據庫可用逗號分隔,或者使用多個binlog-do-db選項
binlog-ignore-db
表示不須要記錄二進制日誌的數據庫。若是有多個數據庫可用逗號分隔,或者使用多個binlog-do-db選項
replicate-do-db
表示須要同步的數據庫,若是有多個數據庫可用逗號分隔,或者使用多個replicate-do-db選項
replicate-ignore-db=mysql
表示不須要同步的數據庫,若是有多個數據庫可用逗號分隔,或者使用多個replicate-ignore-db=mysql選項
log-slave-updates
配置從庫上的更新操做是否寫入二進制文件,若是這臺從庫,還要作其餘從庫的主庫,那麼就須要打這個參數,以便從庫的從庫可以進行日誌同步
slave-skip-errors
在複製過程,因爲各類緣由致使binlog中的sql出錯,默認狀況下,從庫會中止複製,要用戶介入。能夠設置Slave-skip-errors來定義錯誤號,若是複製過程當中遇到的錯誤號是定義的錯誤號,即可以跳過。若是從庫是用來作備份,設置這個參數會存在數據不一致,不要使用。若是是分擔主庫的查詢壓力,能夠考慮。
sync_binlog=1 or N
sync_binlog的默認值是0,這種模式下,MySQL不會同步到磁盤中去。這樣的話,MySQL依賴操做系統來刷新二進制日誌binary log,就像操做系統刷其餘文件的機制同樣。所以若是操做系統或機器(不只僅是MySQL服務器)崩潰,有可能binlog中最後的語句丟失了。要想防止這種狀況,你可使用sync_binlog全局變量,使binlog在每N次binlog寫入後與硬盤同步。當sync_binlog變量設置爲1是最安全的,由於在crash崩潰的狀況下,你的二進制日誌binary log只有可能丟失最多一個語句或者一個事務。可是,這也是最慢的一種方式(除非磁盤有使用帶蓄電池後備電源的緩存cache,使得同步到磁盤的操做很是快)。
即便sync_binlog設置爲1,出現崩潰時,也有可能表內容和binlog內容之間存在不一致性。若是使用InnoDB表,MySQL服務器處理COMMIT語句,它將整個事務寫入binlog並將事務提交到InnoDB中。若是在兩次操做之間出現崩潰,重啓時,事務被InnoDB回滾,但仍然存在binlog中。能夠用–innodb-safe-binlog選項來增長InnoDB表內容和binlog之間的一致性。(註釋:在MySQL 5.1中不須要–innodb-safe-binlog;因爲引入了XA事務支持,該選項做廢了),該選項能夠提供更大程度的安全,使每一個事務的 binlog(sync_binlog =1)和(默認狀況爲真)InnoDB日誌與硬盤同步,該選項的效果是崩潰後重啓時,在滾回事務後,MySQL服務器從binlog剪切回滾的 InnoDB事務。這樣能夠確保binlog反饋InnoDB表的確切數據等,並使從服務器保持與主服務器保持同步(不接收回滾的語句)。
auto_increment_offset和auto_increment_increment
auto_increment_increment和auto_increment_offset用於主-主服務器(master-to-master)複製,並能夠用來控制AUTO_INCREMENT列的操做。兩個變量都可以設置爲全局或局部變量,而且假定每一個值均可覺得1到65,535之間的整數值。將其中一個變量設置爲0會使該變量爲1。
這兩個變量影響AUTO_INCREMENT列的方式:auto_increment_increment控制列中的值的增量值,auto_increment_offset肯定AUTO_INCREMENT列值的起點。
若是auto_increment_offset的值大於auto_increment_increment的值,則auto_increment_offset的值被忽略。例如:表內已有一些數據,就會用如今已有的最大的自增值作爲初始值。
6、二進制日誌清除
主同步服務器產生的二進制日誌會佔據大量的磁盤空間,應按期刪除過時的bin-log。
A、經過PURGE MASTER LOGS刪除
若是您有一個在用的從屬服務器,該服務器當前正在讀取您正在試圖刪除的日誌之一,則本語句不會起做用,而是會失敗,並伴隨一個錯誤。不過,若是從屬服務器是中止的,而且您碰巧清理了其想要讀取的日誌之一,則從屬服務器啓動後不能複製。當從屬服務器正在複製時,本語句能夠安全運行。您不須要中止它們。
要清理日誌,需按照如下步驟:
一、在每一個從屬服務器上,使用SHOW SLAVE STATUS來檢查它正在讀取哪一個日誌。
二、使用SHOW MASTER LOGS得到主服務器上的一系列日誌。
三、在全部的從屬服務器中斷定最先的日誌。這個是目標日誌。若是全部的從屬服務器是更新的,這是清單上的最後一個日誌。
四、製做您將要刪除的全部日誌的備份。(建議備份)
五、清理全部的日誌,可是不包括目標日誌。
PURGE 語法
PURGE {MASTER | BINARY} LOGS TO ‘log_name’
PURGE {MASTER | BINARY} LOGS BEFORE ‘date’
用於刪除列於在指定的日誌或日期以前的日誌索引中的全部二進制日誌。這些日誌也會從記錄在日誌索引文件中的清單中被刪除,這樣被給定的日誌成爲第一個。
BEFORE變量的date自變量能夠爲’YYYY-MM-DD hh:mm:ss’格式。MASTER和BINARY是同義詞。
例如:
#刪除binlog.000002以前的而不包含binlog.000002
mysql> PURGE MASTER LOGS TO 'binlog.000002';
#刪除2011-05-28 1:35:00以前的
mysql> PURGE MASTER LOGS BEFORE '2011-05-28 1:35:00';
#清除3天前的binlog
mysql> PURGE MASTER LOGS BEFORE DATE_SUB(NOW( ), INTERVAL 3 DAY);
B、設置expire-logs-days參數
缺省expire-logs-days爲30天。這裏設爲7天,可根據本身狀況調整。
[mysqld]
expire-logs-days = 7
7、用於控制主、從服務器的SQL語句
A、用於控制主服務器的SQL語句
PURGE MASTER LOGS
用於刪除列於在指定的日誌或日期以前的日誌索引中的全部二進制日誌。這些日誌也會從記錄在日誌索引文件中的清單中被刪除,這樣被給定的日誌成爲第一個。
RESET MASTER
能夠刪除列於索引文件中的全部二進制日誌,把二進制日誌索引文件從新設置爲空,並建立一個新的二進制日誌文件。
SET SQL_LOG_BIN
若是客戶端使用一個有SUPER權限的帳戶鏈接,則能夠禁用或啓用當前鏈接的二進制日誌記錄。若是客戶端沒有此權限,則語句被拒絕,並伴隨有錯誤。
SHOW BINLOG EVENTS
用於在二進制日誌中顯示事件。若是您不指定’log_name’,則顯示第一個二進制日誌。
SHOW MASTER LOGS
用於列出服務器中的二進制日誌文件。
SHOW MASTER STATUS
用於提供主服務器二進制日誌文件的狀態信息。
SHOW SLAVE HOSTS
用於顯示當前使用主服務器註冊的複製從屬服務器的清單。
B、用於控制從服務器的SQL語句
CHANGE MASTER TO
能夠更改從屬服務器用於與主服務器進行鏈接和通信的參數。
LOAD DATA FROM MASTER
用於對主服務器進行快照,並拷貝到從屬服務器上。
LOAD TABLE tbl_name FROM MASTER
用於把表的拷貝從主服務器轉移到從屬服務器。
MASTER_POS_WAIT()
這其實是一個函數,而不是一個語句。它被用於確認,從屬服務器已讀取並執行了到達主服務器二進制日誌的給定位置。
RESET SLAVE
用於讓從屬服務器忘記其在主服務器的二進制日誌中的複製位置。
SET GLOBAL SQL_SLAVE_SKIP_COUNTER
從主服務器中跳事後面的n個事件。要復起因語句致使的複製停止,這是有用的。
SHOW SLAVE STATUS
用於提供有關從屬服務器線程的關鍵參數的信息。
START SLAVE
用於啓動從屬服務器線程
STOP SLAVE
用於停止從屬服務器線程
以上內容摘自MySQL官方手冊,具體用法詳見:http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html#reset-master
8、主從複製如何提升可靠性
主從單向複製,從服務器只是實時的保存了主服務器的一個副本。當主服務器發生故障時,能夠切換到從服務器繼續作查詢,但不能更新。
若是採用雙向複製,即兩臺mysql服務器即做爲主服務器,又做爲從服務器。那麼二者均可以執行更新操做並能實現負載均衡,當一方出現故障時,另外一方不受影響。可是,除非能保證任何更新操做順序都是安全的,不然雙向複製會致使失敗。
爲了更好的提升可靠性和可用性,須要當主服務器不可用時,令從服務器成爲Master。原來的主服務器設定爲Slave,並重新的Master上同步更新。如今已經有了一個這樣開源解決方案[MySQL Master-Master Replication Manager],後面我會在寫一篇關MySQL MMM架構的方案,敬請期待!
9、參考文檔
http://www.google.com
http://blogold.chinaunix.net/u3/93755/showart.php?id=2213538
http://hahaxiao.techweb.com.cn/archives/465.html
http://blog.csdn.net/libraworm/archive/2007/07/23/1703365.aspx
http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html#reset-master