MySQL的主從復制、延時從庫、半同步復制


1.主從復制簡介

1)高可用
2)輔助備份
3)分擔負載

復制是 MySQL 的一項功能,允許服務器將更改從一個實例復制到另一個實例。

1)主服務器將所有數據和結構更改記錄到二進制日志中。
2)從屬服務器從主服務器請求該二進制日志並在本地應用其內容。
3)IO:請求主庫,獲取上一次執行過的新的事件,並存放到relaylog
4)SQL:從relaylog中將sql語句翻譯給從庫執行

2.主從復制原理

1)兩台或兩台以上的數據庫實例
2)主庫要開啟二進制日志
3)主庫要有復制用戶
4)主庫的server_id和從庫不同
5)從庫需要在開啟復制功能前,要獲取到主庫之前的數據(主庫備份,並且記錄binlog當時位置)
6)從庫在第一次開啟主從復制時,時必須獲知主庫:ip,port,user,password,logfile,pos

7)從庫要開啟相關線程:IO、SQL
8)從庫需要記錄復制相關用戶信息,還應該記錄到上次已經從主庫請求到哪個二進制日志
9)從庫請求過來的binlog,首先要存下來,並且執行binlog,執行過的信息保存下來

 

主從復制涉及到的文件和線程

主庫:

1)主庫binlog:記錄主庫發生過的修改事件
2)dump thread:給從庫傳送(TP)二進制日志線程

從庫:

1)relay-log(中繼日志):存儲所有主庫TP過來的binlog事件
2)master.info:存儲復制用戶信息,上次請求到的主庫binlog位置點
3)IO thread:接收主庫發來的binlog日志,也是從庫請求主庫的線程
4)SQL thread:執行主庫TP過來的日志

原理

1)通過change master to語句告訴從庫主庫的ip,port,user,password,file,pos
2)從庫通過start slave命令開啟復制必要的IO線程和SQL線程
3)從庫通過IO線程拿着change master to用戶密碼相關信息,連接主庫,驗證合法性
4)從庫連接成功后,會根據binlog的pos問主庫,有沒有比這個更新的
5)主庫接收到從庫請求后,比較一下binlog信息,如果有就將最新數據通過dump線程給從庫IO線程
6)從庫通過IO線程接收到主庫發來的binlog事件,存儲到TCP/IP緩存中,並返回ACK更新master.info
7)將TCP/IP緩存中的內容存到relay-log中
8)SQL線程讀取relay-log.info,讀取到上次已經執行過的relay-log位置點,繼續執行后續的relay-log日志,執行完成后,更新relay-log.info

主從復制搭建實戰

主庫操作:

1)修改配置文件

#編輯mysql配置文件

[root@db01 ~]# vim /etc/my.cnf

#在mysqld標簽下配置

[mysqld]

#主庫server-id=1,從庫不等於1server_id =1

#開啟binlog日志

log_bin=mysql-bin

 

2)創建主從復制用戶

 

#登錄數據庫 [root@db01 ~]# mysql -uroot -poldboy123 #

創建rep用戶

mysql> grant replication slave on *.* to rep@'10.0.0.%' identified by 'oldboy123';

從庫操作:

1)修改配置文件

#修改db02配置文件

[root@db02 ~]# vim /etc/my.cnf

#在mysqld標簽下配置

[mysqld]

#主庫server-id為1,從庫不等於1 server_id =5

#重啟mysql

[root@db02 ~]# /etc/init.d/mysqld restart

#記錄主庫binlog及位置點

mysql> show master status;

#登陸數據庫

[root@db02 ~]# mysql -uroot -poldboy123

#執行change master to 語句

mysql> change master to

-> master_host='10.0.0.51',

-> master_user='rep',

-> master_password='oldboy123',

-> master_auto_position=1;

3.主從復制基本故障處理

IO線程

連接主庫

1)user password ip port
2)網絡:不通,延時高,防火牆

請求binlog

1)binlog不存在或者損壞

更新relay-log和master.info

SQL線程
1)relay-log出現問題
2)從庫做寫入了

操作對象已存在(create)

操作對象不存在(insert update delete drop truncate alter)

約束問題、數據類型、列屬性

處理方法一:

#臨時停止同步

mysql> stop slave;

#將同步指針向下移動一個(可重復操作)

mysql> set global sql_slave_skip_counter=1

