1. 程式人生 > >使用 Xtrabackup 在線對MySQL做主從復制【轉】

使用 Xtrabackup 在線對MySQL做主從復制【轉】

blog screen art http 地址 備份恢復 日誌記錄 其中 sea

1. 說明

1.1 xtrabackup

mysqldump對於導出10G以下的數據庫或幾個表,還是適用的,而且更快捷。一旦數據量達到100-500G,無論是對原庫的壓力還是導出的性能,mysqldump就力不從心了。Percona-Xtrabackup備份工具,是實現MySQL在線熱備工作的不二選擇,可進行全量、增量、單表備份和還原。(但當數據量更大時,可能需要考慮分庫分表,或使用 LVM 快照來加快備份速度了)

2.2版本 xtrabackup 能對InnoDB和XtraDB存儲引擎的數據庫非阻塞地備份,innobackupex通過perl封裝了一層xtrabackup,對MyISAM的備份通過加表讀鎖的方式實現。2.3版本 xtrabackup 命令直接支持MyISAM引擎。

XtraBackup優勢 :

  1. 無需停止數據庫進行InnoDB熱備
  2. 增量備份MySQL
  3. 流壓縮到傳輸到其它服務器
  4. 能比較容易地創建主從同步
  5. 備份MySQL時不會增大服務器負載

1.2 replication

  1. 為什麽要做主從復制?
    我想這是要在實施以前要想清楚的問題。是為了實現讀寫分離,減輕主庫負載或數據分析? 為了數據安全,做備份恢復?主從切換做高可用?
    大部分場景下,以上三個問號一主一從都能夠解決,而且任何生產環境都建議你至少要有一個從庫,假如你的讀操作壓力特別大,甚至要做一主多從,還可以不同的slave扮演不同的角色,例如使用不同的索引,或者不同的存儲引擎,或使用一個小內存server做slave只用於備份。(當然slave太多也會對master的負載和網絡帶寬造成壓力,此時可以考慮級聯復制,即 A->B->C )

    還有需要考慮的是,一主一從,一旦做了主從切換,不通過其它HA手段幹預的話,業務訪問的還是原IP,而且原主庫很容易就作廢了。於是 主-主 復制就產生了,憑借各自不同的 server-id ,可以避免 “A的變化同步到B,B應用變化又同步到A” 這樣循環復制的問題。但建議是,主主復制,其中一個主庫強制設置為只讀,主從切換後架構依然是可用的。

    復制過程是slave主動向master拉取,而不是master去推的,所以理想情況下做搭建主從時不需要master做出任何改變甚至停服,slave失敗也不影響主庫。

  1. 復制類型

    • 基於語句的復制:STATEMENT
      ,在主服務器上執行的SQL語句,在從服務器上執行同樣的語句,有可能會由於SQL執行上下文環境不同而是數據不一致,例如調用NOW()函數。MySQL在5.7.7以前默認采用基於語句的復制,在 5.7.7 及以後版本默認改用 row-based。
    • 基於行的復制:ROW,把改變的內容復制過去,而不是把命令在從服務器上執行一遍。從mysql5.0開始支持,能夠嚴格保證數據完全一致,但此時用mysqlbinlog去分析日誌就沒啥意義。因為任何一條update語句,都會把涉及到的行數據全部set值,所以binlog文件會比較大。
      (遇到的一個坑是,遷移時,從庫改正了字段默認值定義,但數據在主庫更改後,即使產生的新數據默認值是正確的,但基於行的復制依然用不正確的值字段全部更新了)
    • 混合類型的復制: MIXED,默認采用基於語句的復制,一旦發現基於語句的無法精確的復制時,就會采用基於行的復制。

    mysql系統庫mysql庫裏面表的日誌記錄格式需要說明:在通過如INSERT、UPDATE、DELETE、TRUNCATE等方式直接修改數據的語句,使用binlog_format指定的方式記錄,但使用GRANT、ALTER、CREATE、RENAME等改動的mysql庫裏數據的,會強制使用statement-based方式記錄binlog。

    可以在線修改二進制日誌類型,如SET SESSION binlog_format=MIXED;,需要SUPER權限。

    復制類型還可以分為 異步復制和半同步復制。
    通常沒說明指的都是異步,即主庫執行完Commit後,在主庫寫入Binlog日誌後即可成功返回客戶端,無需等等Binlog日誌傳送給從庫,一旦主庫宕機,有可能會丟失日誌。而半同步復制,是等待其中一個從庫也接收到Binlog事務並成功寫入Relay Log之後,才返回Commit操作成功給客戶端;如此半同步就保證了事務成功提交後至少有兩份日誌記錄,一份在主庫Binlog上,另一份在從庫的Relay Log上,從而進一步保證數據完整性;半同步復制很大程度取決於主從網絡RTT(往返時延),以插件 semisync_master/semisync_slave 形式存在。

  1. 原理
    (1) master將改變記錄到二進制日誌(binary log)中(這些記錄叫做二進制日誌事件,binary log events);
    (2) slave將master的binary log events拷貝到它的中繼日誌(relay log);
    (3) slave重做中繼日誌中的事件,將改變反映它自己的數據。

