一,主從的工作原理

master-slave
- master將改變記錄到二進制日志(binary log)中(這些記錄叫做二進制日志事件,binary log events), Slave根據本機的master.info文件中記錄的Master的日志文件名程和具體位置,通過IO進程連接上Master并請求從指定日志文件的指定位置(或者從最開始的日志)之后的日志內容;
- Master接收到來自Slave的IO進程的請求后,通過負責復制的IO進程根據請求信息讀取制定日志指定位置之后的日志信息,返回給Slave 的IO進程。返回信息中除了日志所包含的信息之外,還包括本次返回的信息已經到Master端的bin-log文件的名稱以及bin-log的位置;
- slave將master的binary log events拷貝到它的中繼日志(relay log);
- slave中的sql進程發現relay-log日志有改動后,根據relay.info中的relay位置,從relay-log的該位置開始重做中繼日志中的事件,將sql語句在本地數據庫執行。
[root@service mysql]# cat relay-log.info
./service-relay-bin.000002
3007731 ------------->代表relay-log文件執行的位置
mysql-bin.000008----->代表遠程master端binlog
338489392----------->執行到遠程master端binlog的具體位置
[root@service mysql]# cat master.info
18
mysql-bin.000008-->代表遠程master端binlog
338493827--------->執行到遠程master端binlog的具體位置
192.168.15.15----->遠程master端ip
username---------->遠程master端mysql的replication用戶名
userpassword----->遠程master端mysql的replication密碼
3306------------->遠程master端mysql端口
二,使用中遇到的問題
- 公司采用 A:主-> B:從(blackhole)->C:從 架構;
- 12月1日運維重啟了一下C機,過了一周后12月8號發現,A機的數據已經一周沒有同步到C機了,去C機器一看:
slave status\G
無任何信息
- 于是想到在C機主動連接B,先登錄B機:
mysql> show master status;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| mysql-bin.000008 | 338242604 | | |
+-------------------+----------+--------------+------------------+
- 然后登錄C
CHANGE MASTER TO MASTER_HOST='B',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='p4ssword',
-> MASTER_LOG_FILE='mysql-bin.000008',
-> MASTER_LOG_POS=338242604;
START SLAVE;
- 原本以為問題解決了,可是又一想從12.1到12.8這7天的數據并沒有同步到C機,但是此時已經過去幾分鐘了,趕快執行
STOP SLAVE
- 后來仔細回憶主從原理,在C機的master.info文件中會保存最后一次請求B的binlog文件和位置,重啟C后,會在對應目錄自動生成master.info_bak文件,于是查看C機的master.info_bak
[root@service mysql]# cat master.info_bak
18
mysql-bin.000008
335481914
192.168.15.15
repl
p4ssword
3306
可以看到12.1最后連接B的位置是335481914
,而我們剛剛start slave的點是 338242604
, 兩個點有差異,本以為在 start slave 到stop slave 之間在A機會有用戶操作產生很多數據, 如果此時在C上從335481914
開始請求擔心會和剛剛同步的數據有沖突;
- 于是想到查看
mysqlbinlog service-relay-bin.000002 > /tmp/relay.sql
cat /tmp/relay.sql
151202 12:02:40 server id 1 end_log_pos 335482146 Query thread_id=281429 exec_time=4294964863 error_code=0
use ljyun_754_merchant/*!*/;
SET TIMESTAMP=1449028960/*!*/;
INSERT INTO role (role_name, role_leader) VALUES (店長, 0)
可以看到在servicw-relay-bin.000002 中會記錄在C上start slave 和stop slave 之間的所有C機數據庫的操作, 查看對應end_log_pos 335482146
到B機的master的位置,根據該文件位置及具體的sql的分析,與master.info文件的對比判斷從start 到 stop之間C機的所有數據庫操作,然后確定只有一條數據產生,原本根據位置的加減判斷有200條數據產生,最后分析binglog中的end_log_pos 335482146 并不是以1為單位累加的,所以不要以binlog中的位置差判斷數據記錄的數量
;
- 最后可以放心的從12.1那天的斷點開始從C上發起請求,登錄C:
mysql> CHANGE MASTER TO MASTER_HOST='B',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='p4ssword',
-> MASTER_LOG_FILE='mysql-bin.000008',
-> MASTER_LOG_POS=335481914;
mysql> START SLAVE;
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.15.15
Master_User: repl
Master_Port: 3306
Connect_Retry: 0
Master_Log_File: mysql-bin.000008-->遠程master端binlog文件名
Read_Master_Log_Pos: 338500476----->執行到master的binlog位置
Relay_Log_File: service-relay-bin.000002-->relay-log文件名
Relay_Log_Pos: 3018815-->本地執行到relay-log的位置
Relay_Master_Log_File: mysql-bin.000008
Slave_IO_Running: Yes------------>slave向master發起請求的io進程,正常=Yes 異常=No
Slave_SQL_Running: Yes---------->slave在本地執行sql的sql進程,正常=Yes 異常=No
Replicate_Do_DB:
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 338500476
Relay_Log_Space: 3018973
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File: oduct w
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 4
1 row in set (0.00 sec)
總結:mysql在賦值的時候,insert語句雖然在binlog中沒有主鍵,但是根據本次事故的觀察,insert操作是在真實數據庫操作的時候,卻與A機保持一致;比如有t1表為空表,則:
- 現在斷開同步,在A機上插入表t1一條記錄id=1, 此時在C上t1是空表;
- 在從最新點連接同步后,id=1的記錄沒有同步,因為連接的點不是當時的斷點; 此時在A上再次插入表t1一條記錄id=2, 查看C已經同步成功,并且在C上t1表只有一條記錄id=2和A保持一致;
- 在C上斷點出連接成功后,查看C上的t1表有兩條記錄,id分別和A上t1表保持一致;