mysql 主從複製

1、mysql複製原理

mysql 主從複製

  • 從庫的I/O thread 線程會讀取master info 文件 獲取主庫的 user,password port信息而後還會獲取上次獲取主庫二進制日誌的位置 如3640 就是00003這個文件640這個位置,主庫收到從庫的請求後,會驗證用戶名密碼等的合法性,而後問主庫你有沒有比上次00003文件640這個位置更加新的二進制日誌,而後主庫就會查看本身的binglog日誌,若是發現比640這個新,如已經到達31080這個位置了,主庫就會把00003號文件的640這個位置到1080這個位置的binglog日誌截斷,經過dump(i/o)線程返回給從庫的I/O thread線程,到從庫以後,它會先存到tcp/ip緩存當中(tcp/ip cached),而後從庫會當即發送一個ack給主庫,主庫收到ack後就認爲這個過程已經完成,就能夠去幹別的事情了,此時從庫會更新mast info的信息,把binglog的位置信息更新到1080,下次就從1080開始往下找,而後再把tcp/ip緩存的日誌寫入到relaylog當中,最後sql thread線程會讀取relay-log.info,獲取到上次執行binglog日誌的位置信息,好比發現上次以及執行到640這個位置了,sql就會讀取relaylog從640的位置開始執行二進制日誌,當執行完後,最後更新relay-log.info文件,記錄最後執行的位置,最後,relaylog會自動把已經執行過的二進制日誌清理掉這樣一次複製就完成了
  • 複製中的線程及文件
    2.一、主庫
    Dump(IO) thread:在複製過程當中,主庫發送二進制日誌的線程
    2.二、從庫
    IO thread:向主庫請求二進制日誌,而且接受二進制日誌的線程
    SQL thread:執行請求過來的二進制的線程
    2.三、主庫
    binlog文件:主庫的二進制日誌
    2.四、從庫
    relaylog:中繼日誌,存儲請求過來的二進制日誌
    master.info:
    一、從庫鏈接主庫的重要參數(user,passwd,ip,port)
    二、上次獲取過的主庫二進制日誌的位置
    relay-log.info
    存儲從庫SQL線程已經執行過的relaylog日誌位置mysql

    2、mysql 主從搭建

  • 主從複製前提sql

    一、兩臺以上MySQL實例(能夠是多臺物理機,也但是mysql實例)
    二、主庫要開啓二進制日誌
    三、主庫要提供複製相關的用戶須要用到 replication slave一個比較特殊的權限
    四、從庫須要將和主庫相差的數據進行追加,通常狀況下認爲備份數據庫,恢復到從庫上
    五、從庫應該從恢復後的時間點開始自動從主庫獲取二進制日誌開始自動同步主庫數據,咱們須要告訴從庫,從哪兒開始複製二進制日誌進行學習數據庫

  • 主從複製搭建實戰
    一、環境準備
    兩個MySQL實例
    3307:master
    3308:slave
    二、開啓主庫binlog,從庫開啓relay-log(默認在數據目錄下生成)
    vim /data/3307/my.cnf
    log-bin=/data/3307/mysql-bin
    binlog_format=row
    三、server-id不一樣
    [root@db02 data]# cat /data/3307/my.cnf |grep server-id
    server-id=3307
    [root@db02 data]# cat /data/3308/my.cnf |grep server-id
    server-id=3308
    四、關閉數據庫自動域名解析(沒個節點實例都加)
    skip-name-resolve
    五、啓動多實例
    mysqld_safe --defaults-file=/data/3307/my.cnf &
    mysqld_safe --defaults-file=/data/3308/my.cnf &
    六、主庫建立複製帳戶鏈接到主庫
    mysql -S /data/3307/mysql.sock
    grant replication slave on . to repl@'10.0.0.%' identified by '123';
    七、從庫數據追加

(1)不須要追加的狀況
主和從同時搭建的新環境,就不須要備份主庫數據,恢復到從庫了,直接從第一個binlog(mysql-bin.000001)開頭位置(120)vim

(2)若是主庫已經工做了很長時間了,咱們通常須要備份主庫數據,恢復到從庫,而後從庫從備份的時間點起自動進行復制緩存

mysqldump -S /data/3307/mysql.sock -A -R --triggers --master-data=2 --single-transaction >/tmp/full.sql
sed -n '22p' /tmp/full.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=325
恢復到從庫:
mysql -S /data/3308/mysql.sock
mysql> set sql_log_bin=0;
mysql> source /tmp/full.sql
八、從庫開啓主庫
mysql -S /data/3308/mysql.sock安全

