總結:
[mysqld]
log-bin=mysql-bin
server-id=1
[mysqld]
log-bin=mysql-bin
server-id=2
TO backup@’192.168.1.254’
IDENTIFIED BY ‘1234’;
MariaDB [test]> change master to master_host='192.168.1.251',
-> master_user='backup',
-> master_password='1234',
-> master_log_file='mysql-bin.000001',
-> master_log_pos=0;
Query OK, 0 rows affected (0.02 sec)
MariaDB [test]> show slave status;
MariaDB [test]> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
1 復制概述
Mysql內建的復制功能是構建大型,高性能應用程序的基礎。將Mysql的數據分布到多個系統上去,這樣的分布的機制,是通過將Mysql的某一台主機的數據拷貝到其他主機(slaves)上,並又一次運行一遍來實現的。復制過程中一個server充當主server。而一個或多個其他server充當從server。
主server將更新寫入二進制日志文件,並維護文件的一個索引以跟蹤日志循環。這些日志能夠記錄發送到從server的更新。當一個從server連接主server時。它通知主server從server在日志中讀取的最后一次成功更新的位置。從server接收從那時起發生的不論什么更新,然后封鎖並等待主server通知新的更新。
請注意當你進行復制時。全部對復制中的表的更新必須在主server上進行。否則,你必需要小心,以避免用戶對主server上的表進行的更新與對從server上的表所進行的更新之間的沖突。
1.1 mysql支持的復制類型:
(1):基於語句的復制: 在主server上運行的SQL語句。在從server上運行相同的語句。
MySQL默認採用基於語句的復制,效率比較高。
一旦發現沒法精確復制時, 會自己主動選着基於行的復制。
(2):基於行的復制:把改變的內容復制過去,而不是把命令在從server上運行一遍. 從mysql5.0開始支持
(3):混合類型的復制: 默認採用基於語句的復制,一旦發現基於語句的無法精確的復制時。就會採用基於行的復制。
1.2 . 復制解決的問題
MySQL復制技術有下面一些特點:
(1) 數據分布 (Data distribution )
(2) 負載平衡(load balancing)
(3) 備份(Backups)
(4) 高可用性和容錯行 High availability and failover
1.3 復制怎樣工作
總體上來說。復制有3個步驟:
(1) master將改變記錄到二進制日志(binary log)中(這些記錄叫做二進制日志事件。binary log events);
(2) slave將master的binary log events復制到它的中繼日志(relay log)。
(3) slave重做中繼日志中的事件,將改變反映它自己的數據。
下圖描寫敘述了復制的過程:
該過程的第一部分就是master記錄二進制日志。在每一個事務更新數據完畢之前,master在二日志記錄這些改變。MySQL將事務串行的寫入二進制日志,即使事務中的語句都是交叉運行的。
在事件寫入二進制日志完畢后,master通知存儲引擎提交事務。
下一步就是slave將master的binary log復制到它自己的中繼日志。首先,slave開始一個工作線程——I/O線程。I/O線程在master上打開一個普通的連接,然后開始binlog dump process。Binlog dump process從master的二進制日志中讀取事件,假設已經跟上master,它會睡眠並等待master產生新的事件。
I/O線程將這些事件寫入中繼日志。
SQL slave thread(SQL從線程)處理該過程的最后一步。SQL線程從中繼日志讀取事件,並重放當中的事件而更新slave的數據。使其與master中的數據一致。僅僅要該線程與I/O線程保持一致。中繼日志一般會位於OS的緩存中。所以中繼日志的開銷非常小。
此外。在master中也有一個工作線程:和其他MySQL的連接一樣。slave在master中打開一個連接也會使得master開始一個線程。
復制過程有一個非常重要的限制——復制在slave上是串行化的,也就是說master上的並行更新操作不能在slave上並行操作。
2 .復制配置
有兩台MySQL數據庫serverMaster和slave,Master為主server,slave為從server。初始狀態時。Master和slave中的數據信息同樣,當Master中的數據發生變化時,slave也跟着發生對應的變化。使得master和slave的數據信息同步,達到備份的目的。
要點:
負責在主、從server傳輸各種修修改作的媒介是主server的二進制變更日志。這個日志記載着須要傳輸給從server的各種修修改作。
因此。主server必須激活二進制日志功能。
從server必須具備足以讓它連接主server並請求主server把二進制變更日志傳輸給它的權限。
環境:
Master和slave的MySQL數據庫版本號同為5.0.18
操作系統:unbuntu 11.10
IP地址:10.100.0.100
2.1、創建復制帳號
1、在Master的數據庫中建立一個備份帳戶:每一個slave使用標准的MySQLusername和password連接master。進行復制操作的用戶會授予REPLICATION SLAVE權限。username的password都會存儲在文本文件master.info中
命令例如以下:
mysql > GRANT REPLICATION SLAVE,RELOAD,SUPER ON *.*
TO backup@’10.100.0.200’
IDENTIFIED BY ‘1234’;
建立一個帳戶backup,而且僅僅能同意從10.100.0.200這個地址上來登陸,password是1234。
(假設由於mysql版本號新舊密碼算法不同。能夠設置:set password for 'backup'@'10.100.0.200'=old_password('1234'))
2.2、拷貝數據
(假如是你全然新安裝mysql主從server,這個一步就不須要。由於新安裝的master和slave有同樣的數據)
關停Masterserver,將Master中的數據復制到Bserver中,使得Master和slave中的數據同步,而且確保在所有設置操作結束前,禁止在Master和slaveserver中進行寫操作。使得兩數據庫中的數據一定要同樣。
2.3、配置master
接下來對master進行配置。包含打開二進制日志。指定唯一的servr ID。
比如。在配置文件增加例如以下值:
server-id=1
log-bin=mysql-bin
server-id:為主服務器A的ID值
log-bin:二進制變更日值
重新啟動master,執行SHOW MASTER STATUS,輸出例如以下:

