背景:
對於MySQL的binlog的查看都是用其自帶的工具mysqlbinlog進行操作的,其實還有另一個方法來操作binlog,就是Replication中的SQL線程去操作binlog,其實binlog和relaylog的格式是一樣的。下面開始介紹如何用該方法進行對binlog的操作。
測試1:
---初始化: root@192.168.200.25 : aaa 03:51:38>reset master; Query OK, 0 rows affected (0.12 sec) root@192.168.200.25 : aaa 03:51:55>reset slave; Query OK, 0 rows affected (0.00 sec) root@192.168.200.25 : aaa 03:51:59>create table test_binlog(id int not null auto_increment,name varchar(10),primary key(id))
engine =innodb default charset utf8; Query OK, 0 rows affected (0.17 sec) root@192.168.200.25 : aaa 03:52:11>insert into test_binlog(name) values('a'),('b'),('c'),('d'),('e'); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 root@192.168.200.25 : aaa 03:52:20>insert into test_binlog(name) values('aa'),('bb'),('cc'),('dd'),('ee'); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 root@192.168.200.25 : aaa 03:52:24>insert into test_binlog(name) values('aaa'),('bbb'),('ccc'),('ddd'),('eee'); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 ---刪除數據,為了恢復: root@192.168.200.25 : aaa 03:52:28>flush logs; Query OK, 0 rows affected (0.13 sec) root@192.168.200.25 : aaa 03:53:21>drop table test_binlog; Query OK, 0 rows affected (0.08 sec)
把Binlog復制到Relaylog 目錄:
root@zhoujy:/var/lib/mysql# cp /var/log/mysql/mysql-bin.000001 /var/lib/mysql/relay-bin.000001
root@zhoujy:/var/lib/mysql# chown -R mysql:mysql relay-bin.000001
修改my.cnf文件:
relay_log = slave_relay
skip-slave-start
server-id = 2 #測試例子是自己的binlog對自己恢復,根據Replication原理,需要修改其Server_id SQL線程才能進行操作
需要生成master.info,relay-log.info,slave_relay.index等Replication需要的文件。
root@192.168.200.25 : aaa 04:00:29>change master to master_host='192.168.220.25',master_user='rep',master_password='rep',
MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=120,master_port=3306; #隨便change 到一個地址,目的是為了生成SQL線程
關閉MySQL並修改Relaylog相關的文件:
vi relay-log.info
---
./slave_relay.000001
4
mysql-bin.000001
120
---
修改成:
---
./relay-bin.000001 #復制過來的binlog文件
4 #開始復制的postition
mysql-bin.000001
120
---
vi slave_relay.index
---
./slave_relay.000001
---
修改成:
---
./relay-bin.000001 #復制過來的binlog文件
---
開啟MySQL並查看復制的狀態:
root@192.168.200.25 : aaa 04:08:04>show slave status\G;
*************************** 1. row *************************** Slave_IO_State: Master_Host: 192.168.220.25 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 120 Relay_Log_File: relay-bin.000001 #Relaylog 已經被替換 Relay_Log_Pos: 4 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: No Slave_SQL_Running: No Replicate_Do_DB: aaa Replicate_Ignore_DB: 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: 120 Relay_Log_Space: 1203 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error:
最后啟動SQL線程:
root@192.168.200.25 : aaa 04:14:58>select * from test_binlog; ERROR 1146 (42S02): Table 'aaa.test_binlog' doesn't exist
root@192.168.200.25 : aaa 04:15:00>start slave sql_thread; Query OK, 0 rows affected (0.00 sec)
#已經恢復:
root@192.168.200.25 : aaa 04:15:11>select * from test_binlog; +----+------+ | id | name | +----+------+ | 1 | a | | 2 | b | | 3 | c | | 4 | d | | 5 | e | | 6 | aa | | 7 | bb | | 8 | cc | | 9 | dd | | 10 | ee | | 11 | aaa | | 12 | bbb | | 13 | ccc | | 14 | ddd | | 15 | eee | +----+------+ 15 rows in set (0.00 sec)
例1結束,上面測試說明通過binlog,把其當成relaylog進行處理,成功的用SQL線程進行恢復。
測試2:
上面是對一個binlog進行恢復的,那如何對多個binlog進行恢復呢?馬上來測試下:
---log1中 root@192.168.200.25 : aaa 04:57:39>create table test_binlog(id int not null auto_increment,name varchar(10),primary key(id))
engine =innodb default charset utf8; Query OK, 0 rows affected (0.17 sec) root@192.168.200.25 : aaa 04:57:47>insert into test_binlog(name) values('a'),('b'),('c'),('d'),('e'); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 root@192.168.200.25 : aaa 04:57:52>insert into test_binlog(name) values('aa'),('bb'),('cc'),('dd'),('ee'); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 root@192.168.200.25 : aaa 04:57:57>flush logs; Query OK, 0 rows affected (0.13 sec) ---log2中 root@192.168.200.25 : aaa 04:58:04>insert into test_binlog(name) values('aaaa'),('bbbb'),('cccc'),('dddd'),('eeee'); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 root@192.168.200.25 : aaa 04:58:10>insert into test_binlog(name) values('aaaaa'),('bbbbb'),('ccccc'),('ddddd'),('eeeee'); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 root@192.168.200.25 : aaa 04:58:15>flush logs; Query OK, 0 rows affected (0.12 sec) ---log3中 root@192.168.200.25 : aaa 04:58:19>insert into test_binlog(name) values('Aaaaaa'),('Bbbbbb'),('Cccccc'),('Dddddd'),('Eeeeee'); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 root@192.168.200.25 : aaa 04:58:23>use test; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A ---切換當前數據庫,test下面插入10行 Database changed root@192.168.200.25 : test 04:58:29>insert into aaa.test_binlog(name) values('A'),('B'),('C'),('D'),('E'); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 root@192.168.200.25 : test 04:58:33>insert into aaa.test_binlog(name) values('AA'),('BB'),('CC'),('DD'),('EE'); Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0 ---切換當前數據庫 root@192.168.200.25 : test 05:34:09>use aaa Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed root@192.168.200.25 : aaa 05:34:19>insert into aaa.test_binlog(name) values('AAAAAA'),('BBBBBBB'),('CCCCCCC'),('DDDDDDD'),('EEEEEEE'); Query OK, 5 rows affected (0.05 sec) Records: 5 Duplicates: 0 Warnings: 0 root@192.168.200.25 : aaa 05:34:40>select * from test_binlog; +----+---------+ | id | name | +----+---------+ | 1 | a | | 2 | b | | 3 | c | | 4 | d | | 5 | e | | 6 | aa | | 7 | bb | | 8 | cc | | 9 | dd | | 10 | ee | | 11 | aaaa | | 12 | bbbb | | 13 | cccc | | 14 | dddd | | 15 | eeee | | 16 | aaaaa | | 17 | bbbbb | | 18 | ccccc | | 19 | ddddd | | 20 | eeeee | | 21 | Aaaaaa | | 22 | Bbbbbb | | 23 | Cccccc | | 24 | Dddddd | | 25 | Eeeeee | | 26 | A | | 27 | B | | 28 | C | | 29 | D | | 30 | E | | 31 | AA | | 32 | BB | | 33 | CC | | 34 | DD | | 35 | EE | | 36 | AAAAAA | | 37 | BBBBBBB | | 38 | CCCCCCC | | 39 | DDDDDDD | | 40 | EEEEEEE | +----+---------+ 40 rows in set (0.00 sec)
按照例1中的步驟操作,復制Binlog:
cp mysql-bin.000001 /var/lib/mysql/relay-bin.000001
cp mysql-bin.000002 /var/lib/mysql/relay-bin.000002
cp mysql-bin.000003 /var/lib/mysql/relay-bin.000003
chown -R mysql:mysql relay-bin.00000*
修改my.cnf文件:
server-id = 12
relay_log = slave_relay
skip-slave-start
replicate_do_db = aaa
需要生成master.info,relay-log.info,slave_relay.index等Replication需要的文件。
change master to master_host='192.168.220.25',master_user='rep',master_password='rep',MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=120,master_port=3306;
關閉MySQL並修改Relaylog相關的文件:
vi relay-log.info 修改成:
---
./relay-bin.000001
4
mysql-bin.000001
120
---
vi slave_relay.index 修改成,這里和例1不同
---
./relay-bin.000001
./relay-bin.000002
./relay-bin.000003
---
開啟MySQL並查看復制的狀態:
root@192.168.200.25 : aaa 05:38:04>show slave status\G; *************************** 1. row *************************** Slave_IO_State: Master_Host: 192.168.220.25 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 120 Relay_Log_File: relay-bin.000001 #Relaylog 已經被替換 Relay_Log_Pos: 4 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: No Slave_SQL_Running: No Replicate_Do_DB: aaa Replicate_Ignore_DB: 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: 120 Relay_Log_Space: 2889 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: 1 row in set (0.06 sec)
最后啟動SQL線程:
root@192.168.200.25 : aaa 05:44:11>select * from test_binlog; ERROR 1146 (42S02): Table 'aaa.test_binlog' doesn't exist
root@192.168.200.25 : aaa 05:44:18>start slave sql_thread; Query OK, 0 rows affected (0.00 sec) root@192.168.200.25 : aaa 05:44:29>select * from test_binlog; +----+---------+ | id | name | +----+---------+ | 1 | a | | 2 | b | | 3 | c | | 4 | d | | 5 | e | | 6 | aa | | 7 | bb | | 8 | cc | | 9 | dd | | 10 | ee | | 11 | aaaa | | 12 | bbbb | | 13 | cccc | | 14 | dddd | | 15 | eeee | | 16 | aaaaa | | 17 | bbbbb | | 18 | ccccc | | 19 | ddddd | | 20 | eeeee | | 21 | Aaaaaa | | 22 | Bbbbbb | | 23 | Cccccc | | 24 | Dddddd | | 25 | Eeeeee | | 36 | AAAAAA | | 37 | BBBBBBB | | 38 | CCCCCCC | | 39 | DDDDDDD | | 40 | EEEEEEE | +----+---------+ 30 rows in set (0.01 sec)
這里看到可以正常的恢復了,但是數據不對,少了10行(26~35行)。為什么少了?這里大家應該都很清楚了,因為是在初始化的時候有10行數據是在test數據庫下面插入的,而在配置文件中只復制aaa數據庫下的操作記錄(replicate_do_db = aaa)。這也是通過Relaylog恢復的一個優點。
總結:
上面的測試在5.1到5.1 和 5.1到5.5的操作都沒有問題,所以通過本文介紹的方法去操作Binlog,更有靈活性,可以隨時進行stop、start slave操作;通過測試了解到,在用binlog進行增量備份的場景下,使用該方法更有效直接的進行恢復,比本身的mysqlbinlog 更有效;也可以解決mysqlbinlog的一些問題:
(*) Max_allowed_packet問題
(*) 惱人的Blob/Binary/text字段問題
(*) 特殊字符的轉義問題
(*) 沒有"斷點恢復":執行出錯后,沒有足夠的報錯,也很難從失敗的地方繼續恢復
更多信息:
http://www.orczhou.com/index.php/2013/11/use-mysql-replication-to-recove-binlog/
http://blog.itpub.net/22664653/viewspace-775778/