; #開啟同步

mysql> start slave;

處理方法二:

#編輯配置文件

[root@db01 ~]# vim /etc/my.cnf

#在[mysqld]標簽下添加以下參數

slave-skip-errors=1032,1062,1007

 以上操作都是有風險存在的

處理方法三:

1)重新備份數據庫,恢復到從庫
2)給從庫設置為只讀

#在命令行臨時設置

set global read_only=1;

#在配置文件中永久生效

read_only=1

4.延時存庫

企業中一般會延時3-6小時

延時從庫配置方法

#停止主從

mysql>stop slave;

#設置延時為180秒

mysql>CHANGE MASTER TO MASTER_DELAY = 180;

#開啟主從

mysql>start slave;

#查看狀態

mysql> show slave status \G

SQL_Delay: 60

3.延時從庫停止方法

#停止主從

mysql> stop slave;

#設置延時為0

mysql> CHANGE MASTER TO MASTER_DELAY = 0;

#開啟主從

mysql> start slave;

總數據量級500G,正常備份去恢復需要1.5-2小時
1)配置延時3600秒

mysql>CHANGE MASTER TO MASTER_DELAY = 3600;

2)主庫

drop database db;

3)怎么利用延時從庫,恢復數據?

提示:
1、從庫relaylog存放在datadir目錄下
2、mysqlbinlog 可以截取relaylog內容
3、show relay log events in 'db01-relay-bin.000001';

處理的思路:

1)停止SQL線程

mysql> stop slave sql_thread;

2)截取relaylog到誤刪除之前點

  • relay-log.info 獲取到上次運行到的位置點,作為恢復起點
  • 分析relay-log的文件內容,獲取到誤刪除之前position

模擬故障處

1)關閉延時

mysql -S /data/3308/mysql.sock

mysql> stop slave;

mysql> CHANGE MASTER TO MASTER_DELAY = 0;

mysql> start slave;

2)模擬數據

mysql -S /data/3307/mysql.sock

source /root/world.sql

use world;

create table c1 select * from city;

create table c2 select * from city

3)開啟從庫延時5分鍾

mysql -S /data/3308/mysql.sock

show slave status \G

mysql>stop slave;

mysql>CHANGE MASTER TO MASTER_DELAY = 300;

mysql>start slave;

mysql -S /data/3307/mysql.sock

use world;

create table c3 select * from city;

create table c4 select * from city;

4)破壞,模擬刪庫故障。(以下步驟在5分鍾內操作完成。)

mysql -S /data/3307/mysql.sock

drop database world;

5)從庫,關閉SQL線程

mysql -S /data/3308/mysql.sock

stop slave sql_thread;

6)截取relay-log

起點:

cd /data/3308/data/

cat relay-log.info

./db01-relay-bin.000002

283

終點:

mysql -S /data/3308/mysql.sock

show relaylog events in 'db01-relay-bin.000002'

db01-relay-bin.000002 | 268047

mysqlbinlog --start-position=283 --stop-position=268047 /data/3308/data/db01-relay-bin.000002 >/tmp/relay.sql

恢復relay.sql

1)取消從庫身份

mysql> stop slave;

mysql> reset slave all;

2)恢復數據

mysql> set sql_log_bin=0;

mysql> source /tmp/relay.sql

mysql> use world

mysql> show tables;

6.半同步復制

從MYSQL5.5開始,支持半自動復制。之前版本的MySQL Replication都是異步(asynchronous)的,主庫在執行完一些事務后,是不會管備庫的進度的。如果備庫不幸落后,而更不幸的是主庫此時又出現Crash(例如宕機),這時備庫中的數據就是不完整的。簡而言之,在主庫發生故障的時候,我們無法使用備庫來繼續提供數據一致的服務了。

半同步復制(Semi synchronous Replication)則一定程度上保證提交的事務已經傳給了至少一個備庫。
出發點是保證主從數據一致性問題,安全的考慮。


5.5 出現概念,但是不建議使用,性能太差
5.6出現group commit 組提交功能,來提升開啟半同步復制的性能
5.7更加完善了,在group commit基礎上出現了MGR
5.7的增強半同步復制的新特性:after commit; after sync;

半同步復制開啟方法

1)安裝(主庫)

#登錄數據庫

[root@db01 ~]# mysql -uroot -poldboy123

