3.1 MySQL複製
爲了保證應用24小時提供服務,那麼咱們須要作2件事情,系統數據的備份和冗餘。備份能夠將數據恢復到崩潰以前的狀態,而冗餘則是保證在一個或多個節點中止服務的狀況下,應用仍能提供服務。mysql
3.1.1 什麼是複製
這裏說的複製,就是指MySQL複製主節點(master)的全部數據改變到從節點(slave),並應用改變的數據,與主節點數據保存一致。一般複製就是爲了給master建立一個可靠的副本。sql
MySQL複製,有什麼特色呢?數據庫
(1) 數據分佈 (Data distribution ),數據能夠分佈在不一樣的數據中心。安全
(2) 負載平衡(load balancing),能夠分配查詢,下降主服務器壓力。服務器
(3) 備份(Backups) ,複製自己就是一種master的備份。網絡
(4) 高可用性和容錯行 High availability and failover,當master宕機後,slave能夠接管master的任務,同時具備及時糾正錯誤,挽回數據的容錯率。併發
從MySQL5.0開始,MySQL默認採用日誌複製,效率很是高,可靠性也很是高,前提是主從,一開始是徹底相同的數據。當沒法保證精準複製時,MySQL會基於行的複製。異步
3.1.2 異步與同步的區別
MySQL的複製準確的說,是異步的,不是同步複製的。事務首先在主節點提交,而後複製給從節點,並在從節點上應用。這意味着主節點和從節點可能並不一致,若是主節點一直在更新,那麼從節點始終是落後與主節點的。函數
異步複製優勢在於,比同步複製更快,擴展性更好,佔用系統資源更少。高併發
同步複製則須要master等待全部的slave的寫都完成後,才能提交,致使寫的速度大大下降,同時須要額外的同步機制來保證一致性,但卻有額外的通訊消息傳遞,增長了網絡數據量。
3.2 主從複製
搭建一個主從複製,大體看看是一個什麼樣的效果,一主一從,最簡單的開始。
這裏須要涉及到二進制日誌,後面來詳細說明,本次主要說明覆制過程。
3.2.1 配置複製
第一步:配置master。首先須要開啓二進制日誌,配置好server-id,而後啓動MySQL,以下所示幾行添加到/etc/my.cnf文件中:
log-bin=master-bin 二進制日誌文件名稱格式。
log-bin-index=master-bin.index 二進制日誌的索引文件名
server-id=1 server id用於標示主從。
通常狀況下log-bin默認是hostname-bin。Hostname的值來自pid-file選項,可是這樣也會有問題,主機名修改以後,binlog日誌文件名也會隨之改變,索引文件仍是能夠讀取到正確的值。
當不給log-bin-index值的時候,默認與binlog文件基本名相同,索引文件隨主機名改變而改變,當你重啓了服務器以後,索引文件就找不到日誌文件了,認爲不存在了。
接下來,須要建立一個複製用的用戶。例如:
mysql> change master to
-> master_host='vm11.qq.com',
-> master_port=3306,
-> master_user='repl_user',
-> master_password='mysql';
Query OK, 0 rows affected, 2 warnings (0.04 sec)
注意:最好在同步以前,主從兩邊的數據庫是同樣的,由於master在沒有開啓二進制日誌以前的全部操做都不會同步過去到slave的。
咱們這裏在master沒有開啓二進制日誌以前,先創建了一個庫test,slave確定同步不過去,這時候master刪除這個庫。而後再次新建test的時候,出現了問題。
這是master的,看看slave的。
這裏沒有同步過去,看看什麼問題。
錯誤:1008,test庫不存在,drop database test語句執行不了,因此slave_sql_running狀態變成了NO。生產環境很容易忽略,出現這樣的問題。
CHANGE MASTER TO MASTER_HOST='vm11.qq.com',
MASTER_USER='repl_user',
MASTER_PASSWORD='mysql',
MASTER_LOG_FILE='master-bin.000001',
MASTER_LOG_POS=756;
Start slave;重新的位置重新同步,前面的忽略。
3.2.2 二進制日誌
什麼是二進制日誌,就是記錄表改變的記錄,以上例來看。
來看看日誌都記錄了什麼;
對比一下,咱們如下的操做,那些記錄了,那些沒有記錄。
mysql> create database test; 記錄
mysql>use test; 記錄
mysql>create table tab(text text); 記錄
mysql>insert into tab values("hello!"); 記錄,自動添加use test命令。
mysql>select * from tab; 沒有,日誌記錄了一次commit;
mysql> flush logs; 記錄
最後一條記錄:Info:master-bin.000002;pos=4是slave下一次讀取二進制日誌的位置,由於咱們執行了flush logs;強制切換日誌。
當咱們想看第二個日誌文件的內容時,默認是沒法看到的,能夠這樣:
mysql> show binlog eventsin 'master-bin.000002' \G;
3.2.3 複製工做原理
總體上來講,複製有3個步驟:
(1) master將改變記錄到二進制日誌(binary log)中(這些記錄叫作二進制日誌事件,binary logevents);
(2) slave將master的binary log events拷貝到它的中繼日誌(relay log);
(3) slave重作中繼日誌中的事件,將改變反映它本身的數據。
1.基於語句複製
也稱爲邏輯複製,須要保證主從基礎數據同樣,而後把主庫上記錄的更改在從庫上再執行一遍,實現簡單,同步效果較好,網絡傳輸少,但問題就是,存在着一些沒法被正確複製的SQL,像時間戳,current_user()這樣的函數語句,觸發器,存儲過程等也容易出現問題。另一個問題時更新必須串行的,因此會須要更多的鎖。
優勢:適應場景普遍,能夠很是靈活,都是SQL執行方式,當出現問題能夠很好的去定位。
缺點:有些語句存在沒法正確複製問題,特別是存儲過程和觸發器。
2.基於行的複製
就是直接複製改變的行數據,在從庫中也作update操做,也種實現方式比較複雜,由於複製的數據可能不正確,從庫更新量大,主庫一個update操做更新2000條數據,但在從庫可能須要update2000次才能將數據與主庫保持一致,優勢是直接複製數據,會比較高效,不用去分析日誌,可是缺點也很是明顯。網絡傳輸量較大,
優勢:這種方式什麼狀況均可以使用,存儲過程,觸發器等都沒有問題,可是備庫與主庫的字段有不一致的狀況,那麼複製就會失敗。
缺點:沒法獲知執行了什麼操做,只能看到變化了的值,當問題出現後,很難去判斷故障的緣由,或是什麼致使的,並且不少狀況下,備庫的開銷很是大,並且網絡傳輸也更高。
3.2.4 推薦複製配置
此小結主要用來分析複製的配置,有些配置是沒有必要的,有些也是須要分適用場景的,主要仍是以安全爲第一,最小化可能出現的問題爲前提,而後是性能上的建議。
主庫上最重要的一個參數:sync_binlog=1
開啓,MySQL每次提交事務前都會將二進制日誌同步到磁盤上,可以保證崩潰時不丟失事務,關閉則無需再提交以前寫到磁盤,對於中繼日誌來講,不適用該參數,因此建議主庫上開啓,從庫上關閉。
若是使用InnoDB,那麼建議配置如下設置:
innodb_flush_logs_at_trx_commit:設爲1固然是最安全的,但性能頁是最差的(相對其餘兩個參數而言,但不是不能接受)。若是對數據一致性和完整性要求不高,徹底能夠設爲2,若是隻最求性能,例如高併發寫的日誌服務器,設爲0來得到更高性能。
Innodb_support_xa=1 保證binlog裏面存在的事務必定在redo log裏面存在,同時binlog裏面事務順序與redo log事務順序一致。
Innodb_safe_binlog 表示在5.0版本以前,跟Innodb_support_xa參數意思同樣。
log-bin=/data/binlog/master-bin 必定要配置文件名,否則在其它應用的時候,容易出現問題,同時制定了它的路徑。
在備庫上推薦配置:
Relay_log=/data/relaylog/relay-bin 制定路徑避免不一樣版本之間的bug問題,
Skip_slave_start 表示備庫在崩潰後不自動複製,由於可能已經不一致了,自動複製,可能致使更多的損壞,因此通常都須要禁用掉。
Read_only 能夠阻止大部分用戶更改非臨時表,除了SQL線程和超級權限用戶外。
3.2.5 複製延遲
複製延遲,在大部分的同步系統中,都存在這樣的問題,目前較爲成熟的亞秒級實時同步的解決方案是GoldenGate,固然大部分系統是不須要這麼高的要求,因此只要延遲在咱們接受的範圍內都是科學的解決方案。
複製延遲通常存在2種:一種是產生延遲而後再跟上,一種是穩定的延遲增大,前一種基本都是因爲運行一條運行很長時間的查詢致使,然後者,可能存在很是嚴重的問題致使。一般沒有太大的調優空間,簡單的辦法是配置InnoDB,能夠不那麼頻繁的刷新磁盤,事務提交更快。能夠設置innodb_flush_log_at_trx_commit值爲2來作,還能夠禁止備庫上的二進制日誌記錄,配置innodb_locks_unsafe_for_binlog爲1,並配置MyISAM的delay_key_write爲all,但這些都是犧牲安全爲代價提高效率,還有一點,是這樣配置備庫後,那麼這個永遠就只能是備庫,不能切換爲主庫了,若是須要切換,須要將配置改回來。
優化主庫高代價操做
在主庫上任何昂貴的操做,都會在備庫上重複一次,某些工做能夠移動到備庫,就不會讓高代價的操做在主從上執行2次。例如:一個大表,須要彙總到一個小表用於平常維護:
Replayce into s_db.ip_table(col1,col2,…)
Select col1,sum(col2,….) from s_db.epc_table group by col1;
若是在主庫上執行,那麼備庫也須要執行龐大的group by操做,當進行的太多的話,那麼備庫就容易跟不上了,若是在備庫上操做,完成以後能夠select into outfile,而後再load data infile將結果集加載到主庫中,這樣重負的工做變成了load data infile操做了。
備庫並行寫入
因爲備庫要求串行寫入,某些應用更新就很吃力,那麼咱們能不能並行寫入呢,固然複製自己是不具有的,這須要區分寫入的類別了,例如禁止歸檔日誌記錄到二進制日誌,而後再主庫和備庫上分別執行,提升效率,這就是OLTP系統的歸檔數據操做,每每這樣來作比讓數據庫本身靠複製完成要高效的多。
還須要注意一個問題,主庫和備庫的max_allowed_packet配置不一致,主庫可能會記錄一個備庫認爲過大的包,備庫獲取到該二進制事件後,可能會無限報錯和重試,或中繼日誌損壞。
3.2.6 半同步和複製心跳
半同步複製在提交過程當中增長了一個延遲,當提交事務時,客戶端接收到查詢結束反饋前必須保證二進制日誌已經傳輸到至少一臺備庫上。主庫將事務提交到磁盤上以後會增長一個延遲。那麼速度上延遲增長,但同步複製也會增長2段提交,增長的額外消息交換而性能不高。
也就是說主庫執行完事務後,是不會管備庫進度的,這樣提升了主庫的效率,而備庫上的事務至少有一個是跟主庫一致的,因此某種程度上講,實現了事務同步,不保證備庫已經執行完成,在性能上主庫提高較大。
複製心跳,就是主庫和備庫相互聯繫功能,避免不聲不響的斷開鏈接。當出現斷開鏈接,備庫會注意到丟失的心跳數據,當再次恢復的時候,以此爲依據,再次同步數據。