mysql從3.23開始提供複製功能,複製指將主庫的ddl和dml操做經過binlog文件傳送到從庫上執行,從而保持主庫和從庫數據同步。mysql支持一臺主庫同時向多臺從庫複製,從庫同時也能夠做爲其餘從庫的主庫,從而實現級聯複製功能。mysql複製功能至關於oracle數據庫的邏輯dg功能。mysql
mysql複製原理大體以下:linux
1)mysql主庫事務提交時會把數據變動做爲event記錄在binlog文件中,mysql主庫的sync_binlog參數控制binlog日誌刷新到磁盤。sql
2)從庫收集主庫binlog中的event到從庫的中繼日誌relay log中,以後從庫根據中繼日誌重作數據變動操做,經過邏輯複製來達到與主庫同步的目的。數據庫
基本步驟以下:安全
l 主服務器將更新寫入binlog文件,並維護文件的一個索引以跟蹤日誌的循環。服務器
l 從庫複製主庫的binlog event到本地中繼日誌(relay log)。網絡
l 從庫sql線程重放中繼日誌。session
將從服務器設置爲複製主服務器的數據後,它將鏈接主服務器並等待更新過程。若是主服務器失敗,或者從服務器和主服務器之間失去聯繫,那麼從服務器將保持按期嘗試重連,直到它可以繼續監聽爲止。由--master-connect-retry選項控制着重試間隔,默認60s。架構
mysql經過3個線程完成複製功能:其中binlog dump線程跑在主庫上,io線程和sql線程跑在從庫上。當從庫啓動複製(start slave)時,從服務器首先建立io線程鏈接主庫,主庫隨後建立binlog dump線程讀取event發送給io線程,io線程獲取到event後更新到從庫中繼日誌relay log中,以後從庫sql線程根據relay log內容在從庫從作操做。從而完成mysql複製功能。由此可知,這樣讀取和執行語句將被分紅兩個獨立的任務。mysql複製結構如圖:oracle
主庫經過show processlist命令能夠看到binlog dump進程,以下:
mysql> show processlist \G;
*************************** 1. row ***************************
Id: 125
User: root
Host: localhost
db: test
Command: Query
Time: 0
State: init
Info: show processlist
*************************** 2. row ***************************
Id: 127 --線程127爲主庫複製線程
User: rep1
Host: 192.168.80.136:44889
db: NULL
Command: Binlog Dump
Time: 16991
State: Master has sent all binlog to slave; waiting for binlog to be updated --已經發送了全部binlog,等待更新
Info: NULL
2 rows in set (0.00 sec)
從庫經過show processlist命令能夠看到io線程和sql線程,以下:
mysql> show processlist \G;
*************************** 1. row ***************************
Id: 4
User: root
Host: localhost
db: test
Command: Query
Time: 0
State: init
Info: show processlist
*************************** 2. row ***************************
Id: 7 --從庫中的io線程
User: system user
Host:
db: NULL
Command: Connect
Time: 17079
State: Waiting for master to send event --等待主庫發送日誌狀態
Info: NULL
*************************** 3. row ***************************
Id: 8 --從庫sql線程
User: system user
Host:
db: NULL
Command: Connect
Time: 17107 --能夠顯示從服務器比主服務器滯後多長時間
State: Slave has read all relay log; waiting for the slave I/O thread to update it --已經應用了全部relay log
Info: NULL
3 rows in set (0.00 sec)
複製的做用:
複製有不少用途,好比備份、讀寫分離、軟件升級、故障轉移等。注意在mysql版本升級過程須要考慮到複製的兼容性問題。
mysql複製涉及到兩種文件:binlog和relay log文件。其中根據binlog的不一樣設置,mysql複製分爲3中模式。
l 基於sql語句級別的複製。
l 基於行的複製
l 混合模式複製
1)基於SQL語句級別的複製
基於語句級的複製,複製將執行主庫上所執行的語句,也就是說,從庫執行的更新語句和主庫執行的同樣。基於語句的複製,優勢有:
l 相對於基於行的複製,更簡單,易實現。
l 數據庫產生的二進制日誌更少,傳輸佔用帶寬更少。
l 二進制日誌可讀性更好,mysqlbinlog能夠方便讀取binlog日誌內容。
l 有利於排查問題,從庫上執行和主庫同樣。
基於語句的複製,缺點有:
l 主庫的某些操做不能正確複製到從庫。
l 從庫須要鎖定更多記錄。
l 負載、代價大的sql在從庫上須要再次執行。
l 對於非核心功能支持有限。
2)基於行的複製
Mysql5.1開始支持基於行的複製,它的適用範圍更廣,也可靠地多。基於行的複製其格式比較難以理解。基於行的複製能夠處理各類高級功能,好比存儲過程、觸發器等,若是你想更兼容高級功能,建議採用基於行的複製模式。
基於行的複製優勢有:
l 全部改變均被複制,對比與基於語句的複製,這是一種更安全的方式。
l 更少的鎖定。
l 對於mysql高級特性兼容良好,好比存儲過程、觸發器。
l 二進制日誌更有利於恢復,由於binlog裏記錄了更爲詳細的數據庫變動。
l 更容易發現數據的不一致。
基於行復制的缺點有:
l 產生更多的binlog日誌。
l Binlog日誌內容不易閱讀,不方便使用mysqlbinlog工具解讀。
l 要求主從表結構一致,這樣限制了它的靈活性,由於生產環境有時須要臨時修改從庫表結構,提高從庫爲主庫。
3)混合複製模式
默認採用基於語句的複製,一旦檢測到觸發了某些條件,則使用基於行的方式進行復制,這種設計完美的解決了語句級和行級複製的缺點,這也是建議採用的複製方式。
複製的3中常見架構:一主多從、級聯複製、雙主架構
1)mysql一主多從架構:解決主庫讀請求壓力解決方案。
2)mysql級聯架構:解決一主多從架構中主庫io和網絡壓力,缺點時額外增長了主庫到從庫的應用延遲,其中master2能夠設置爲blackhold(黑洞)模式來緩解複製延遲。
3)雙主複製/dual master架構:
4)雙主級聯複製架構:
複製相關參數設置:
1)slave_exec_mode
複製衝突解決和錯誤檢測能夠採用以下兩種模式:
l Strict:默認
l Idempotent:忽略duplicate-key、no-key-found錯誤,通常在主主複製、環形複製等其餘特殊狀況下才使用,不推薦使用。
2)max_allowed_packet
默認設置過小,聲場環境中建設設置爲16m或更大,設置過小可能致使從庫不能解釋接收主庫發送的包,主從庫建議設置成同樣的值,若是數據庫存在大的blob字段,還須要考慮將這個值設置爲更大。
3)複製過濾選項
請不要隨意使用複製過濾選項,除非你真的有理由這麼作,即便使用,也建議在從庫進行設置。複製過濾選項主庫上主要由參數binlog-do-db和binlog-ignore-db兩個參數決定,通常不建議使用,很差的地方是他們可能致使你不能進行基於時間點的恢復或者丟失數據。
Binlog-do-db=db_name:
告訴主服務器,若是當前的數據庫是db_name,應該講更新記錄到binlog,其餘全部沒有明確指定的數據庫將被忽略。若是使用了該選線,你應該確保僅對當前數據庫進行更新。
Binlog_ignore_db=db_name:
告訴主服務器,若果當前數據庫是db_name,那麼應該不記錄更新到binlog。
在從庫上對應有兩個參數replicate-do-db和replicate-ignore-db,他們的做用相似於主庫設置的binlog-do-db和binlog-ignore-db的做用,不一樣點僅在於設置地方不同。
*-do-db和*-ignore-db參數其實都僅僅是針對當前數據庫,也就是說,若是咱們use到其餘數據庫上,而後執行了一條更新其餘庫的SQL,這些參數將不起做用。
如下是在從庫上設置的一些參數:
--replicate-ignore-db=db_name
這個選線告訴從服務器不要複製默認數據庫爲db_name的語句。要想忽略多個數據庫,能夠屢次指定該參數,且每一個數據庫只能使用一次。若是存在跨數據庫更新而且不想複製這些更新,那麼久不要使用了。
--replicate-ignore-table=db_name.tb1_name
它將告訴從服務器複製線程不要複製更新指定表的任何語句。要想忽略多個表,須要屢次指定該選項,且每一個表只能指定一次。該選項能夠跨數據庫更新。
--replicate-wild-ignore-table=foo%.bar%
它告訴從服務器線程不要複製匹配通配符模式的語句,要想忽略多個表,須要屢次指定該選項,且每一個表只能指定一次。該選項能夠跨數據庫更新。若是必定要指定過濾選項,建議以上參數中僅適用此參數設置。
若是要在session級別禁用複製特性,那麼咱們能夠在session級別設置變量set sql_log_bin=0,使當前的某些操做不被複制到從庫。
4)slave_commpressed_protocol
請慎重對待跨集羣複製,跨集羣複製時能夠採用slave_commpressed_protocol=1壓縮傳輸數據,須要在主庫進行壓縮,在從庫進行解壓縮,由於壓縮須要額外的cpu,所以須要評審cpu資源。
5)Read-only
能夠考慮在從庫上設置read-obly,以只讀方式啓動從庫,要注意的是super權限用戶依舊能夠在從庫更新。
6)slave-net-timeout
因爲生產環境網絡異常,即便show slave status輸出正常,但此時可能也已經中止複製,slave-net-timeout默認設置1小時,對於生產來講太長,很難及時發現網絡問題,通常設置1分鐘。
7)--slave-skip-errors
一般狀況下,當出現錯誤時複製會中止,這個選項能夠給你一次手動解決數據不一致問題的機會。當語句返回slave-skip-errors鎖列問題時,該選線會告訴sql線程繼續複製。
例如:--slave-skip-errors=1062,1053
--salve-skip-errors=all
8)skip-slave-start
Skip-slave-start能夠在命令行下或配置文件中使用,目的是在mysql啓動的時候不要啓動slave,這在某些故障狀況下頗有用。使用--skip-slave-start選項來啓動從庫,能夠防止當從庫啓動時,sql線程開始工做。
複製相關文件:
1)中繼日誌:默認狀況下中繼日誌使用host_name-relay-bin.nnnnnn形式命名,其中host_name表示主機名,nnnnnn表示編號。用連續的序列號來建立連續的中繼日誌文件。從服務器跟蹤索引文件中目前正在使用的中繼日誌文件。中繼日誌索引文件命名爲host_name-relay-bin.index。默認狀況下,能夠在從服務器的數據目錄中建立這些文件。可使用--relay-log和--relay-log-index服務器選項覆蓋默認文件名,強烈建議設置這兩個參數,這主要有助於之後的遷移及故障處理。
中繼日誌文件與binlog格式相同,因此可使用mysqlbinlog工具讀取中繼日誌文件內容。Sql線程執行中繼日誌中的event而且再也不須要中繼日誌後,會當即自動刪除它。沒有直接刪除中繼日誌的機制,由於sql線程能夠自動完成它。
2)狀態文件:從服務器數據目錄中存在兩個與複製有關的文件,分別爲master.info和relay-log.info,它們包含了show slave status語句輸出顯示的信息。狀態文件保存在磁盤上,所以從服務器關閉時不會丟失狀態文件。下次啓動從服務器,讀取這些文件以肯定從服務器已經從主庫上讀取了多少binlog日誌,以及處理了本身的中繼日誌的成度。
由io線程更新master.info文件,master.info文件中和show slave status顯示的列的對應關係以下表所示:
略。
由sql線程更新relay-log.info文件,relay-log.info文件中和show slave status顯示的列的對應關係以下表所示:
略。
3)複製下的備份:
當備份從服務器的數據時,你還須要備份狀態文件和中繼日誌文件。他們能夠用來恢復從服務器後繼續複製。若是丟失中繼日誌可是還存在relay-log.info文件,那麼你能夠經過檢查該文件來確認sql線程已經執行的主服務器中的二進制日誌文件程度。而後咱們可使用master_log_file和master_log_pos選項執行change_master命令來告訴從服務器須要從新從該點讀取二進制日誌。固然,binlog必須在主服務器上存在才能夠。
4)mysql5.1中中繼日誌和狀態文件並非crash-safe的,也就是說,他們默認是不會實時刷新到磁盤的,那麼發生故障的狀況下,文件的信息可能就是錯誤的,將會致使複製異常。Mysql5.5,那麼能夠設置如下選項來確保這些文件刷新磁盤的頻率:
Sync_master_info=1
Sync_relay_log=1
Sync_relay_log_info=1
注意這些參數會帶來必定開銷,對於寫頻繁的應用,建議不要設置這些參數。
Mysql5.5還有一個參數:relay_log_space_limit,這個參數設置了全部中繼日誌可使用的空間閾值。意思是若是中間日誌佔用了空間超過了這個設置,那麼io線程就會關閉,等待sql線程應用並刪除中繼日誌釋放空間。
複製環境經常使用的命令:
1)show master status命令查看主庫狀態:該命令用來提供主服務器binlog文件的狀態信息,執行它須要super或replacation client權限。
mysql> show master status \G;
*************************** 1. row ***************************
File: dbking-bin.000004 --當前正在讀取的binlog文件
Position: 1729 --讀取binlog文件的位置
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
2)經過show slave status查看從庫狀態:該命令用於提供從庫線程的關鍵參數信息。
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.80.133 --當前主服務器主機
Master_User: rep1 --被用於鏈接主服務器的當前用戶
Master_Port: 3306 --鏈接主服務器端口號
Connect_Retry: 60 --「--master-connect-retry」參數的當前值
Master_Log_File: dbking-bin.000004 --io線程正在讀取的主服務器binlog名稱
Read_Master_Log_Pos: 1729 --io線程正在讀取的主服務器binlog位置編號
Relay_Log_File: chavinking-relay-bin.000010 --sql線程當前正在讀取和執行的中繼日誌名稱。
Relay_Log_Pos: 714 --當前relay log文件,sql線程已經讀取和執行的位置
Relay_Master_Log_File: dbking-bin.000004 --sql線程執行包含多個近期event的主服務器binlog名稱
Slave_IO_Running: Yes --io線程運行狀態,正常狀態爲yes
Slave_SQL_Running: Yes --sql線程運行狀態,正常狀態爲yes
Replicate_Do_DB: --使用--replicate-do-db選項指定的數據庫清單
Replicate_Ignore_DB: --使用--replicate-ignore-db選項指定的數據庫清單
Replicate_Do_Table: <------------------------------------------------
Replicate_Ignore_Table: 使用期間這些選項指定的表清單
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table: ------------------------------------------------->
Last_Errno: 0 <--多數最近被執行的查詢返回錯誤數和錯誤消息,Last_Errno爲0
Last_Error: 而且Last_Error爲null,意味着沒有錯誤,不然從庫錯誤日誌會被記錄>
Skip_Counter: 0 --最近被使用的用於sql_slave_skip_counter的值
Exec_Master_Log_Pos: 1729 --來自主服務器binlog、由sql線程執行的、上一個時間的位置 (relay_master_log_file).主服務器中binlog中的 (relay_master_log_file,exec_master_log_pos)對
應中繼日誌中的(relay_log_file、relay_log_pos)。
Relay_Log_Space: 1056 --全部原有中繼日誌結合起來總大小
Until_Condition: None <------------------------------
Until_Log_File: 在start slave語句的until子句中指定的值
Until_Log_Pos: 0 ------------------- --->
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0 --是從庫落後多少的一個指示。通常是基於同一集羣內網主從集羣,此值應爲 0。本字段用於測量從庫sql線程和從庫io線程之間時間差距,單位以秒計算
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 9b92b2a8-b7e0-11e6-81e4-000c29fa5a95
Master_Info_File: /usr/local/software/mysql-5.6.24-linux-glibc2.5-x86_64/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
1 row in set (0.00 sec)
3)change master命令
這個命令在從庫中執行,能夠配置所要鏈接的數據庫信息,以及從哪裏開始同步。經常使用語法以下:
change master to
master_host='xxx.xxx.xxx.xxx',
master_port=3306,
master_user='replic_user',
master_password='password',
master_log_file='log file name',
master_log_pos=position;
咱們能夠在正在運行的從庫中動態修改鏈接主庫的信息。例如修改密碼:
mysql>stop slave;
mysql>change master to master_password='password';
mysql>start slave;
此更改沒有必要指定沒有變動的參數。
參數解釋:
master_host和master_port:指定主庫ip和端口。
master_log_file和master_log_pos:指定主庫binlog名稱和位置
master_user和master_password:指定複製用戶的帳號和密碼,從庫將使用這個帳號去鏈接主庫,因此主庫要爲這個帳號授予replication slave的權限。
change master:會刪除全部中繼日誌文件並啓動一個新的日誌,除非你指定了relay_log_file或relay_log_pos,這種狀況下,中繼日誌將被保持。
change master to:會改變從庫master.info和relay-log.info文件內容。
4)start slave和stop slave命令
stop salve命令能夠中止io線程和sql線程。而咱們經常使用的start slave語句有3種經常使用用法:
A)start slave不帶任何參數
不包含任何參數的start slave命令會同時啓動2個從庫線程。io線程從主服務器讀取查詢,並把他們存儲到中繼日誌文件中;sql線程讀取中繼日誌文件,並應用複製。start slave要求super權限。若是start slave成功地啓動了從庫線程,則會返回,不會出現錯誤。可是,即便如此,也有可能出現從庫線程啓動了可是又中止了。start slave對此不發生任何警告,必須檢查從庫錯誤日誌肯定錯誤緣由,或者使用show slave status命令檢查io線程和sql線程運行狀態。
B)start slave啓動單個服務器線程
start slave io_thread;
start slave sql_thread;
C)start slave指定到某個位置自動中止
能夠在start slave命令中添加until子句,指定從庫應啓動並運行,直到sql線程達到主服務器二進制日誌中一個給定點爲止。當sql線程執行到該指定點,它會自動中止。若是在該語句中指定了sql_thread選項,它會僅僅啓動sql線程,不然它會同時啓動2個線程。通常狀況下,這種操做咱們僅操控sql線程。語法以下:
start slave [sql_thread] until master_log_file='binlog_name',master_log_pos='binlog_post'
5)show slave host命令在主庫上運行能夠查詢從庫信息