技術分享

  • 該過程的第一部分就是master記錄二進制日誌。在每個事務更新數據完成之前,master在二進制日誌記錄這些改變。MySQL將事務串行的寫入二進制日誌,即使事務中的語句都是交叉執行的。在事件寫入二進制日誌完成後,master通知存儲引擎提交事務。
  • 下一步將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上並行操作。

補充:

  • mysql 5.7開始加入了多源復制,這個特性對同時有很多個mysql實例是很有用的,阿裏雲RDS(遷移)實現了類似的方式。
  • 從MySQL 5.6.2開始,mysql binlog支持checksum校驗,並且5.6.6默認啟用(CRC32),這對自己模擬實現mysql復制的場景有影響。

下面開始配置主從

  主從版本一致—>主庫授權復制帳號—>確保開啟binlog及主從server_id唯一—>xtrabackup恢復到從庫—>記錄xtrabackup_binlog_info中binlog名稱及偏移量—>從庫change master to —>slave start—>檢查兩個yes

2. 創建復制賬號

在主庫上

mysql> GRANT REPLICATION SLAVE ON *.* TO slave_ali@192.168.5.% IDENTIFIED BY slave_ali_pass;  
mysql> FLUSH PRIVILEGES;

3. 使用Percona-Xtrabackup恢復數據

這裏假設比較簡單的情況:全量備份,全量恢復,不涉及增量。

安裝和具體使用,見文章。

賦予備份用戶權限:

mysql> CREATE USER bkpuser@localhost IDENTIFIED BY bkppass;
mysql> GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT,PROCESS,SUPER ON *.* TO bkpuser@localhost;
mysql> FLUSH PRIVILEGES;

完整的選項使用請執行innobackupex –-help,這裏只介紹使用常用的選項進行完整備份及增量備份和還原。

這一節是把數據恢復到從庫,借此記錄一下xtrabackup的使用(用了雲之後,備份技能都丟了~)。生產環境你應該是早就有了xtrabackup的備份,做從庫時只需要把備份拷過來,解壓恢復。

假設 MySQL 安裝目錄在/opt/mysql,my.cnf配置文件/opt/mysql/my.cnf,端口3306,數據目錄/opt/mysql_data,sock位於/opt/mysql_data/mysql.sock。備份數據放在/data/backup/mysql/

3.1 全量備份

$ export BKP_PASS="bkppass"
$ innobackupex --defaults-file=/opt/mysql/my.cnf --host=localhost --port=3306 --user=bkpuser --password=${BKP_PASS} /data/backup/mysql