2.4、配置slave
log_bin = mysql-bin
server_id = 2
relay_log = mysql-relay-bin
log_slave_updates = 1
read_only = 1
server_id是必須的,並且唯一。slave沒有必要開啟二進制日志。可是在一些情況下,必須設置,比如。假設slave為其他slave的master。必須設置bin_log。在這里,我們開啟了二進制日志,並且顯示的命名(默認名稱為hostname,可是。假設hostname改變則會出現故障)。
relay_log配置中繼日志,log_slave_updates表示slave將復制事件寫進自己的二進制日志(后面會看到它的用處)。
有些人開啟了slave的二進制日志。卻沒有設置log_slave_updates,然后查看slave的數據是否改變,這是一種錯誤的配置。
所以,盡量使用read_only,它防止改變數據(除了特殊的線程)。可是,read_only並是非常有用。特別是那些須要在slave上創建表的應用。
2.5、啟動slave
接下來就是讓slave連接master,並開始重做master二進制日志中的事件。你不應該用配置文件進行該操作,而應該使用CHANGE MASTER TO語句,該語句能夠全然代替對配置文件的改動。並且它能夠為slave指定不同的master。而不須要停止server。例如以下:
mysql> CHANGE MASTER TO MASTER_HOST='server1',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='p4ssword',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=0;
MASTER_LOG_POS的值為0,由於它是日志的開始位置。
你能夠用SHOW SLAVE STATUS語句查看slave的設置是否正確:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 4
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
...omitted...
Seconds_Behind_Master: NULL
Slave_IO_State, Slave_IO_Running, 和Slave_SQL_Running是No
表明slave還沒有開始復制過程。
日志的位置為4而不是0,這是由於0僅僅是日志文件的開始位置,並非日志位置。實際上,MySQL知道的第一個事件的位置是4。
為了開始復制。你能夠執行:
mysql> START SLAVE;
執行SHOW SLAVE STATUS查看輸出結果:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 164
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 164
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...omitted...
Seconds_Behind_Master: 0
Slave_IO_Running=Yes
Slave_SQL_Running=Yes
slave的I/O和SQL線程都已經開始執行,並且Seconds_Behind_Master不再是NULL。日志的位置添加了,意味着一些事件被獲取並執行了。
假設你在master上進行改動,你能夠在slave上看到各種日志文件的位置的變化,相同,你也能夠看到數據庫中數據的變化。
你可查看master和slave上線程的狀態。在master上,你能夠看到slave的I/O線程創建的連接:
mysql> show processlist \G *************************** 1. row *************************** Id: 1 User: root Host: localhost:2096 db: test Command: Query Time: 0 State: NULL Info: show processlist *************************** 2. row *************************** Id: 2 User: repl Host: localhost:2144 db: NULL Command: Binlog Dump Time: 1838 State: Has sent all binlog to slave; waiting for binlog to be updated Info: NULL 2 rows in set (0.00 sec) |
行2為處理slave的I/O線程的連接。
在slaveserver上執行該語句:
mysql> show processlist \G *************************** 1. row *************************** Id: 1 User: system user Host: db: NULL Command: Connect Time: 2291 State: Waiting for master to send event Info: NULL *************************** 2. row *************************** Id: 2 User: system user Host: db: NULL Command: Connect Time: 1852 State: Has read all relay log; waiting for the slave I/O thread to update it Info: NULL *************************** 3. row *************************** Id: 5 User: root Host: localhost:2152 db: test Command: Query Time: 0 State: NULL Info: show processlist 3 rows in set (0.00 sec) |
2.5、加入新slaveserver
假如master已經執行非常久了,想對新安裝的slave進行數據同步,甚至它沒有master的數據。
此時,有幾種方法能夠使slave從還有一個服務開始,比如。從master拷貝數據,從還有一個slave克隆。從近期的備份開始一個slave。
Slave與master同步時,須要三樣東西:
(1)master的某個時刻的數據快照;
(2)master當前的日志文件、以及生成快照時的字節偏移。這兩個值能夠叫做日志文件坐標(log file coordinate),由於它們確定了一個二進制日志的位置,你能夠用SHOW MASTER STATUS命令找到日志文件的坐標。
(3)master的二進制日志文件。
能夠通過下面幾中方法來克隆一個slave:
(1) 冷拷貝(cold copy)
停止master。將master的文件復制到slave。然后重新啟動master。缺點非常明顯。
(2) 熱拷貝(warm copy)
假設你僅使用MyISAM表,你能夠使用mysqlhotcopy拷貝。即使server正在執行。
(3) 使用mysqldump
使用mysqldump來得到一個數據快照可分為下面幾步:
<1>鎖表:假設你還沒有鎖表,你應該對表加鎖,防止其他連接改動數據庫,否則。你得到的數據能夠是不一致的。例如以下:
mysql> FLUSH TABLES WITH READ LOCK;
<2>在還有一個連接用mysqldump創建一個你想進行復制的數據庫的轉儲:
shell> mysqldump --all-databases --lock-all-tables >dbdump.db
<3>對表釋放鎖。
mysql> UNLOCK TABLES;
3、深入了解復制
3.1、基於語句的復制(Statement-Based Replication)
master記錄下改變數據的查詢,然后,slave從中繼日志中讀取事件,並運行它,這些SQL語句與master運行的語句一樣。
這樣的方式的長處就是實現簡單。
此外,基於語句的復制的二進制日志能夠非常好的進行壓縮。並且日志的數據量也較小,占用帶寬少——比如,一個更新GB的數據的查詢僅須要幾十個字節的二進制日志。而mysqlbinlog對於基於語句的日志處理十分方便。
可是。基於語句的復制並非像它看起來那么簡單,由於一些查詢語句依賴於master的特定條件,比如。master與slave可能有不同的時間。所以,MySQL的二進制日志的格式不不過查詢語句,還包含一些元數據信息。比如,當前的時間戳。
即使如此,還是有一些語句,比方,CURRENT USER函數。不能正確的進行復制。
此外。存儲過程和觸發器也是一個問題。
另外一個問題就是基於語句的復制必須是串行化的。
這要求大量特殊的代碼。配置,比如InnoDB的next-key鎖等。並非全部的存儲引擎都支持基於語句的復制。
3.2、基於記錄的復制(Row-Based Replication)
這樣的方式有長處,也有缺點。長處就是能夠對不論什么語句都能正確工作。一些語句的效率更高。基本的缺點就是二進制日志可能會非常大,並且不直觀,所以。你不能使用mysqlbinlog來查看二進制日志。
對於一些語句。基於記錄的復制可以更有效的工作,如:
mysql> INSERT INTO summary_table(col1, col2, sum_col3)
-> SELECT col1, col2, sum(col3)
-> FROM enormous_table
-> GROUP BY col1, col2;
如果,僅僅有三種唯一的col1和col2的組合。可是。該查詢會掃描原表的很多行。卻僅返回三條記錄。
此時,基於記錄的復制效率更高。
還有一方面。以下的語句,基於語句的復制更有效:
mysql> UPDATE enormous_table SET col1 = 0;
此時使用基於記錄的復制代價會非常高。因為兩種方式不能對全部情況都能非常好的處理,所以,MySQL 5.1支持在基於語句的復制和基於記錄的復制之前動態交換。你能夠通過設置session變量binlog_format來進行控制。
3.3、復制相關的文件
(1)mysql-bin.index
它用於跟蹤磁盤上存在哪些二進制日志文件。MySQL用它來定位二進制日志文件。它的內容例如以下(我的機器上):
(2)mysql-relay-bin.index
內容例如以下:
.\mysql-02-relay-bin.000017
.\mysql-02-relay-bin.000018
(3)master.info
不要刪除它,否則,slave重新啟動后不能連接master。內容例如以下(我的機器上):
I/O線程更新master.info文件,內容例如以下(我的機器上):
.\mysql-02-relay-bin.000019 254 mysql-01-bin.000010 286 0 52813 |
(4)relay-log.info
3.4、發送復制事件到其他slave