help change master to網絡

CHANGE MASTER TO
MASTER_HOST='10.0.0.52',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=3307,
MASTER_LOG_FILE='mysql-bin.000002',
MASTER_LOG_POS=325;
開啓主從(開啓IO/SOL線程)
start slave
九、查看主從狀態
show slave status\G架構

Slave_IO_Running: Yes
Slave_SQL_Running: Yes
十、主從重要狀態信息介紹app

show slave status\G
Slave_IO_Running: Yes(io線程狀態)
Slave_SQL_Running: Yes(sql線程狀態)
Last_IO_Errno: 0(io線程異常狀態碼)
Last_IO_Error: (io線程異常詳細信息)
Last_SQL_Errno: 0(sql線程狀態碼)
Last_SQL_Error: (sql線程異常詳細信息)運維

三 、 主從複製常見異常解決思路

  • IO線程故障
    一、主庫鏈接不上
    檢查user,password,port,IP,網絡,防禦牆
    stop slave;
    reset slave all;(清空配置)
    chagen master to
    start slave

二、主庫二進制文件丟失或損壞
解決方案;
stop slave;
reset slave all;
重新備份恢復
change master to
start slave;

  • SQL線程故障
    執行relaylog日誌新新的事件
    一、刪除,修改對象的操做時,沒有這個對象
    二、建立對象時,對象已存在
    三、主鍵衝突
    從庫作寫入操做,會致使以上問題出現

處理方法跳過這個錯誤
stop slave;
set global sql_slave_skip_counter=1;
start slave;
/etc/my.cnf
slave-skip-errors=1032,1062,1007
可是,以上操做有的時候時候是有風險的,最安全的方法是重新構建新的主從
如何預防?
修改從庫爲只讀庫
set global read_only=1;
vim /etc/my.cnf
read_only=1(這個參數只能控制普通用戶)

  • 主從延時過長
    show slave status \G
    Seconds_Behind_Master:0

默認的主從複製是異步的過程

主庫緣由
一、主庫作修改操做以後,纔會記錄二進制日誌
二、主庫的壓力特別大(大事務,多事物)
三、從庫數量多,致使domp線程繁忙
從庫緣由:
一、relay-log寫入慢
二、sql線程慢(主從硬件差別較大)
解決思路
主庫
一、sync_binlog=1(1表示只要主庫作了一次commit,二進制日誌就會馬上刷新到磁盤,若是等於0要根據系統binlog決定)
二、大事物拆分紅小事物,多事物進行分離
三、使用多級主從,分庫分表架構
四、將binlog放在ssd或者flash上,高性能存儲
從庫
一、將relay放到ssd或者flash上
二、儘可能選擇和主庫同樣的硬件配置

4、主從複製其餘特性

  • 半同步複製
    一、出現緣由
    保證數據一致性問題,安全考慮
    默認狀況下MySQL主從備份是經過異步的方式進行備份,當從庫向主庫請求二進制日誌,從庫會把請求過來的二進制日誌存到tcp/ip緩存當中,返回一個ack告訴主庫接收到了二進制日誌,試想一下當這個時候從庫忽然斷電了,存到tcp/ip緩存當中的二進制日誌就會丟失,而主庫還也覺得從庫正常接收到了二進制日誌,從庫的數據就會丟失,半同步的實現方法就是當從庫接收到二進制日誌後必需要存到relaylog落地到磁盤當中從庫纔會發送ack給主庫,這樣就保證了數據的一致性
    半同步複製是在5.5出現的概念,但5.5的半同步複製性能太差不建議使用,在5.6之後出現group commit 組提交功能,來提高開啓版同步複製的性能,5.7 加強半同步複製的新特性:after sync;
  • 具體實現

加載插件

主:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

從:
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
查看是否加載成功:
show plugins;

啓動:
主:
SET GLOBAL rpl_semi_sync_master_enabled = 1;

從:
SET GLOBAL rpl_semi_sync_slave_enabled = 1;

重啓從庫上的IO線程
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;

查看是否在運行
主:
show status like 'Rpl_semi_sync_master_status';
從:
show status like 'Rpl_semi_sync_slave_status';