如果手頭有一份未壓縮的全備數據,要在另一臺恢復,其實還不如直接 rsync 過來,將近400G的數據壓縮與解壓縮過程特別漫長。
默認會以當天 日期+時間 戳命名備份目錄,如 2015-09-16_00-00-02。一般會對它進行tar壓縮,由於tar只能單進程,所以往往這個壓縮過程會比備份過程耗時2倍還多。拷貝到需要恢復(做從庫)的目錄。

3.2 全量恢復

在恢復的數據庫服務器(從庫)上:

恢復準備
$ innobackupex --use-memory=16G --apply-log 2015-09-16_00-00-02
 
確認數據庫是關閉的,並且datadir,目錄下為空
$ innobackupex --defaults-file=/opt/mysql/my.cnf --use-memory=16G --copy-back 2015-09-16_00-00-02

4. 做從庫
第一步是恢復準備,apply-log應用全備時 log sequence number 之後的數據,完了後會輸出類似 InnoDB: Last MySQL binlog file position 0 262484673, file name ./mysql-bin.000135 的信息,告訴我們了後面的從庫應該從哪個地方開始復制。時間不會很長,但最好用screen之類的軟件放到後臺執行,以免終端斷開,功虧一簣。 第二步使用新的my.cnf文件,將完整的mysql數據文件拷貝到datadir下。

上面恢復過程最後一步apply-log完成之後,會得到一個lsn position 和binlog文件名:262484673、mysql-bin.000135。下面開始從庫制作。

一般在copy-back之後需要修改數據文件目錄的屬性:

chown -R mysql.mysql /opt/mysql_data


4.1 my.cnf

從庫的配置文件簡單一點可以從主庫拷貝過來,但根據需要,要註意以下幾處

  • server-id一定不能與主庫相同
    否則,會出現如下錯誤:
    Slave: received end packet FROM server, apparent master shutdown

  • 從庫一般作為只讀庫使用,所以為安全起見,設置只讀 set global read_only=1;
    可以在從服務器的 my.cnf 裏加入read-only參數來實現這一點,唯一需要註意的一點事read-only僅對沒有super權限的用戶有效。所以最好核對一下連接從服務器的用戶,確保其沒有super權限。

  • 關於從庫的事件
    MYSQL Replication 可以很好的達到你的預期:從庫的事件不會自己去執行,主庫會把event執行的結果直接同步。在statement模式下,復制的是 event BODY 裏的SQL,在row模式下是主庫事件執行完成後影響的行精確復制。

    從庫 event_scheduler 參數是被忽略的,並且每個event 狀態會是 SLAVESIDE_DISABLED ,但CREATE/ALTER EVENT等操作語句是會復制。主從切換後,從庫事件狀態會變成ENABLE。

  • 參數調整
    從庫是不允許寫入的,否則數據就不一致了。從庫實例的配置可以不要主庫那麽高,比如原16G的buffer pool,根據用途,從庫可以設到4-8G(當時前提是將來你也不打算把它切換為主庫用)。
    相應的,read_buffer_size,sort_buffer_size, query_cache_size 這些讀相關參數可以略微增大。當然我一般都懶得去改。

  • skip-slave-start
    主從創建完成後,默認情況下次啟動從庫,會自動啟動復制進程,一般這也正是我們需要的,但在維護階段時你可能不想從庫啟動後立即開始復制,--skip-slave-start選項可以幫到你。

  • log-slave-updates
    正常情況從庫是不需要寫回放日誌產生的binlog,無形中增加服務器壓力。但如果你想要實現級聯復制即 A -> B -> C ,B同時是A的從庫,也是C的主庫,就需要開啟 log-bin 和 log-slave-updates 。

    另外,建議顯示設置 log-bin=mysql-bin 確保主從正常切換。 show variables like ‘log%‘ 查看當前值。

  • 關於過濾表見mysql-replica-filter

  • sync_binlog
    For the greatest possible durability and consistency in a replication setup using InnoDB with transactions, you should use innodb_flush_log_at_trx_commit=1 and sync_binlog=1 in the master my.cnf file.

    上面的話同時也意味著性能最低。可以在這埋點,假如出現慢的情況,把兩參數調成2。