3.5、復制過濾(Replication Filters)
4、復制的經常使用拓撲結構
(1) 每一個slave僅僅能有一個master。
(2) 每一個slave僅僅能有一個唯一的serverID;
(3) 每一個master能夠有非常多slave;
(4) 假設你設置log_slave_updates,slave能夠是其他slave的master,從而擴散master的更新。
MySQL不支持多主server復制(Multimaster Replication)——即一個slave能夠有多個master。
可是。通過一些簡單的組合,我們卻能夠建立靈活而強大的復制體系結構。
4.1、單一master和多slave
Slave之間並不相互通信。僅僅能與master進行通信。
在實際應用場景中。MySQL復制90%以上都是一個Master拷貝到一個或者多個Slave的架構模式,主要用於讀壓力比較大的應用的數據庫端便宜擴展解決方式。
由於僅僅要Master和Slave的壓力不是太大(尤其是Slave端壓力)的話,異步復制的延時一般都非常少非常少。尤其是自從Slave端的復制方式改成兩個線程處理之后。更是減小了Slave端的延時問題。而帶來的效益是。對於數據實時性要求不是特別Critical的應用。僅僅須要通過便宜的pcserver來擴展Slave的數量,將讀壓力分散到多台Slave的機器上面,就可以通過分散單台數據庫服務器的讀壓力來解決數據庫端的讀性能瓶頸。畢竟在大多數數據庫應用系統中的讀壓力還是要比寫壓力大非常多。
這在非常大程度上攻克了眼下非常多中小型站點的數據庫壓力瓶頸問題。甚至有些大型站點也在使用類似方案解決數據庫瓶頸。

