1、主從復制準備
1.1 前提
- 準備2個以上地mysql實例,一主一從。
- 每臺實例server_id不同
- 主庫方面創(chuàng)建專用地復制用戶
- 主庫必須開啟二進制日志
- 從庫需要初始化數(shù)據(jù),保證和主庫數(shù)據(jù)在一個時間點上一致
1.2 準備
3307配置文件添加binlog配置
vim /data/3307/my.cnf
log_bin=/data/3307/data/mysql-bin
binlog_format=row啟動多實例
/application/mysql/bin/mysqld_safe --defaults-file=/data/3307/my.cnf &
/application/mysql/bin/mysqld_safe --defaults-file=/data/3308/my.cnf &
/application/mysql/bin/mysqld_safe --defaults-file=/data/3309/my.cnf &驗證
netstat -lnp|grep 330主庫創(chuàng)建復制用戶
mysql -uroot -S /data/3307/mysql.sock
grant replication slave on *.* to repl@'10.0.0.%' identified by '123';全備主庫數(shù)據(jù),恢復到從庫
mysqldump -S /data/3307/mysql.sock -A -R --triggers --master-data=2 --single-transaction >/tmp/full.sql查看binlog文件和位置點
vim /tmp/full.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=325;全備導入從庫
mysql -uroot -S /data/3308/mysql.sock
set sql_log_bin=0;
source /tmp/full.sql開啟主從復制
mysql -uroot -S /data/3308/mysql.sock
CHANGE MASTER TO
MASTER_HOST='10.0.0.51', ---->主庫IP
MASTER_USER='repl', ---->主庫復制用戶
MASTER_PASSWORD='123', ---->主庫復制用戶密碼
MASTER_PORT=3307, ----->主庫端口
MASTER_LOG_FILE='master2-bin.000001', ----->需要復制的二進制日志名
MASTER_LOG_POS=325, ---->需要復制的二進制日志復制起點
MASTER_CONNECT_RETRY=10; ---->重連重試次數(shù)
啟動復制線程
start slave;
查看主從狀態(tài)
show slave status\G
slave_IO_Running:yes
slave_SQL_Running:yes
2、主從復制介紹
2.1 什么是主從復制?
基于主庫二進制日志實時恢復到從庫
2.2 主從復制存在的原因
- 輔助備份:解決物理損壞
- 演變高可用架構(gòu):在主庫發(fā)生故障時,自動進行故障轉(zhuǎn)移,對應用透明
2.3 主從復制原理
- 主從復制前提
- 多臺節(jié)點
- server_id要不同
- 主庫開啟binlog
- 主庫提供專門的復制用戶
- 主庫備份導入從庫,跟上主庫的數(shù)據(jù)位置
- 通知從庫:復制用戶、密碼、IP、port、復制文件和起點
- 開啟復制
- 文件
- Master:
binlog:記錄主庫的數(shù)據(jù)變化 - Slave:
relaylog:中繼日志,存儲從主庫請求過來的二進制日志的存儲位置
master.info:存儲用戶,密碼,IP,port,記錄上次請求過的binlog位置
relay-log.info:記錄了上次SQL線程執(zhí)行過的relaylog的位置點
- 線程:
- Master:
dump線程:主庫發(fā)送二進制日志給從庫的線程 - Slave:
IO線程:請求binlog,并接收binlog的線程
SQL線程:執(zhí)行relaylog日志的線程
主從復制原理