4.2 啟動從庫

啟動數據庫,註意看日誌

# /opt/mysql/bin/mysqld_safe --defaults-file=/opt/mysql/my.cnf &

提示:如果你不確定這個庫是誰的從庫,保守起見加上--skip-slave-start啟動,興許能防止數據不一致。

4.3 change master

在從庫上

$ mysql -uslave_ali -pslave_ali_pass -S /opt/mysql_data/mysql.sock
mysql> change master to master_host=MASTER_HOST, master_port=3306, 
       master_user=slave_ali,master_password=slave_ali_pass,
       master_log_file=mysql-bin.000135, master_log_pos=262484673;

上面的 master_log_file 和 master_log_pos 即是輸出的值,也可以在新的數據目錄下xtrabackup_binlog_info找到信息。

mysql> show slave status\G
mysql> start slave;
mysql> show slave status\G

4.4 驗證同步延遲

從庫執行 show slave status\G
節選:

Slave_IO_State: Waiting for master to send event
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 931
Relay_Log_File: slave1-relay-bin.000056
Relay_Log_Pos: 950
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Exec_Master_Log_Pos: 931
Relay_Log_Space: 408
Seconds_Behind_Master: 0


Master_Log_File
: I/O線程當前正在讀取的主服務器二進制日誌文件的名稱

  • Read_Master_Log_Pos:本機I/O線程讀取主服務器二進制日誌位置
    上面2各值,與在主庫執行show master status;看到的值如果基本接近,說明從庫IO線程已經趕上了主庫的binlog。
  • Relay_Master_Log_File: 由SQL線程執行的包含多數近期事件的主服務器二進制日誌文件的名稱
  • Exec_Master_Log_Pos: SQL線程執行來自master的二進制日誌最後一個事件位置
    與上面的Relay_Master_Log_File一起,同Master_Log_FileRead_Master_Log_Pos比較,能看到SQL線程是否已經趕上從庫本地的IO線程。

  • Slave_IO_Running:I/O線程是否啟動並成功連接到主服務器上
    一般和下面的Slave_IO_RunningSeconds_Behind_Master一起監控主從健康狀態

  • Slave_SQL_Running:SQL線程是否啟動
  • Seconds_Behind_Master: 從屬服務器“落後”多少秒
    官網的解釋是:The number of seconds that the slave SQL thread is behind processing the master binary log。但是當 SBM 為 0 時也不代表一定沒有延遲,因為可能因為網絡慢的緣故,從庫的IO線程傳輸binlog太慢,它的SQL線程應用日誌很容易就趕上relay log,但實際主庫產生的binlog比傳輸的快,就會造成為0的假象。
    有時你反復status會發現 Seconds_Behind_Master 的值在0與一個很大的數之間波動,有可能是主庫上執行了一個非常大的event,沒執行完畢的時候從庫SBM顯示為0,event執行完成並傳輸完binlog後,就會顯示SBM非常巨大。(我在從機房遷移mysql到阿裏雲上部分庫老出現這種情況,應該跟網絡和大event都有關系)。
    另外,relay log 中event記錄的時間戳是主庫上的時間戳,而SQL thread的時間戳是從庫上的,如果主庫和從庫的時間偏差較大,那麽這個SBM的意義就基本不存在了。

5. 參考

  • 高性能Mysql主從架構的復制原理及配置詳解
  • How does MySQL Replication really work?
  • XtraBackup不停機不鎖表搭建MySQL主從同步實踐
  • MySQL復制原理與配置
  • 許多模糊的內容還是看官網的

本文鏈接地址:http://seanlook.com/2015/12/14/mysql-replicas/

轉自

使用 Xtrabackup 在線對MySQL做主從復制 | Sean‘s Notes
http://seanlook.com/2015/12/14/mysql-replicas/

使用 Xtrabackup 在線對MySQL做主從復制【轉】