假設寫操作較少。而讀操作非常時。能夠採取這樣的結構。你能夠將讀操作分布到其他的slave,從而減小master的壓力。
可是,當slave添加到一定數量時,slave對master的負載以及網絡帶寬都會成為一個嚴重的問題。
這樣的結構盡管簡單,可是。它卻很靈活,足夠滿足大多數應用需求。一些建議:
(1) 不同的slave扮演不同的作用(比如使用不同的索引,或者不同的存儲引擎);
(2) 用一個slave作為備用master,僅僅進行復制。
(3) 用一個遠程的slave。用於災難恢復。
大家應該都比較清楚,從一個Master節點能夠復制出多個Slave節點。可能有人會想。那一個Slave節點能否夠從多個Master節點上面進行復制呢?至少在眼下來看,MySQL是做不到的,以后是否會支持就不清楚了。
MySQL不支持一個Slave節點從多個Master節點來進行復制的架構。主要是為了避免沖突的問題。防止多個數據源之間的數據出現沖突,而造成最后數據的不一致性。只是聽說已經有人開發了相關的patch,讓MySQL支持一個Slave節點從多個Master結點作為數據源來進行復制,這也正是MySQL開源的性質所帶來的優點。
4.2、主動模式的Master-Master(Master-Master in Active-Active Mode)
可能有些讀者朋友會有一個操心,這樣搭建復制環境之后。難道不會造成兩台MySQL之間的循環復制么?實際上MySQL自己早就想到了這一點。所以在MySQL的BinaryLog中記錄了當前MySQL的server-id,並且這個參數也是我們搭建MySQLReplication的時候必須明白指定。並且Master和Slave的server-id參數值比須要不一致才干使MySQLReplication搭建成功。一旦有了server-id的值之后。MySQL就非常easy推斷某個變更是從哪一個MySQLServer最初產生的,所以就非常easy避免出現循環復制的情況。並且。假設我們不打開記錄Slave的BinaryLog的選項(--log-slave-update)的時候,MySQL根本就不會記錄復制過程中的變更到BinaryLog中,就更不用操心可能會出現循環復制的情形了。

