218.4.3-4.4 15周2,3次課
MySQL主從復制原理
MYSQL的主從復制是一個異步的復制過程,數據將從一個MySQL數據庫(Master)復制到另一個MySQL數據庫(Slave), 在Master與Slave 之間實現整個主從復制的過程是由三個線程參與完成的。其中有兩個線程 (SQL線程和I/O線程) 在Slave端 , 另外一個線程 ( I/O線程) 在 Master端.
要實現MySQL的主從復制,首先必須打開Master端的binlog記錄功能, 否則就無法實現。 因為整個復制過程實際上就是Slave從Master端獲取binlog日誌,然後再在 Slave上以相同順序執行獲取的binlog日誌中所記錄的各種SQL操作。
要打開MySQL的binlog記錄功能,可通過在MYSQL的配置文件my.cnf中的 mysqld模塊([mysqld]標識後的參數部分)增加"log-bin"參數選項來實現,具體信息如下。
[mysqld]
Log-bin=/data/mysql/mysql-bin
提示:有些讀者因把log-bin放在了配置文件結尾,而不是[mysqld]標識後,從而導致配置復制不成功。
下面簡單描述MySQL Replication的復制原理過程。
1) 在Slave服務器上執行start slave命令開啟主從復制開關,開始進行主從復制
2) 此時,Slave服務器的I/O線程會通過在Master上已經授權的復制用戶權限請求連接Master服務器,並請求從指定binlog日誌文件的指定位置(日誌文件名和位置就是在配置主從復制服務時執行change master命令指定的)之後開始發送binlog日誌內
3) Master服務器接收到來自Slave服務器的I/O線程的請求後,其上負責復制的I/O線程會根據Slave服務器的I/O線程請求的信息分批讀取指定binlog日誌文件指定位置之後的binlog日誌信息,然後返回給Slave端的I/O線程。返回的信息中除了binlog日誌內容外,還有在Master服務器端記錄的新的binlog文件名稱,以及在新的binlog中的下一個指定更新位置。
4) 當Slave服務器的I/O線程獲取到Master服務器上I/O線程發送的日誌內容、日誌文件及位置點後,會將binlog日誌內容依次寫到Slave端自身的Relay Log(即中繼日誌)文件(MySQL-relay-bin.xxxxxx)的最末端,並將新的binlog文件名和位置記錄到 master-info文件中,以便下一次讀取Master端新binlog日誌時能夠告訴Master服務器從新binlog日誌的指定文件及位置開始請求新的binlog日誌內容
5) Slave服務器端的SQL線程會實時檢測本地Relay Log中I/O線程新增加的日誌內容,然後及時地把Relay Log文件中的內容解析成SQL語句,並在自身Slave服務器上按解析SQL語句的位置順序執行應用這些SQL語句,並在relay-log.info中記錄當前應用中繼日誌的文件名及位置點.
經過了上面的過程,就可以確保在Master端和Slave端執行了同樣的SQL語句。當復制狀態正常時,Master端和Slave端的數據是完全一樣的。當然,MySQL的復制機制也有一些特殊情況 ,不過在大多數情況下,大家不用擔心。
針對MYSQL主從復制原理的重點進行小結:
主從復制是異步的邏輯的SQL語句級的復制。
復制時,主庫有一個I/O線程,從庫有兩個線程,即I/O 和SQL線程。
實現主從復制的必要條件是主庫要開啟記錄binlog功能。
作為復制的所有MYSQL節點的server-id都不能相同。
binlog文件只記錄對數據庫有更改的SQL語句(來自主數據庫內容的變更),不記錄任何查詢(如select、show)語句。
mysql主從數據庫不同步的2種解決方法
Mysql的主從數據庫沒有同步
先上Master庫:
mysql>show processlist; 查看下進程是否Sleep太多。發現很正常。
show master status; 也正常。
mysql> show master status;
+-------------------+----------+--------------+-------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+-------------------------------+
| mysqld-bin.000001 | 3260 | | mysql,test,information_schema |
+-------------------+----------+--------------+-------------------------------+
1 row in set (0.00 sec)
再到Slave上查看
mysql> show slave status\G
Slave_IO_Running: Yes
Slave_SQL_Running: No
可見是Slave不同步
下面介紹兩種解決方法:
方法一:忽略錯誤後,繼續同步
該方法適用於主從庫數據相差不大,或者要求數據可以不完全統一的情況,數據要求不嚴格的情況
解決:
stop slave;
#表示跳過一步錯誤,後面的數字可變
set global sql_slave_skip_counter =1;
start slave;
之後再用mysql> show slave status\G 查看:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
ok,現在主從同步狀態正常了。。。
方式二:重新做主從,完全同步
該方法適用於主從庫數據相差較大,或者要求數據完全統一的情況
解決步驟如下:
1.先進入主庫,進行鎖表,防止數據寫入
使用命令:
mysql> flush tables with read lock;
註意:該處是鎖定為只讀狀態,語句不區分大小寫
2.進行數據備份
#把數據備份到mysql.bak.sql文件
[root@server01 mysql]#mysqldump -uroot -p -hlocalhost > mysql.bak.sql
這裏註意一點:數據庫備份一定要定期進行,可以用shell腳本或者python腳本,都比較方便,確保數據萬無一失
3.查看master 狀態
mysql> show master status;
+-------------------+----------+--------------+-------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+-------------------------------+
| mysqld-bin.000001 | 3260 | | mysql,test,information_schema |
+-------------------+----------+--------------+-------------------------------+
1 row in set (0.00 sec)
4.把mysql備份文件傳到從庫機器,進行數據恢復
#使用scp命令
[root@server01 mysql]# scp mysql.bak.sql [email protected]:/tmp/
5.停止從庫的狀態
mysql> stop slave;
6.然後到從庫執行mysql命令,導入數據備份
mysql> source /tmp/mysql.bak.sql
7.設置從庫同步,註意該處的同步點,就是主庫show master status信息裏的| File| Position兩項
change master to master_host = '192.168.128.100', master_user = 'rsync', master_port=3306, master_password='', master_log_file = 'mysqld-bin.000001', master_log_pos=3260;
8.重新開啟從同步
mysql> stop slave;
9.查看同步狀態
mysql> show slave status\G 查看:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
好了,同步完成啦。
mysql一主多從同步配置
一主多從,其實和一主一從是一樣的原理
一、環境
Master:192.168.1.100
slave1:192.168.1.110
slave2:192.168.1.111
master和 slave上的相關配置
master 上編輯my.cnf文件
在[mysqld]下添加如下字段:
server-id = 100
log-bin=mysql-bin
binlog-do-db=YYY //需要同步的數據庫
binlog-ignore-db=mysql //被忽略的數據庫
binlog-ignore-db=information-schema //被忽略的數據庫
在master上為slave添加一個同步賬號
grant replication slave on *.* to 'repl'@192.168.1.110 identified by '123456'; //在slave1上登陸成功
grant replication slave on *.* to 'repl'@192.168.37.111 identified by 'password'; //在slave2上登陸成功
保存後,重啟master的mysql服務:
service mysql restart;
用show master status命令查看日誌情況
修改slave1上的配置文件my.cnf
在[mysqld]下添加如下字段:
server-id = 110
保存後,重啟slave1的mysql服務
先關閉主從同步:stop slave;
實現主從同步:
change master to master_host='192.168.1.100', master_user='repl', master_password='123456', master_log_file=' mysql-bin.000001', master_log_pos=320;
打開同步:start slave;
判斷主從是否配置成功:show slave status\G(最後可以不用分號,\G本身就是結束符)
確認以下兩項參數都為Yes
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
修改slave2上的配置文件my.cnf
在[mysqld]下添加如下字段:
server-id = 111
其他操作和slave1上相同
MySQL雙主(主主)架構方案
MySQL雙主(主主)架構方案思路是:
1.兩臺mysql都可讀寫,互為主備,默認只使用一臺(masterA)負責數據的寫入,另一臺(masterB)備用;
2.masterA是masterB的主庫,masterB又是masterA的主庫,它們互為主從;
3.兩臺主庫之間做高可用,可以采用keepalived等方案(使用VIP對外提供服務);
4.所有提供服務的從服務器與masterB進行主從同步(雙主多從);
5.建議采用高可用策略的時候,masterA或masterB均不因宕機恢復後而搶占VIP(非搶占模式);
這樣做可以在一定程度上保證主庫的高可用,在一臺主庫down掉之後,可以在極短的時間內切換到另一臺主庫上(盡可能減少主庫宕機對業務造成的影響),減少了主從同步給線上主庫帶來的壓力;
但是也有幾個不足的地方:
1.masterB可能會一直處於空閑狀態(可以用它當從庫,負責部分查詢);
2.主庫後面提供服務的從庫要等masterB先同步完了數據後才能去masterB上去同步數據,這樣可能會造成一定程度的同步延時;
架構的簡易圖如下:
主主環境:
1. 2臺:masterA(192.168.1.100,masterB(192.168.1.101)CentOS 7.4
2.Mysql5.6版本
添加masterA配置文件/etc/my.cnf
[mysqld]
server-id = 100
log-slave-updates = true #將復制事件寫入binlog,一臺服務器既做主庫又做從庫此選項必須要開啟
#masterA自增長ID
auto_increment_offset = 1
auto_increment_increment = 2 #奇數ID
添加masterB配置文件/etc/my.cnf
[mysqld]
server-id = 101
log-slave-updates = true #將復制事件寫入binlog,一臺服務器既做主庫又做從庫此選項必須要開啟
#masterB自增加ID
auto_increment_offset = 2
auto_increment_increment = 2 #偶數ID
添加主從同步賬戶
masterA上:
mysql> grant replication slave on *.* to 'repl'@'192.168.1.101' identified by '123456';
mysql> flush privileges;
masterB上:
mysql> grant replication slave on *.* to 'repl'@'192.168.1.100' identified by '123456';
mysql> flush privileges;
查看主庫的狀態
masterA上:
mysql> show master status;
File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 120 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
masterB上
mysql> show master status;
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 437 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
配置同步信息:
masterA上:
mysql>change master to
master_host='192.168.10.12',master_port=3306,master_user='repl',master_password='123456',master_log_file='mysql-bin.000003',master_log_pos=437;
mysql> start slave;
mysql> show slave status\G;
顯示有如下狀態則正常:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
masterB上:
#本人是測試環境,可以保證沒數據寫入,否則需要的步驟是:先masterA鎖表-->masterA備份數據-->masterA解鎖表 -->masterB導入數據-->masterB設置主從-->查看主從
mysql> change master to
master_host='192.168.1.100',master_port=3306,master_user='repl',master_password='123456',master_log_file='mysql-bin.000003',master_log_pos=120;
mysql>start slave;
mysql> show slave status\G;
顯示有如下狀態則正常:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
開啟MySQL5.6的GTID功能
masterA和masterB分別執行如下命令:
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> change master to MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
218.4.3-4.4 15周2,3次課