mysql
2015年5月28日11時,12小時後恢復,損失:平均每小時106.48W$sql
複製是 MySQL 的一項功能,容許服務器將更改從一個實例複製到另外一個實例。數據庫
1)兩臺或兩臺以上的數據庫實例 2)主庫要開啓二進制日誌 3)主庫要有複製用戶 4)主庫的server_id和從庫不一樣 5)從庫須要在開啓複製功能前,要獲取到主庫以前的數據(主庫備份,而且記錄binlog當時位置) 6)從庫在第一次開啓主從複製時,時必須獲知主庫:ip,port,user,password,logfile,pos IP:10.0.0.51 Port:3306 User:rep Password:oldboy123 logFile:mysql-bin.000002 Pos:120 7)從庫要開啓相關線程:IO、SQL 8)從庫須要記錄複製相關用戶信息,還應該記錄到上次已經從主庫請求到哪一個二進制日誌 9)從庫請求過來的binlog,首先要存下來,而且執行binlog,執行過的信息保存下來
主庫:vim
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,從庫不等於1 server_id =1 #開啓binlog日誌 log_bin=mysql-bin
2)建立主從複製用戶session
#登陸數據庫 [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='127.0.0.1', -> master_port=3309, -> master_user='rep', -> master_password='123', -> master_log_file='mysql-bin.000003', -> master_log_pos=1165; #從庫開啓主從複製 mysql> start slave; Query OK, 0 rows affected (0.01 sec) #從庫查看啓動結果 mysql> show slave status\G
鏈接主庫
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
1)邏輯損壞怎麼辦? 2)不能保證主庫的操做,從庫必定能作 3)高可用?自動failover? 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)怎麼利用延時從庫,恢復數據?
提示:
一、從庫relaylog存放在datadir目錄下 二、mysqlbinlog 能夠截取relaylog內容 三、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
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;
從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%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 1 | | Rpl_semi_sync_master_net_avg_wait_time | 768 | | Rpl_semi_sync_master_net_wait_time | 1497 | | Rpl_semi_sync_master_net_waits | 2 | | Rpl_semi_sync_master_no_times | 0 | | Rpl_semi_sync_master_no_tx | 0 | | Rpl_semi_sync_master_status | ON | | Rpl_semi_sync_master_timefunc_failures | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 884 | | Rpl_semi_sync_master_tx_wait_time | 1769 | | Rpl_semi_sync_master_tx_waits | 2 | | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | | Rpl_semi_sync_master_wait_sessions | 0 | #此行顯示2,表示剛纔建立的兩個庫執行了半同步 | Rpl_semi_sync_master_yes_tx | 2 | +--------------------------------------------+-------+ 14 rows in set (0.06 sec) #從庫查看 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | | test1 | | test2 | +--------------------+ #關閉半同步(1:開啓 0:關閉) mysql> SET GLOBAL rpl_semi_sync_master_enabled = 0; #查看半同步狀態 mysql> show global status like 'rpl_semi%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 1 | | Rpl_semi_sync_master_net_avg_wait_time | 768 | | Rpl_semi_sync_master_net_wait_time | 1497 | | Rpl_semi_sync_master_net_waits | 2 | | Rpl_semi_sync_master_no_times | 0 | | Rpl_semi_sync_master_no_tx | 0 | | Rpl_semi_sync_master_status | OFF | #狀態爲關閉 | Rpl_semi_sync_master_timefunc_failures | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 884 | | Rpl_semi_sync_master_tx_wait_time | 1769 | | Rpl_semi_sync_master_tx_waits | 2 | | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | | Rpl_semi_sync_master_wait_sessions | 0 | | Rpl_semi_sync_master_yes_tx | 2 | +--------------------------------------------+-------+ 14 rows in set (0.00 sec) #再一次建立兩個庫 mysql> create database test3; Query OK, 1 row affected (0.00 sec) mysql> create database test4; Query OK, 1 row affected (0.00 sec) #再一次查看半同步狀態 mysql> show global status like 'rpl_semi%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 1 | | Rpl_semi_sync_master_net_avg_wait_time | 768 | | Rpl_semi_sync_master_net_wait_time | 1497 | | Rpl_semi_sync_master_net_waits | 2 | | Rpl_semi_sync_master_no_times | 0 | | Rpl_semi_sync_master_no_tx | 0 | | Rpl_semi_sync_master_status | OFF | | Rpl_semi_sync_master_timefunc_failures | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 884 | | Rpl_semi_sync_master_tx_wait_time | 1769 | | Rpl_semi_sync_master_tx_waits | 2 | | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | | Rpl_semi_sync_master_wait_sessions | 0 | #此行仍是顯示2,則證實,剛纔的那兩條並無執行半同步不然應該是4 | Rpl_semi_sync_master_yes_tx | 2 | +--------------------------------------------+-------+ 14 rows in set (0.00 sec) 注:不難發現,在查詢半同步狀態是,開啓半同步,查詢會有延遲時間,關閉以後則沒有
白名單:只記錄白名單中列出的庫的二進制日誌 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.sock 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;