- 從庫IO線程,查看master.info信息,獲取IP,port,user,password,file,position位置點
- 通過IP,port,user,password,連接到主庫
- 拿著 file(mysql-bin.000003),pos(120),請求主庫
- 主庫判斷如果有新的binlog(mysql-bin.000003,800),通過Dump線程從3號文件的120開始發(fā)送二進制日志事件
- 從庫IO線程,接收binlog日志
- 接收到的binlog日志存到TCP/IP緩存
- IO線程回復一個ACK確認給dump線程,主庫收到后,主庫此次復制工作就完成了
- IO線程通知更新master.info文件,file,position被更新為最新請求的值
- 同時TCP/IP的緩存數(shù)據(jù),寫入relay-log中
- SQL線程,讀取relay-log.info,獲取到上次已經(jīng)執(zhí)行過的位置信息
- SQL執(zhí)行最新的relay-log日志內(nèi)容,數(shù)據(jù)重做
- 再次更新relay-log.info
- 已經(jīng)復制過的relay-log,會被自動清理
簡單來說就是三個步驟:
1、master將改變記錄到二進制日志(binary log),這些記錄過程叫做二進制日志事件(binary log events);
2、slave將master 的binary log events 拷貝到它的中繼日志( relay log);
3、slave重做中繼日志中的事件,將改變應用到自己的數(shù)據(jù)庫中。mysql復制是異步的且串行化的
2.4 主從復制監(jiān)控
主庫:
show master status; //主庫和從庫的文件和位置信息應該是一致
show processlist;從庫:
show slave status\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 10.0.0.51
Master_User: repl
Master_Port: 3307
Connect_Retry: 10
Master_Log_File: master-bin.000004 //主庫的binlog日志文件
Read_Master_Log_Pos: 918 //binlog日志文件位置點
Relay_Log_File: db01-relay-bin.000001 //relay log 文件
Relay_Log_Pos: 4 //relay log 位置點
Relay_Master_Log_File: master-bin.000004 //relaylog 日志文件對應的主庫的binlog文件名
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
啟動關(guān)閉線程
stop slave;
start slave;
stop slave io_thread; //單獨關(guān)閉IO線程
stop slave sql_thread; //單獨關(guān)閉sql線程監(jiān)控線程具體報錯信息
Last_IO_Errno: 1236
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'
Last_SQL_Errno: 0
Last_SQL_Error:
2.5 主從復制故障
- IO線程故障
- 連接master故障
user,password,IP,port,網(wǎng)絡不通,防火墻,master沒啟動,master連接數(shù)到達上限,反向解析(skip-name-resolve)
# 用戶密碼錯誤,嘗試登錄主庫
mysql -urepl -p123 -h 10.0.0.51 -P3307
# 解決方法:
show slave status\G //查看故障點的binlog位置
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 918
# 停止復制
stop slave;
reset slave all; //清除之前的復制
# 修改信息重新復制
CHANGE MASTER TO
MASTER_HOST='10.0.0.51',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=3307,
MASTER_LOG_FILE='mysql-bin.000004',
MASTER_LOG_POS=918, //從故障時間點的位置開始復制主庫
MASTER_CONNECT_RETRY=10;
start slave;
show slave status\G
- 接收binlog故障
binlog日志文件找不到、損壞、與主庫斷節(jié)
Last_IO_Errno: 1236
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'
Last_SQL_Errno: 0
Last_SQL_Error:
reset master //二進制日志從頭開始。禁用
解決方法:
# 從庫停庫
stop slave;
reset slave all;
# 使用備份恢復,重新初始化數(shù)據(jù);如果主庫數(shù)據(jù)沒有變化,則不用
set sql_log_bin=0;
source /tmp/full.sql
# 重新復制
CHANGE MASTER TO
MASTER_HOST='10.0.0.51',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=3307,
MASTER_LOG_FILE='mysql-bin.000001', //從頭開始復制
MASTER_LOG_POS=120,
MASTER_CONNECT_RETRY=10;
start slave;
-
SQL線程故障
(1)讀寫relay log.info
(2)relay log 損壞,斷節(jié),找不到
(3)接收到的SQL無法執(zhí)行;根本原因是從庫有寫入操作,從庫所有的數(shù)據(jù)都應該來自于主庫。
解決方法:
1、寫入操作撤回
2、跳過錯誤的方法是有風險的,最安全的方法重新構(gòu)建主從。
3、徹底解決方法是將從庫設置為只讀庫
從庫設置只讀權(quán)限
# 會話級別設置:
set global read_only=1;
# 永久設置:
vim /etc/my.cnf
[mysqld]
read_only=1
# 以上兩條只對普通用戶生效
# 設置管理員只讀權(quán)限
vim /etc/my.cnf
[mysqld]
innodb_read_only=1
會話級別無法設置,只能重啟生效
- 主從復制延時過高
定義:主庫做了一個操作,從庫很久都沒有追上
- 原因1 主庫寫binlog不及時
解決方法:控制binlog從內(nèi)存寫入到磁盤的控制參數(shù):
每次事務提交會立即刷新binlog到磁盤(雙一標準的其中一個)
sync_binlog=1每次事務提交不立即寫入磁盤,靠操作系統(tǒng)判斷什么時候?qū)懭?br> sync_binlog=0
原因2 dump線程壓力大
原因3 IO線程阻塞
大事務------->拆成多個小事務
事務量大------->group commit,5.6以后的參數(shù),可以同時提交原因4 SQL線程慢
- 默認只有一個SQL線程,從庫中的事務都是一個一個來執(zhí)行的
- 如果主庫的并發(fā)事務數(shù)很多,大事務,都會造成從庫延時
5.6 多線程復制(多SQL線程),有局限性,針對不同庫的事務進行并發(fā);
大事務只能在主庫拆成小事務。
- 查看從庫延時時間
show slave status\G
Seconds_Behind_Master:8888