補充:
rpl_semi_sync_master_timeout | 10000
默認狀況先,到達10秒鐘尚未ack,主從關係自動切換爲普通複製
若是是1主多從的半同步複製,只要有一臺落地relaylog,返回ack,此次半同步就完成了。

  • 從庫延時
    防止數據庫的邏輯損壞,假設在主庫不當心誤刪除了一個表,這個事件會一樣記錄到二進制日誌當中發送到從庫,這時候從庫不會當即執行這個 操做,好比配置了延時3小時,從庫會在3小時後才執行刪除表的操做,這樣就給咱們運維人員一些緩衝的時間,延時從庫是對sql線程的延時
    會專門找一個節點,配置成延時節點,儘量防止邏輯損壞,通常狀況下這個節點會被用備份

  • 配置實現
    SQL_thread的延時

mysql>stop slave;

mysql>CHANGE MASTER TO MASTER_DELAY = 60;

mysql>start slave;

mysql> show slave status \G
SQL_Delay: 300

取消延時:
mysql> stop slave;
mysql> CHANGE MASTER TO MASTER_DELAY = 0;
mysql> start slave;

  • 複製過濾
    出現緣由,有得時候咱們不想複製主庫的全部數據,只想複製一個庫或者一個庫某些表
    主庫方面控制(不建議使用):
    白名單:只記錄白名單中列出的庫的二進制日誌
    binlog-do-db
    黑名單:不記錄黑名單列出的庫的二進制日誌
    binlog-ignore-db

從庫方面控制:
白名單:只執行白名單中列出的庫或者表的中繼日誌

--replicate-do-db=test (哪一個庫)
--replicate-do-table=test.t1 (哪一個庫的哪一個表)
--replicate-wild-do-table=test.x* (模糊的匹配)

黑名單:不執行黑名單中列出的庫或者表的中繼日誌
--replicate-ignore-db
--replicate-ignore-table
--replicate-wild-ignore-table

只複製world數據庫的數據
在從庫配置
vi /etc/my.cnf
replicate-do-db=world
重啓從庫

查詢:show slave status \G
replicate-do-db = world

  • 主從複製新模式-GTID複製
  • GTID是從5.6以後新的複製特性,之前的複製模式是當主庫發生了任何方式的變化,會已事件的形式記錄到binlog日誌當中,每一個事件生成一個position號,而後從庫去獲取這些二進制事件,而GTID是把每一個完整的事物單獨的生成一個全局惟一的編號,這樣就簡化了主從複製的配置,實現過程相對也簡單寫
    它的官方定義以下:
    GTID = source_id :transaction_id
    7E11FA47-31CA-19E1-9E56-C43AA21293967:29
    前半段爲UUID,後半段爲事物的編號,存放在auto.cnf下

  • 配置實現
    一、重要參數
    gtid-mode=on (是否開啓GTID)
    enforce-gtid-consistency=true (強制GTID的一致性)
    log-slave-updates=1 (slave更新是否寫入日誌)
    二、規劃
    主庫: 10.0.0.51/24
    從庫1: 10.0.0.52/24
    從庫2:10.0.0.53/24
    三、寫入配置文件
    主庫:
    加入如下配置信息

db01:10.0.0.51/24

vim /etc/my.cnf
[mysqld]
basedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log-error=/var/log/mysql.log
log_bin=/data/binlog/mysql-bin
binlog_format=row
skip-name-resolve
server-id=51
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[client]
socket=/tmp/mysql.sock

slave1:
db02:10.0.0.52/24

vim /etc/my.cnf
[mysqld]
basedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log-error=/var/log/mysql.log
log_bin=/data/binlog/mysql-bin
binlog_format=row
skip-name-resolve
server-id=52
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[client]
socket=/tmp/mysql.sock

slave2:
db02:10.0.0.53/24

vim /etc/my.cnf
[mysqld]
basedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log-error=/var/log/mysql.log
log_bin=/data/binlog/mysql-bin
binlog_format=row
skip-name-resolve
server-id=53
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[client]
socket=/tmp/mysql.sock

三臺節點分別初始化數據:

/application/mysql/scripts/mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data/

分別啓動三個節點mysql:

/etc/init.d/mysqld start

測試啓動狀況:
mysql -e "show variables like 'server_id'"

master:51
slave:52,53

51:
grant replication slave on . to repl@'10.0.0.%' identified by '123';

52\53:

change master to master_host='10.0.0.51',master_user='repl',master_password='123' ,MASTER_AUTO_POSITION=1;

start slave;

相關文章
相關標籤/搜索