主動的Master-Master復制有一些特殊的用處。比如,地理上分布的兩個部分都須要自己的可寫的數據副本。
這樣的結構最大的問題就是更新沖突。
如果一個表僅僅有一行(一列)的數據,其值為1,如果兩個server分別同一時候運行例如以下語句:
在第一個server上運行:
mysql> UPDATE tbl SET col=col + 1;
在第二個server上運行:
mysql> UPDATE tbl SET col=col * 2;
那么結果是多少呢?一台server是4,還有一個server是3,可是,這並不會產生錯誤。
實際上。MySQL並不支持其他一些DBMS支持的多主server復制(Multimaster Replication),這是MySQL的復制功能非常大的一個限制(多主server的難點在於解決更新沖突),可是。假設你實在有這樣的需求,你能夠採用MySQL Cluster。以及將Cluster和Replication結合起來。能夠建立強大的高性能的數據庫平台。可是。能夠通過其他一些方式來模擬這樣的多主server的復制。
4.3、主動-被動模式的Master-Master(Master-Master in Active-Passive Mode)

在有些應用場景中,可能讀寫壓力區別比較大,讀壓力特別的大,一個Master可能須要上10台甚至很多其它的Slave才可以支撐注讀的壓力。這時候,Master就會比較吃力了。由於只連上來的SlaveIO線程就比較多了。這樣寫的壓力略微大一點的時候,Master端由於復制就會消耗較多的資源,非常easy造成復制的延時。
遇到這樣的情況怎樣解決呢?這時候我們就能夠利用MySQL能夠在Slave端記錄復制所產生變更的BinaryLog信息的功能,也就是打開—log-slave-update選項。
然后,通過二級(或者是很多其它級別)復制來降低Master端由於復制所帶來的壓力。也就是說,我們首先通過少數幾台MySQL從Master來進行復制。這幾台機器我們姑且稱之為第一級Slave集群。然后其它的Slave再從第一級Slave集群來進行復制。
從第一級Slave進行復制的Slave,我稱之為第二級Slave集群。假設有須要。我們能夠繼續往下添加很多其它層次的復制。這樣。我們非常easy就控制了每一台MySQL上面所附屬Slave的數量。這樣的架構我稱之為Master-Slaves-Slaves架構
這樣的多層級聯復制的架構,非常easy就攻克了Master端由於附屬Slave太多而成為瓶頸的風險。
下圖展示了多層級聯復制的Replication架構。
當然,假設條件同意,我更傾向於建議大家通過拆分成多個Replication集群來解決
上述瓶頸問題。
畢竟Slave並沒有降低寫的量,全部Slave實際上仍然還是應用了全部的數據變更操作,沒有降低不論什么寫IO。
相反,Slave越多。整個集群的寫IO總量也就會越多,我們沒有非常明顯的感覺,只不過由於分散到了多台機器上面,所以不是非常easy表現出來。
此外,添加復制的級聯層次,同一個變更傳到最底層的Slave所須要經過的MySQL也會很多其它。相同可能造成延時較長的風險。
而假設我們通過分拆集群的方式來解決的話,可能就會要好非常多了,當然,分拆集群也須要更復雜的技術和更復雜的應用系統架構。
4.5、帶從server的Master-Master結構(Master-Master with Slaves)

級聯復制在一定程度上面確實攻克了Master由於所附屬的Slave過多而成為瓶頸的問題。可是他並不能解決人工維護和出現異常須要切換后可能存在又一次搭建Replication的問題。
這樣就非常自然的引申出了DualMaster與級聯復制結合的Replication架構,我稱之為Master-Master-Slaves架構
和Master-Slaves-Slaves架構相比,差別只不過將第一級Slave集群換成了一台單獨的Master,作為備用Master。然后再從這個備用的Master進行拷貝到一個Slave集群。
這樣的DualMaster與級聯復制結合的架構,最大的優點就是既能夠避免主Master的寫入操作不會受到Slave集群的復制所帶來的影響,同一時候主Master須要切換的時候也基本上不會出現重搭Replication的情況。可是。這個架構也有一個弊端,那就是備用的Master有可能成為瓶頸,由於假設后面的Slave集群比較大的話。備用Master可能會由於過多的SlaveIO線程請求而成為瓶頸。當然,該備用Master不提供不論什么的讀服務的時候。瓶頸出現的可能性並非特別高,假設出現瓶頸,也能夠在備用Master后面再次進行級聯復制。架設多層Slave集群。當然,級聯復制的級別越多。Slave集群可能出現的數據延時也會更為明顯。所以考慮使用多層級聯復制之前,也須要評估數據延時相應用系統的影響。