(1)擴展方式: Scale Up ,Scale Outhtml
(2)MySQL的擴展mysql
讀寫分離
複製:每一個節點都有相同的數據集
向外擴展
二進制日誌
單向
(3)複製的功用:linux
數據分佈
負載均衡讀
備份
高可用和故障切換
MySQL升級測試
兩臺或兩臺以上實例,經過binlog實現最終數據同步關係;sql
主從複製前提(搭建過程)
a.至少兩臺MySQL實例,server_id,server_uuid不一樣;
b.主庫要開binlog
c.專用的複製用戶和權限
d.預同步主庫數據到從庫
e.告訴從庫鏈接\同步起點
f.啓動複製線程
配置主庫數據庫
安裝 mysql 8.0.20 二進制包vim
配置二進制文件路徑,server_id緩存
cat > /etc/my.cnf <<EOF [mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/3306/data port=3306 socket=/tmp/mysql.sock server_id=10 log_bin=/data/3306/data/binlog plugin-load-add=mysql_clone.so clone=FORCE_PLUS_PERMANENT [client] socket=/tmp/mysql.sock EOF
重啓MySQL安全
systemctl restart mysqld
驗證二進制日誌,clone插件是否開啓,server_id,server_uuid是否和從庫不一樣bash
select @@log_bin; select @@log_bin_basename; select @@server_id; select @@server_uuid; SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'clone';
建立複製專用用戶並受權服務器
create user repl@'10.0.0.%' identified with mysql_native_password by '123'; grant replication slave on *.* to repl@'10.0.0.%';
建立給予端用戶並受權
CREATE USER 'donor_clone_user'@'%' IDENTIFIED BY '123'; GRANT BACKUP_ADMIN on *.* to 'donor_clone_user'@'%';
查看主狀態
show master status;
配置從庫
安裝 mysql 8.0.20 二進制包
配置server_id和主庫不一樣
cat > /etc/my.cnf <<EOF [mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/3306/data port=3306 socket=/tmp/mysql.sock server_id=20 log_bin=/data/3306/data/binlog plugin-load-add=mysql_clone.so clone=FORCE_PLUS_PERMANENT [client] socket=/tmp/mysql.sock EOF
重啓MySQL
systemctl restart mysqld
驗證server_id,server_uuid是否和從庫不一樣,clone插件是否開啓
select @@server_id; select @@server_uuid; SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'clone';
建立接受端用戶並受權
CREATE USER 'recipient_clone_user'@'%' IDENTIFIED BY '123'; GRANT CLONE_ADMIN on *.* to 'recipient_clone_user'@'%';
設置主庫IP:端口加入給予主機列表
SET GLOBAL clone_valid_donor_list='10.0.0.51:3306';
使用克隆用戶鏈接新數據庫
mysql -urecipient_clone_user -p1 -h10.0.0.61
執行遠程克隆
CLONE INSTANCE FROM 'donor_clone_user'@'10.0.0.51':3306 IDENTIFIED BY '123';
克隆完成,新數據庫自動重啓
使用root用戶鏈接新數據庫
mysql -uroot -p123
查看克隆狀態信息
mysql> select * from performance_schema.clone_status\G *************************** 1. row *************************** ID: 1 PID: 0 STATE: Completed BEGIN_TIME: 2020-11-18 10:22:39.531 END_TIME: 2020-11-18 10:22:46.824 SOURCE: 10.0.0.51:3306 DESTINATION: LOCAL INSTANCE ERROR_NO: 0 ERROR_MESSAGE: BINLOG_FILE: binlog.000021 BINLOG_POSITION: 276 GTID_EXECUTED: 1aa38bc6-1cbc-11eb-a6b8-000c29caebef:1-9, c985eb8e-2896-11eb-a6af-000c29caebef:1-3, d1d0b198-2899-11eb-babe-000c29caebef:1-4 1 row in set (0.01 sec)
告訴從庫鏈接信息,從什麼位置點開始自動複製(help change master to
)
CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_USER='repl', MASTER_PASSWORD='123', MASTER_PORT=3306, MASTER_LOG_FILE='binlog.000021', MASTER_LOG_POS=276, MASTER_CONNECT_RETRY=10;
注意:
MASTER_LOG_FILE
和MASTER_LOG_POS
必須和主庫中show master status;
查到的一致
啓動複製線程
start slave;
查看從狀態
show slave status \G
主從複製原理
# 主庫: binlog 二進制日誌 # 從庫 relaylog:中繼日誌,從庫用來臨時存儲接收到的binlog master.info:主庫相關信息(ip port user password 已經獲取的binlog 位置點) relay-log.info:存儲SQL線程回放過的日誌 三線程四文件(主庫一個文件,從庫三個文件。主庫一個線程,從庫兩個線程)
主節點:
dump Thread:爲每一個Slave的I/O Thread啓動一個dump線程,用於向其發送binary log events
從節點:
I/O Thread:向Master請求二進制日誌事件,並保存於中繼日誌中
SQL Thread:從中繼日誌中讀取日誌事件,在本地完成重放
主從複製特色:
異步複製
主從數據不一致比較常見
複製架構:
Master/Slave, Master/Master, 環狀複製 一主多從 從服務器還能夠再有從服務器 一從多主:適用於多個不一樣數據庫 主主
複製須要考慮二進制日誌事件記錄格式
STATEMENT(5.0以前)
ROW(5.1以後,推薦)
MIXED
主從複製(Classic Replication)原理描述:異步複製
從庫執行 change master to ...
時,將主庫鏈接信息和binlog位置信息寫入master.info
文件或者slave_master_info
表中
從庫執行 start slave
時,從庫啓動IO線程和SQL線程
IO線程讀取master.info
,獲取主庫信息鏈接主庫
主庫會生成一個DUMP
線程(自動監控binlog
變化),來響應從庫
IO線程根據master.info
記錄的binlog
文件名和position
號,請求主庫DUMP
最新日誌
DUMP線程檢查主庫的binlog
日誌,若是有新的,傳送給從從庫的IO線程,主庫不關心投遞的結果(異步)。
IO線程將收到的日誌存儲到了TCP/IP 緩存
IO線程將緩存中的數據,存儲到relay-log日誌文件,更新master.info
文件或者slave_master_info
表的binlog
文件名和postion
,IO線程工做完成
SQL線程讀取relay-log.info
文件或者slave_relay_log_info
表,獲取到上次執行到的db02-relay-bin
的位置,做爲起點,回放db02-relay-bin
SQL線程回放完成以後,會更新relay-log.info
文件。
回放過的db02-relay-bin
,relay_log_purge
線程會按期刪除這些日誌。
注意:主庫一旦有新的日誌生成,dump 會發送「信號」給從庫 ,IO線程再去請求
https://mariadb.com/kb/en/library/setting-up-replication/ https://dev.mysql.com/doc/refman/5.5/en/replication-configuration.html
常見報錯場景:
通訊故障:
外部網絡問題(防火牆,網絡不通,...)
鏈接信息問題(ip\port\user\passwd)
用戶錯誤
密碼錯誤
-- 報錯信息:
Slave_IO_Running: Connecting Last_IO_Errno: 1045 Last_IO_Error: error connecting to master 'repl1@10.0.0.51:3306' - retry-time: 10 retries: 2 message: Access denied for user 'repl1'@'10.0.0.61' (using password: YES) -- 鏈接測試:
[root@db01 ~]# mysql -urepl -p123333 -h 10.0.0.51 -P 3306 mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 1045 (28000): Access denied for user 'repl'@'10.0.0.61' (using password: YES)
-- 處理方法:
stop slave; reset slave all; change master to ... ; start slave; show slave status \G
地址錯誤
Slave_IO_Running: Connecting Last_IO_Errno: 0 Last_IO_Error:
端口錯誤
-- 報錯信息:
Slave_IO_Running: Connecting Last_IO_Errno: 2003 Last_IO_Error: error connecting to master 'repl@10.0.0.51:3307' - retry-time: 10 retries: 1 message: Can't connect to MySQL server on '10.0.0.51' (111) -- 鏈接測試:
[root@db01 opt]# mysql -urepl -p123333 -h 10.0.0.51 -P 3307 mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 2003 (HY000): Can't connect to MySQL server on '10.0.0.51' (111)
禁止域名解析:skip_name_resolve
達到最大鏈接數上限
-- 報錯信息:
Last_IO_Errno: 1040
Last_IO_Error: error reconnecting to master 'repl@10.0.0.51:3307' - retry-time: 10 retries: 7
-- 鏈接測試:
[root@db01 ~]# mysql -urepl -p123 -h 10.0.0.51 -P 3307
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1040 (HY000): Too many connections
-- 處理方法:
set global max_connections=1024;
請求二進制日誌故障:
主庫二進制日誌文件名錯誤或缺失
Slave_IO_Running: No Last_IO_Errno: 13114 Last_IO_Error: Got fatal error 1236 from master when reading data from binary log:
'Could not find first log file name in binary log index file'
主庫二進制日誌文件位置點錯誤
Slave_IO_Running: No Last_IO_Errno: 13114 Last_IO_Error: Got fatal error 1236 from master when reading data from binary log:
'binlog truncated in the middle of event; consider out of disk space on master; the first event 'binlog.000021' at 156, the last event read from '/data/3306/data/binlog.000021' at 125,
the last byte read from '/data/3306/data/binlog.000021' at 276.'
注意: 在主從複製中,禁止主庫
reset master;
。能夠選擇expire
進行按期清理主庫二進制日誌
server_id
重複
Last_IO_Errno: 13117 Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work (or the --replicate-same-server-id
option must be used on slave but this does not always make sense; please check the manual before using it).
server_uuid
重複
Last_IO_Errno: 1593 Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs;
these UUIDs must be different for replication to work.
正常狀態:
Slave_SQL_Running: Yes Last_SQL_Errno: 0 Last_SQL_Error:
故障狀態:
Slave_SQL_Running: NO Last_SQL_Errno: 故障代碼 Last_SQL_Error: 故障信息
故障緣由分析:
SQL線程功能:回放relay-log.info
,執行裏面的SQL語句。
故障現象
relay-log
損壞,斷節,找不到
接收到的SQL沒法執行
要建立的對象,已經存在
要刪除或修改的對象不存在
約束衝突,DML語句不符合表定義及約束
版本差別,參數設定不一樣,好比:數據類型的差別,SQL_MODE影響
故障緣由
chang master to ...
指定的binlog
位置點不對
從庫被寫入
業務繁忙時,從庫宕機了
主從切換時,沒有正確操做(鎖定原主庫+binlog寫入)
雙主結構,沒有正確使用
Last_SQL_Error: Error 'Can't create database 'db'; database exists' on query. Default database: 'db'. Query: 'create database db'
解決方案:
以主庫爲準
衝突操做回退回去
從庫跳過錯誤
pt-checksum
/pt-sync
從庫跳過指定錯誤代碼
vim /etc/my.cnf
[mysqld]
slave-skip-errors = 1032,1062,1007
常見錯誤代碼:
1007: 對象已存在
1032: 沒法執行DML
1062: 主鍵衝突,或約束衝突
將同步指針向下移動一個,若是屢次不一樣步,能夠重複操做。
stop slave;
set global sql_slave_skip_counter=1;
start slave;
刪除從庫中有衝突的數據,有風險
最安全的作法就是從新構建主從
從庫配置只讀
show variables like '%read_only%';
select @@read_only;
select @@super_read_only;
-- 普通用戶只讀
set @@read_only=1;
-- 管理員用戶只讀
set @@super_read_only=1;
雙主結構,屏蔽多寫
加中間件,讀寫分離。
主從延時:主庫作的操做,從庫好久才作。
主從延時帶來的延伸問題:
讀寫分離架構,依賴主從環境。主庫做爲寫節點,從庫做爲讀節點。要是太高,致使讀的不及時。
高可用架構,依賴主從環境。主庫宕機,故障切換時,可能會丟失較多數據。
時間差,主從延時的秒數(非人爲)
Seconds_Behind_Master: 0
主庫日誌執行位置點
Master_Log_File: mysql-bin.000005 Read_Master_Log_Pos: 444
從庫日誌執行位置點
Relay_Log_File: db01-relay-bin.000002 Relay_Log_Pos: 485
對比主從日誌執行位置點,能夠找到故障操做點,計算延時日誌量
主從硬件差別
主從版本差別
網絡問題:延時、阻塞、攻擊
資源耗盡
大事務(儘可能切割)大事務拆成多個小事務,能夠有效的減小主從延時。
全表掃描
存儲過程
DDL阻塞
...
其餘緣由
過分追求安全:從庫關閉「雙一」
鎖衝突:RR隔離級別,鎖衝突嚴重;調整爲RC隔離級別,保證索引主從一致
產生場景:
主庫併發大量事務
從庫個數多
binlog_dump 線程以事件爲單元,串行傳輸二進制日誌給從庫IO,串行阻塞後續的事務(5.6 5.5),致使主從延時。
解決方案:
5.6 版本:開啓GTID,實現GC(
5.7 版本:不開啓GTID,也會自動維護匿名的GTID,也能實現GC,建議開啓GTID
產生場景:
主庫併發大量事務,從庫默認只有一個SQL線程,串行回放relay-log中的事務,阻塞後續的事務運行,致使主從延時。
解決方案:
5.6 版本:開啓GTID,加入SQL多線程的特性,可是隻能針對不一樣庫(database)下的事務進行併發回放。
5.7 版本:開始GTID,加入MTS(enhanced multi-threaded slave
)技術,基於logical_clock
(邏輯時鐘)機制,binlog
加入了seq_no
機制,真正實現了基於事務級別的併發回放。
產生情景:
需求:master 有4個庫A,B,C ,D,如今須要將其中2個庫B,C單獨拆分出來。
作法:單獨搭建一個只有B,C庫的實例,而後只複製master的B,C庫,過濾掉A,D庫。
show master status;
# 使用白名單或黑名單控制二進制日誌是否記錄,不經常使用
Binlog_Do_DB # 白名單,出現的記錄
Binlog_Ignore_DB # 黑名單,出現的不記錄
show slave status\G
# 在SQL線程回放流程中,加入過濾功能:庫,表,通配符表的白名單和黑名單
# 白名單:只執行白名單中列出的庫或者表的中繼日誌
# 黑名單:不執行黑名單中列出的庫或者表的中繼日誌
Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table
在線配置:
stop slave SQL_THREAD; change replication filter Replicate_Do_Table=(test.t1,test.t2); start slave sql_thread;
永久配置:
vim /etc/my.cnf [mysqld] replicate_do_table=test.t1 replicate_do_table=test.t2
注意1:庫級別的規則,只針對
binlog_format='STATEMENT or MIXED‘
注意2:binlog_format=‘ROW’
,不受庫級別規則限制,只受表級別規則限制。
注意: 如下總結和測試,前提都是
binlog-format='MIXED'
DB level:
binlog-format=statement
時,過濾以use DB爲主(不容許跨庫)
binlog-format=row
時:過濾不以use DB爲主(容許跨庫)
binlog-format=statement or row
,table level 的判斷都是不以use DB爲主(能夠跨庫的)
總的流程走向:
先判斷 DB-level,若是 DB-level 判斷完成後須要 exit,則退出。
若是 DB-level 判斷完成後,沒有 exit,則再判斷Table-level。
DB-level:
若是有 replicate-do-db,則判斷 replicate-do-db,將不會走到 replicate-ignore-db 這層。
若是判斷 replicate-do-db 符合條件,則判斷 table-level。 若是不符合,則exit。
若是沒有 replicate-do-db,可是有 replicate-ignore-db 。
若是判斷符合replicate-ignore-db規則,則exit。不符合,則走到 table-level 層繼續判斷。
Table-level:
判斷邏輯順序自上而下爲:replicate-do-table -> replicate-ignore-table -> replicate-wild-do-table -> replicate-wild-ignore-table
從第一個階段(replicate-do-table)開始,若是符合replicate-do-table判斷規則,則exit。
若是不符合,則跳到下一層(replicate-ignore-table)。
以此類推,直到最後一層(replicate-wild-ignore-table)都不符合,則最後判斷是否有(replicate-do-table or replicate-wild-do-table),若是有,則 ignore & exit。若是沒有,則execute & exit
說明:如下測試,均以statement格式爲例。 rows模式參見原理一樣能夠證實。
設置replicate_do_DB=A,B
結論:A和B都沒有在slave上執行。由於mysql將'A,B'做爲一個庫名。
只有庫級別的規則
do-db
replicate_do_DB=A replicate_do_DB=B
ignoare-db
replicate_ignore_DB=A replicate_ignore_DB=B
do-db & ignore-db
replicate_do_DB=A replicate_do_DB=B replicate-ignore-db=mysql replicate-ignore-db=test
只有表級別的規則
do-table
ignore-table
wild-do-table
wild-ignore-table
do-table & ignore-table
do-table & wild-ignore-table
wild-do-table & wild-ignore-table
庫和表級別的規則混用
do-DB & do-table
replicate_do_DB=A replicate_do_DB=B replicate-do-table=table1 replicate-do-table=table2
do-DB & wild-do-table
replicate_do_DB=A replicate_do_DB=B replicate-wild-do-table=mysql.% replicate-wild-do-table=test.%
do-DB & ignore-table
replicate_do_DB=A replicate_do_DB=B replicate-ignore-table=table1 replicate-ignore-table=table2
do-DB & wild-ignore-table
replicate_do_DB=A replicate_do_DB=B replicate-wild-ignore-table=mysql.% replicate-wild-ignore-table=test.%
最多見場景: db-db & do-ignore-db & wild-do-table & wild-ignore-table
常見場景:將master上的A,B庫 拆分到 新的一組機器上。
特色:
1) slave 不復制 master 的 mysql,test 庫
2) slave 只複製 master 的 A,B 庫全部操做
replicate-ignore-db=mysql
replicate-ignore-db=test
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate_do_DB=A
replicate_do_DB=B
replicate-wild-do-table=A.%
replicate-wild-do-table=B.%
誤區:
1) 若是個人 default database 不是A或者B,那麼接下來的操做就不會被slave 執行,而後悲劇就產生了。
master> use C;insert into A.id values(1);
2)因此,以上cnf配置,只適合 default database 是 A,B 的狀況。
若是要完成這種需求,應該這樣配置[前提:開發沒有權限登錄到mysql,test庫]:
replicate-ignore-db=mysql replicate-ignore-db=test replicate-wild-ignore-table=mysql.% replicate-wild-ignore-table=test.% replicate-wild-do-table=A.% replicate-wild-do-table=B.%
實戰: wild-do-table & ignore-table & wild-ignore-table
需求: 將老服務器上的某個庫,遷移到新機器上
old_master[庫: A , B , mysql] ---->(同步) new_maser[A]
驗證單庫(A)複製的正確性: 規則=> slave 只複製A庫,不復制B庫
Replicate_Wild_Do_Table: A.% Replicate_Ignore_DB: mysql Replicate_Wild_Ignore_Table: mysql.% a)use A/B; insert A.a select B.b from B ; --err:同步報錯,slave沒有B庫的內容 b) use A/B; insert A.a select B.b from A,B where A.b=B.b; --err:同步報錯,slave沒有B庫的內容 c) use mysql; insert into A.a values('a'); --err: 同步不報錯,可是老master的binlog沒有在slave執行,由於Replicate_Ignore_DB: mysql,Replicate_Wild_Ignore_Table: mysql.% d) use 空庫; insert into A.a values('a'); --ok: 能夠同步複製下來 e) use B; insert into A.a values('a'); --ok: 能夠同步複製下來
產生情景:
需求:主從複製很是擅長解決物理損壞,可是沒辦法處理邏輯損壞,例如主庫有個誤刪除寫入的操做,正常狀況下從庫也會同步這個錯誤,怎麼能避免這個狀況?
作法:創建延時從庫,delay(延時)從節點同步數據。能夠處理邏輯損壞,但只能作備用庫。
原理:對SQL線程回放流程,進行延時設置。
建議:通常企業建議3-6小時,具體看公司運維人員對於故障的反應時間
查看延時時間
show slave status\G
# 延時時間,單位秒
SQL_Delay: 0
# 延時剩餘時間,單位秒
SQL_Remaining_Delay: NULL
查看中繼日誌
show relaylog events in 'db01-relay-bin.000002';
在線配置:
stop slave SQL_THREAD; change master to master_delay = 300; start slave sql_thread;
故障場景:一主一從,從庫延時5分鐘,主庫誤刪1個庫
故障模擬:主庫操做
create database relay charset utf8; use relay; create table t1 (id int); insert into t1 values(1); commit; drop database relay;
故障恢復操做:
5分鐘以內,偵測到誤刪除操做
從庫中止SQL線程:
stop slave SQL_THREAD;
從庫查找截取relaylog的起點和終點
起點:中止SQL線程時,relay最後應用的位置
mysql> show slave status\G ... ... Relay_Log_File: db02-relay-bin.000002 Relay_Log_Pos: 321 ... ...
終點:誤刪除以前的Position(GTID)
mysql> show relaylog events in 'db02-relay-bin.000002';
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
... ...
| m01-relay-bin.000002 | 988 | Anonymous_Gtid | 1 | 1020 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| db01-relay-bin.000002 | 1065 | Query | 1 | 1127 | drop database relay /* xid=81 */
|
從庫截取relaylog
mysqlbinlog --start-position=321 --stop-position=988 /data/3306/data/db02-relay-bin.000002 > /tmp/relay.sql
從庫確認截取文件
tail -10 /tmp/relay.sql
從庫恢復截取的日誌
source /tmp/relay.sql
從庫身份解除,替代主庫工做
stop slave; reset slave all;
業務改用從庫
5分鐘以內,偵測到誤刪除操做
從庫中止SQL線程:
stop slave SQL_THREAD;
關閉延遲從庫
CHANGE MASTER TO MASTER_DELAY = 0;
從庫查詢誤刪除以前的Position(GTID)
mysql> show slave status\G
... ...
Relay_Log_File: db02-relay-bin.000002
... ...
mysql> show relaylog events in 'db02-relay-bin.000002';
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
... ...
| m01-relay-bin.000002 | 988 | Anonymous_Gtid | 1 | 1020 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| db01-relay-bin.000002 | 1065 | Query | 1 | 1127 | drop database relay /* xid=81 */
|
從庫SQL線程自動回放,直到DROP操做以前。
binlog方式UNTIL
START SLAVE SQL_THREAD UNTIL RELAY_LOG_FILE = 'db01-relay-bin.000002', RELAY_LOG_POS = 988 ;
GTID方式UNTIL
START SLAVE UNTIL SQL_BEFORE_GTIDS = "1aa38bc6-1cbc-11eb-a6b8-000c29caebef:4";
從庫身份解除,替代主庫工做
stop slave; reset slave all;
業務改用從庫
從 MYSQL 5.5 開始,支持半同步複製(Semi synchronous Replication),必定程度上保證提交的事務已經傳給了至少一個備庫。解決主從數據不一致問題,提供通常一致性。可以使用多從庫提升ACK接收率。
以前版本的MySQL Replication都是異步(asynchronous)的,主庫在執行完一些事務後,是不會管備庫的進度的。若是備庫不幸落後,而更不幸的是主庫此時又出現Crash(例如宕機),這時備庫中的數據就是不完整的。若是主庫發生故障,此時咱們沒法使用備庫來繼續提供數據一致的服務了。
5.5 出現概念,可是不建議使用,性能太差 5.6 出現
group commit
組提交功能,來提高開啓半同步複製的性能 5.7 更加完善了,在group commit
基礎上出現了MGR
5.7 加強半同步複製的新特性:after commit
;after sync
;
主庫執行新的事務,commit
時阻塞
更新 show master status
信息,觸發一個信號給 binlog dump
binlog dump
通知從庫日誌更新了
從庫IO線程請求新的二進制日誌事件
主庫經過binlog dump
線程,傳送新的二進制日誌事件,給從庫IO線程
從庫IO線程接收到binlog
,當日志寫入到磁盤上的relaylog
文件時,給主庫ACK_receiver
線程響應
ACK_receiver
線程觸發一個事件,告訴主庫commit
能夠成功了
若是ACK_receiver
等待,達到了預設的超時時間尚未收到響應,半同步複製會切換爲原始的異步複製
配置主庫
在線配置:
# 查看是否有動態支持
show global variables like 'have_dynamic_loading';
# 安裝自帶插件
INSTALL PLUGIN rpl_semi_sync_master SONAME'semisync_master.so';
# 啓動插件
SET GLOBAL rpl_semi_sync_master_enabled = 1;
# 設置超時時間
SET GLOBAL rpl_semi_sync_master_timeout = 1000;
永久配置:
vim /etc/my.cnf [mysqld] rpl_semi_sync_master_enabled=1 rpl_semi_sync_master_timeout=1000
查看運行狀態
show status like 'Rpl_semi_sync_master_status';
配置從庫
在線配置:
# 安裝自帶插件
INSTALL PLUGIN rpl_semi_sync_master SONAME'semisync_master.so';
# 啓動插件
SET GLOBAL rpl_semi_sync_master_enabled = 1;
# 重啓io線程使其生效
STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
永久配置:
vim /etc/my.cnf [mysqld] rpl_semi_sync_master_enabled=1
查看運行狀態
show status like 'Rpl_semi_sync_slave_status';
rpl_semi_sync_master_enabled =ON rpl_semi_sync_master_timeout =1000 rpl_semi_sync_master_trace_level =32 rpl_semi_sync_master_wait_for_slave_count =1 rpl_semi_sync_master_wait_no_slave =ON rpl_semi_sync_master_wait_point =AFTER_SYNC rpl_semi_sync_slave_enabled =ON rpl_semi_sync_slave_trace_level =32 binlog_group_commit_sync_delay =1 binlog_group_commit_sync_no_delay_count =1000
GTID(Global Transaction ID)是對於一個已提交事務的惟一編號,而且是一個全局(主從複製)惟一的編號。
GTID =server_uuid : transaction_id
7E11FA47-31CA-19E1-9E56-C43AA21293967:29
注意:
mysqldump
備份開啓GTID
的數據庫,不能加--set-gtid-purged=OFF
選項。SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;
SET @@SESSION.SQL_LOG_BIN= 0;
總結:
gtid事務和 Position都增長了;
加了--set-gtid-purged=OFF時,在會記錄binlog日誌,若是不加,不記錄binlog日誌。
[mysqld] gtid-mode=on --啓用gtid類型,不然就是普通的複製架構 enforce-gtid-consistency=true --強制GTID的一致性 log-slave-updates=1 --slave更新是否記入日誌
配置主庫(db01)
安裝 mysql 8.0.20 二進制包
tar xf mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz ln -s /opt/mysql-8.0.20-linux-glibc2.12-x86_64 /usr/local/mysql yum remove mariadb-libs -y useradd -M -r mysql mkdir -p /data/3306/data && chown -R mysql. /data/ echo export PATH=\$PATH:/usr/local/mysql/bin/ >> /etc/profile && . /etc/profile
配置文件
cat > /etc/my.cnf <<EOF [mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/3306/data port=3306 socket=/tmp/mysql.sock server_id=51 log_bin=/data/3306/mysql-bin secure-file-priv=/tmp binlog_format=row gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [client] socket=/tmp/mysql.sock [mysql] prompt=db01 [\\d]> EOF
初始化數據,加入systemctl服務管理,啓動並開機自啓
mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/3306/data cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld systemctl enable mysqld systemctl start mysqld
建立複製專用用戶並受權
create user repl@'10.0.0.%' identified with mysql_native_password by '123'; grant replication slave on *.* to repl@'10.0.0.%';
查看主狀態
show master status;
配置從庫(db02 db03)
安裝 mysql 8.0.20 二進制包
配置文件
cat > /etc/my.cnf <<EOF [mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/3306/data port=3306 socket=/tmp/mysql.sock server_id=52 log_bin=/data/3306/mysql-bin secure-file-priv=/tmp binlog_format=row gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [client] socket=/tmp/mysql.sock [mysql] prompt=db02 [\\d]> EOF cat > /etc/my.cnf <<EOF [mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/3306/data port=3306 socket=/tmp/mysql.sock server_id=53 log_bin=/data/3306/mysql-bin secure-file-priv=/tmp binlog_format=row gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [client] socket=/tmp/mysql.sock [mysql] prompt=db03 [\\d]> EOF
初始化數據,加入systemctl服務管理,啓動並開機自啓
配置主庫鏈接信息(help change master to
)
CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_USER='repl', MASTER_PASSWORD='123', MASTER_AUTO_POSITION=1;
啓動複製線程
start slave;
查看從狀態
show slave status \G
查看監控信息:
Last_SQL_Error: Error 'Can't create database 'oldboy'; database exists' on query. Default database: 'oldboy'. Query: 'create database oldboy' Retrieved_Gtid_Set: 71bfa52e-4aae-11e9-ab8c-000c293b577e:1-3 Executed_Gtid_Set: 71bfa52e-4aae-11e9-ab8c-000c293b577e:1-2,
跳過報錯事務(GTID),注入空事務:
stop slave; set gtid_next='71bfa52e-4aae-11e9-ab8c-000c293b577e:3'; begin;commit; set gtid_next='AUTOMATIC';
CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_USER='repl', MASTER_PASSWORD='123', MASTER_PORT=3306, MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=444, MASTER_CONNECT_RETRY=10; CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_USER='repl', MASTER_PASSWORD='123', MASTER_AUTO_POSITION=1;
在主從複製環境中,主庫發生過的事務,在全局都是由惟一GTID記錄的,更方便Failover
額外功能參數(3個)
change master to ...
時,不須要binlog文件名和position號,啓用自動便可MASTER_AUTO_POSITION=1
;
在複製過程當中,從庫再也不依賴master.info
文件,而是直接讀取最後一個relaylog的GTID號
mysqldump備份時,默認包含事務操做的GTID,以SET @@GLOBAL.GTID_PURGED='8c49d7ec-7e78-11e8-9638-000c29ca725d:1';
形式告訴從庫,個人備份中已經有以上事務,你就不用運行了,直接從下一個GTID開始請求binlog就行。
MySQL 5.7 以前只能支持一主一從,一主多從或者多主多從的複製。若是想實現多主一從,只能使用mariadb,可是mariadb又與官方的mysql版本不兼容。
MySQL 5.7 開始支持多主一從也就是多源複製(multi-source)。簡單的說,多源複製就是將多個主庫同步到一個從庫,從而增長從的利用率,節省了機器。
應用場景:
數據分析部門會須要各個業務部門的部分數據作數據分析,這個時候就可使用到多源複製把各個主數據庫的數據複製到統一的數據庫中。報表系統
在從服務器進行數據的彙總,若是咱們的主服務器進行了分庫分表的操做,爲了實現後期的一些數據的統計功能,每每要把數據彙總在一塊兒在進行統計。OLAP(在線分析處理)
在從服務器對全部主服務器的數據進行備份。
[mysqld] slow_query_log=ON -- 啓用慢查詢 slow_query_log_file=/data/3306/data/db01-slow.log -- 慢查詢日誌保存路徑 long_query_time=0.1 -- 慢查詢記錄執行超過0.1秒的查詢 log_queries_not_using_indexes -- 記錄預期將檢索全部行的查詢 master_info_repository=TABLE -- 存儲 master_info 到表中,更安全 relay_log_info_repository=TABLE -- 存儲 relay_log_info 到表中,更安全 [mysql] prompt=db01 [\\d]> -- mysql命令行提示符
修改配置文件
cat > /etc/my.cnf <<EOF [mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/3306/data port=3306 socket=/tmp/mysql.sock server_id=1 log_bin=/data/binlog/mysql-bin secure-file-priv=/tmp binlog_format=row gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 innodb_flush_method=O_DIRECT slow_query_log=ON slow_query_log_file=/data/3306/data/db01-slow.log long_query_time=0.1 log_queries_not_using_indexes master_info_repository=TABLE relay_log_info_repository=TABLE [client] socket=/tmp/mysql.sock [mysql] prompt=db01 [\\d]> EOF cat > /etc/my.cnf <<EOF [mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/3306/data port=3306 socket=/tmp/mysql.sock server_id=2 log_bin=/data/binlog/mysql-bin secure-file-priv=/tmp binlog_format=row gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 innodb_flush_method=O_DIRECT slow_query_log=ON slow_query_log_file=/data/3306/data/db01-slow.log long_query_time=0.1 log_queries_not_using_indexes master_info_repository=TABLE relay_log_info_repository=TABLE [client] socket=/tmp/mysql.sock [mysql] prompt=db02 [\\d]> EOF cat > /etc/my.cnf <<EOF [mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/3306/data port=3306 socket=/tmp/mysql.sock server_id=3 log_bin=/data/binlog/mysql-bin secure-file-priv=/tmp binlog_format=row gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 innodb_flush_method=O_DIRECT slow_query_log=ON slow_query_log_file=/data/3306/data/db01-slow.log long_query_time=0.1 log_queries_not_using_indexes master_info_repository=TABLE relay_log_info_repository=TABLE [client] socket=/tmp/mysql.sock [mysql] prompt=db03 [\\d]> EOF
重啓mysql服務
systemctl restart mysql
清除原來主從關係(db02 db03)
stop slave; reset slave all;
多源複製從庫配置主庫信息(db03)並啓動
CHANGE MASTER TO MASTER_HOST='10.0.0.51',MASTER_USER='repl',
MASTER_PASSWORD='1', MASTER_AUTO_POSITION=1 FOR CHANNEL 'Master_1'; CHANGE MASTER TO MASTER_HOST='10.0.0.52',MASTER_USER='repl',
MASTER_PASSWORD='1', MASTER_AUTO_POSITION=1 FOR CHANNEL 'Master_2'; start slave for CHANNEL 'Master_1'; start slave for CHANNEL 'Master_2';
多源複製從庫監控
-- 查看單一信道的複製的詳細狀態
SHOW SLAVE STATUS FOR CHANNEL 'Master_1'\G SHOW SLAVE STATUS FOR CHANNEL 'Master_2'\G
-- 查看視圖中複製配置,狀態
use performance_schema; show tables like '%repl%'; select * from performance_schema.replication_connection_configuration\G SELECT * FROM performance_schema.replication_connection_status WHERE CHANNEL_NAME='master_1'\G
-- 查看全部複製信道的複製狀態概況
select * from performance_schema.replication_applier_status_by_worker;
多源複製配置過濾
CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('db1.%') FOR CHANNEL "master_1"; CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('db2.%') FOR CHANNEL "master_2";
檢查測試
-- 在主庫(10.0.0.51)實例建立一些數據。
create database master1; use master1; CREATE TABLE `test1` (`id` int(11) DEFAULT NULL,`count` int(11) DEFAULT NULL); insert into test1 values(1,1);
-- 在主庫(10.0.0.52)實例建立一些數據。
create database master2;
use master2;
CREATE TABLE `test2` (`id` int(11) DEFAULT NULL,`count` int(11) DEFAULT NULL);
insert into test2 values(1,1);
-- 在從庫(10.0.0.53)實例檢查數據是否成功複製。
select * from master1.test1; select * from master2.test2;
主主複製
主主複製:互爲主從 (1)容易產生的問題:數據不一致;所以慎用 (2)考慮要點:自動增加id
配置一個節點使用奇數id
auto_increment_offset=1 開始點 auto_increment_increment=2 增加幅度
另外一個節點使用偶數id
auto_increment_offset=2 auto_increment_increment=2
(1) 各節點使用一個唯一server_id
(2) 都啓動binary log和relay log
(3) 建立擁有複製權限的用戶帳號
(4) 定義自動增加id字段的數值範圍各爲奇偶
(5) 均把對方指定爲主節點,並啓動複製線程
vim /etc/my.cnf [mysqld] server-id=1 binlog_format=ROW plugin-load-add=mysql_clone.so clone=FORCE_PLUS_PERMANENT auto_increment_offset=1 auto_increment_increment=2
重啓db01機器mysql服務器
systemctl reatart mysqld mysql> select @@log_bin; mysql> select @@log_bin_basename; mysql> create user repl@'10.0.0.%' identified with mysql_native_password by '123'; mysql> grant replication slave on *.* to repl@'10.0.0.%'; 建立遠程clone用戶 # 捐贈者(source)受權 mysql> reset master; create user test_s@'%' identified by '123'; grant backup_admin on *.* to test_s@'%'; mysql > show databases; mysql > CHANGE MASTER TO mysql > start slave; 開啓slave mysql > show slave status\G mysql> create table t1(id int auto_increment primary key,name char(10)); 建立表t1 Query OK, 0 rows affected (0.03 sec) mysql> insert t1(name)value('a'); 插入a信息 Query OK, 1 row affected (0.01 sec) mysql> insert t1(name)value('b'); 插入b信息 Query OK, 1 row affected (0.00 sec) mysql> select * from t1; +----+------+ | id | name | +----+------+ | 1 | a | | 3 | b | +----+------+
vim /etc/my.cnf [mysqld] server-id=2 binlog_format=ROW auto_increment_offset=2 auto_increment_increment=2 plugin-load-add=mysql_clone.so clone=FORCE_PLUS_PERMANENT
重啓
systemctl restart mysqld SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'clone';
# 接受者(target)受權
mysql> reset master;
create user test_t@'%' identified by '123';
grant clone_admin on *.* to test_t@'%';
遠程clone(目標端)
# 開始克隆
SET GLOBAL clone_valid_donor_list='10.0.0.51:3306';
mysql -utest_t -p123 -h10.0.0.52 -P3306
CLONE INSTANCE FROM test_s@'10.0.0.51':3306 IDENTIFIED BY '123';
==========================================================
f. 告訴從庫鏈接信息,從什麼位置點開始自動複製 change master to
mysql> select * from performance_schema.clone_status\G mysql> CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_USER='repl', MASTER_PASSWORD='123', MASTER_PORT=3306, MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=156, MASTER_CONNECT_RETRY=10;
g. 啓動專用複製線程 start slave;
mysql> start slave ;
mysql> show slave status \G;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
mysql > show databases;
查看二進制日誌狀況
mysql > show master logs;
插入表
mysql > insert t1(name)value('a'); 在B主機上插入a信息 Query OK, 1 row affected (0.01 sec) mysql > insert t1(name)value('b'); 在B主機上插入b信息 Query OK, 1 row affected (0.00 sec) mysql > select * from t1; 查看此時未出現衝突狀況,可是ID順序會比較亂 +----+------+ | id | name | +----+------+ | 1 | a | | 3 | b | | 4 | a | | 6 | b | +----+------+
主-中間主(change master to)-從1(change master to中間主)-從2(change master to中間主)-從3(change master to中間主)
一主多從 主 ----從1(-change master to主)-從2-change master to主