#查看是否有動態支持

mysql> show global variables like 'have_dynamic_loading';

#安裝自帶插件

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME'semisync_master.so';

#啟動插件

mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;

#設置超時

mysql> SET GLOBAL rpl_semi_sync_master_timeout = 1000;

#修改配置文件

[root@db01 ~]# vim /etc/my.cnf

#在[mysqld]標簽下添加如下內容(不用重啟庫)

[mysqld]

rpl_semi_sync_master_enabled=1

rpl_semi_sync_master_timeout=1000

檢查安裝:

mysql> show variables like'rpl%';

mysql> show global status like 'rpl_semi%';

2)安裝(從庫)

#登錄數據庫

[root@mysql-db02 ~]# mysql -uroot -poldboy123

#安裝slave半同步插件

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME'semisync_slave.so';

#啟動插件

mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;

#重啟io線程使其生效

mysql> stop slave io_thread;

mysql> start slave io_thread;

#編輯配置文件(不需要重啟數據庫)

[root@mysql-db02 ~]# vim /etc/my.cnf

#在[mysqld]標簽下添加如下內容

[mysqld]

rpl_semi_sync_slave_enabled =1

注:相關參數說明
rpl_semi_sync_master_timeout=milliseconds
設置此參數值(ms),為了防止半同步復制在沒有收到確認的情況下發生堵塞,如果Master在超時之前沒有收到任何確認,將恢復到正常的異步復制,並繼續執行沒有半同步的復制操作。

rpl_semi_sync_master_wait_no_slave={ON|OFF}
如果一個事務被提交,但Master沒有任何Slave的連接,這時不可能將事務發送到其它地方保護起來。默認情況下,Master會在時間限制范圍內繼續等待Slave的連接,並確認該事務已經被正確的寫到磁盤上。
可以使用此參數選項關閉這種行為,在這種情況下,如果沒有Slave連接,Master就會恢復到異步復制。

測試半同步

#創建兩個數據庫,test1和test2

mysql> create database test1;

Query OK, 1 row affected (0.04 sec)

mysql> create database test2;

Query OK, 1 row affected (0.00 sec)

#查看復制狀態

mysql> show global status like 'rpl_semi%';

#關閉半同步(1:開啟 0:關閉)

mysql> SET GLOBAL rpl_semi_sync_master_enabled = 0;

#查看半同步狀態

mysql> show global status like 'rpl_semi%';

 

#再一次創建兩個庫

mysql> create database test3;

 mysql> create database test4;

#再一次查看半同步狀態

mysql> show global status like 'rpl_semi%';

注:不難發現,在查詢半同步狀態是,開啟半同步,查詢會有延遲時間,關閉之后則沒有

 7.過濾復制

 

主庫:

白名單:只記錄白名單中列出的庫的二進制日志

  • binlog-do-db

黑名單:不記錄黑名單列出的庫的二進制日志

  • binlog-ignore-db

從庫:

白名單:只執行白名單中列出的庫或者表的中繼日志

  • --replicate-do-db=test
  • --replicate-do-table=test.t1
  • --replicate-wild-do-table=test.t2

黑名單:不執行黑名單中列出的庫或者表的中繼日志

  • --replicate-ignore-db
  • --replicate-ignore-table
  • --replicate-wild-ignore-table

復制過濾配置:

 [root@db01 data]#

vim /data/3307/my.cnf

#在[mysqld]標簽下添加

replicate-do-db=world

#關閉MySQL

mysqladmin -S /data/3307/mysql.sock shutdown

#啟動MySQL

mysqld_safe --defaults-file=/data/3307/my.cnf &

測試復制過濾:

第一次測試:

1)主庫:

 [root@db02 ~]# mysql -uroot -p123 -S /data/3308/mysql.sock

mysql> use world

mysql> create table t1(id int);

 2)從庫查看結果:

 [root@db02 ~]# mysql -uroot -p123 -S /data/3307/mysql.sock

mysql> use world

mysql> show tables;

 

第二次測試:

1)主庫:

[root@db02 ~]# mysql -uroot -p123 -S /data/3308/mysql.soc

mysql> use test

mysql> create table tb1(id int);

 

 2)從庫查看結果:

[root@db02 ~]# mysql -uroot -p123 -S /data/3307/mysql.sock

mysql> use test

mysql> show tables;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM