Mysql之Binlog日誌 徹底備份|增量 +binlog日誌基於時間點恢復數據

 初步瞭解binlog:

    衆所周知,binlog日誌對於mysql數據庫來講是十分重要的。在數據丟失的緊急狀況下,咱們每每會想到用binlog日誌功能進行數據恢復(定時全備份+binlog日誌恢復增量數據部分),化險爲夷!html

廢話很少說,下面是梳理的binlog日誌操做解說:node

MySQL的二進制日誌binlog能夠說是MySQL最重要的日誌,它記錄了全部的DDL和DML語句(除了數據查詢語句select),以事件形式記錄,還包含語句所執行的消耗的時間,MySQL的二進制日誌是事務安全型的。mysql

DDL
----Data Definition Language 數據庫定義語言 
主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定義或改變表(TABLE)的結構,數據類型,表之間的連接和約束等初始化工做上,他們大多在創建表時使用。sql

DML
----Data Manipulation Language 數據操縱語言
主要的命令是SELECT、UPDATE、INSERT、DELETE,就象它的名字同樣,這4條命令是用來對數據庫裏的數據進行操做的語言數據庫

mysqlbinlog 經常使用選項 通常來講開啓binlog日誌大概會有1%的性能損耗:

 

1 --start-datetime:從二進制日誌中讀取指定等於時間戳或者晚於本地計算機的時間
2 --stop-datetime: 從二進制日誌中讀取指定小於時間戳或者等於本地計算機的時間 取值和上述同樣
3 --start-position:從二進制日誌中讀取指定position 事件位置做爲開始。
4 --stop-position: 從二進制日誌中讀取指定position 事件位置做爲事件截至
binlog日誌有兩個最重要的使用場景:

1)MySQL主從複製:MySQL Replication在Master端開啓binlog,Master把它的二進制日誌傳遞給slaves來達到
master-slave數據一致的目的。 
2)天然就是數據恢復了,經過使用mysqlbinlog工具來使恢復數據。vim

binlog日誌包括兩類文件:
1)二進制日誌索引文件(文件名後綴爲.index)用於記錄全部的二進制文件
2)二進制日誌文件(文件名後綴爲.00000*)記錄數據庫全部的DDL和DML(除了數據查詢語句select)語句事件。安全

開啓binlog日誌:

 

1 編輯mariadb配置文件
2 [root@node-zabbix ~]# cat /etc/my.cnf
3 在[mysqld] 區塊添加 
4 innodb_file_per_table =ON  #爲每一個表開啓單獨的表空間
5 log-bin=mysql-bin          #開啓binlog   mysql-bin 只是日誌前綴
6 [root@node-zabbix ~]# systemctl restart mariadb.service
查看binlog日誌是否開啓:
 1 [root@node-zabbix ~]# mysql -e "show variables like 'log_%'"
 2 +---------------------------------+--------------------------------------------------------------------------------------------------------------+
 3 | Variable_name                   | Value                                                                                                        |
 4 +---------------------------------+--------------------------------------------------------------------------------------------------------------+
 5 | log_bin                         | ON                                                                                                           |
 6 | log_bin_trust_function_creators | OFF                                                                                                          |
 7 | log_error                       | /var/log/mariadb/mariadb.log                                                                                 |
 8 | log_output                      | FILE                                                                                                         |
 9 | log_queries_not_using_indexes   | OFF                                                                                                          |
10 | log_slave_updates               | OFF                                                                                                          |
11 | log_slow_filter                 | admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk |
12 | log_slow_queries                | OFF                                                                                                          |
13 | log_slow_rate_limit             | 1                                                                                                            |
14 | log_slow_verbosity              |                                                                                                              |
15 | log_warnings                    | 1                                                                                                            |
16 +---------------------------------+--------------------------------------------------------------------------------------------------------------+
查看binlog日誌是否開啓
經常使用binlog日誌操做命令:
#查看全部binlog日誌列表
[root@node-zabbix ~]# mysql -e "show master logs" +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 30349 | | mysql-bin.000002 | 1038814 | | mysql-bin.000003 | 106446169 | | mysql-bin.000004 | 16705415 | +------------------+-----------+
#查看master狀態,即最後(最新)一個binlog日誌的編號名稱,及其最後一個操做事件pos結束點(Position)值
[root@node-zabbix ~]# mysql -e "show master status" +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000004 | 16725872 | | | +------------------+----------+--------------+------------------+
#flush刷新log日誌,自此刻開始產生一個新編號的binlog日誌文件
注意:
每當mysqld服務重啓時,會自動執行此命令,刷新binlog日誌;在mysqldump備份數據時加 -F 選項也會刷新binlog日誌;
[root@node-zabbix ~]# mysql -e "flush logs" [root@node-zabbix ~]# mysql -e "show master logs" +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 30349 | | mysql-bin.000002 | 1038814 | | mysql-bin.000003 | 106446169 | | mysql-bin.000004 | 16761013 | | mysql-bin.000005 | 1698 | +------------------+-----------+
#重置(清空)全部binlog日誌
[root@node-zabbix ~]# mysql -e "reset master" [root@node-zabbix ~]# mysql -e "show master logs" +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 1032 | +------------------+-----------+
查看binlog日誌內容:

    

 1 #使用mysqlbinlog自帶查看命令法:
 2 [root@node01 mysql]# mysqlbinlog mysql-bin.000001 ..........
 3 ..........
 4 ..........
 5 # at 593
 6 #180416 21:59:10 server id 1  end_log_pos 712     Query    thread_id=3    exec_time=0    error_code=0
 7 SET TIMESTAMP=1523930350/*!*/;
 8 insert into tb1(name,age)values('simple',23),('alex',34)    #執行SQL語句
 9 /*!*/;
10 # at 712
11 #180416 21:59:10 server id 1  end_log_pos 739     Xid = 24
12 COMMIT/*!*/;                                                #執行sql語句時間
13 # at 739
14 #180416 22:09:54 server id 1  end_log_pos 807     Query    thread_id=3    exec_time=0    error_code=0
15 SET TIMESTAMP=1523930994/*!*/;
16 BEGIN
17 /*!*/;
18 # at 807
19 #180416 22:09:54 server id 1  end_log_pos 835     Intvar
20 SET INSERT_ID=5/*!*/;
21 # at 835
22 #180416 22:09:54 server id 1  end_log_pos 941     Query    thread_id=3    exec_time=0    error_code=0
23 SET TIMESTAMP=1523930994/*!*/;
24 insert into tb1(name,age)values('simle',23)
25 /*!*/;
26 # at 941
27 #180416 22:09:54 server id 1  end_log_pos 968     Xid = 25
28 COMMIT/*!*/;
29 DELIMITER ;
30 # End of log file
31 ROLLBACK /* added by mysqlbinlog */;
32 /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
33 /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
34 解釋:
35 server id 1 : 數據庫主機的服務號;
36 end_log_pos 712: sql結束時的pos節點
37 thread_id=3: 線程號
方法一
1 2)上面這種辦法讀取出binlog日誌的全文內容比較多,不容易分辨查看到pos點信息
 2 下面介紹一種更爲方便的查詢命令:
 3 命令格式:
 4 mysql> show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count];
 5 參數解釋:
 6 IN 'log_name' :指定要查詢的binlog文件名(不指定就是第一個binlog文件)
 7 FROM pos :指定從哪一個pos起始點開始查起(不指定就是從整個文件首個pos點開始算)
 8 LIMIT [offset,] :偏移量(不指定就是0)
 9 row_count :查詢總條數(不指定就是全部行)
10 
11 以下操做示例:
12 MariaDB [test]> show binlog events in 'mysql-bin.000001'\G;
13 *************************** 1. row ***************************
14    Log_name: mysql-bin.000001
15         Pos: 4
16  Event_type: Format_desc
17   Server_id: 1
18 End_log_pos: 245
19        Info: Server ver: 5.5.56-MariaDB, Binlog ver: 4
20 *************************** 2. row ***************************
21    Log_name: mysql-bin.000001
22         Pos: 245
23  Event_type: Query
24   Server_id: 1
25 End_log_pos: 497
26        Info: use `test`; CREATE TABLE `tb1` (   `id` int(11) NOT NULL AUTO_INCREMENT,   `name` char(32) NOT NULL,   `age` int(11) NOT NULL,   PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
27 *************************** 3. row ***************************
28    Log_name: mysql-bin.000001
29         Pos: 497
30  Event_type: Query
31   Server_id: 1
32 End_log_pos: 565
33        Info: BEGIN
34 *************************** 4. row ***************************
35    Log_name: mysql-bin.000001
36         Pos: 565
37  Event_type: Intvar
38   Server_id: 1
39 End_log_pos: 593
40        Info: INSERT_ID=3
41 *************************** 5. row ***************************
42    Log_name: mysql-bin.000001
43         Pos: 593
44  Event_type: Query
45   Server_id: 1
46 End_log_pos: 712
47        Info: use `test`; insert into tb1(name,age)values('simple',23),('alex',34)
48 *************************** 6. row ***************************
49    Log_name: mysql-bin.000001
50         Pos: 712
51  Event_type: Xid
52   Server_id: 1
53 End_log_pos: 739
54        Info: COMMIT /* xid=24 */
55 *************************** 7. row ***************************
56    Log_name: mysql-bin.000001
57         Pos: 739
58  Event_type: Query
59   Server_id: 1
60 End_log_pos: 807
61        Info: BEGIN
62 *************************** 8. row ***************************
63    Log_name: mysql-bin.000001
64         Pos: 807
65  Event_type: Intvar
66   Server_id: 1
67 End_log_pos: 835
68        Info: INSERT_ID=5
69 *************************** 9. row ***************************
70    Log_name: mysql-bin.000001
71         Pos: 835
72  Event_type: Query
73   Server_id: 1
74 End_log_pos: 941
75        Info: use `test`; insert into tb1(name,age)values('simle',23)
76 *************************** 10. row ***************************
77    Log_name: mysql-bin.000001
78         Pos: 941
79  Event_type: Xid
80   Server_id: 1
81 End_log_pos: 968
82        Info: COMMIT /* xid=25 */
83 10 rows in set (0.00 sec)
84 
85 ERROR: No query specified
86 a)查詢第一個(最先)的binlog日誌:
87 mysql> show binlog events\G;
88 
89 b)指定查詢 mysql-bin.000002這個文件:
90 mysql> show binlog events in 'mysql-bin.000002'\G;
91 
92 c)指定查詢 mysql-bin.000002這個文件,從pos點:624開始查起:
93 mysql> show binlog events in 'mysql-bin.000002' from 624\G;
94 
95 d)指定查詢 mysql-bin.000002這個文件,從pos點:624開始查起,查詢10條(即10條語句)
96 mysql> show binlog events in 'mysql-bin.000002' from 624 limit 10\G;
97 
98 e)指定查詢 mysql-bin.000002這個文件,從pos點:624開始查起,偏移2行(即中間跳過2個),查詢10條
99 mysql> show binlog events in 'mysql-bin.000002' from 624 limit 2,10\G;
方法二
使用binglog日誌恢復mysql數據:

 

MariaDB [test]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| jeebbs             |
| mysql              |
| performance_schema |
| shop               |
| test               |
| xtrabackup         |
| zrlog              |
+--------------------+
8 rows in set (0.00 sec)

MariaDB [test]> use test;
Database changed
MariaDB [test]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| tb1            |
| tb2            |
+----------------+
2 rows in set (0.00 sec)

MariaDB [test]> select * from tb1;
+----+--------+-----+
| id | name   | age |
+----+--------+-----+
|  3 | simple |  23 |
|  4 | alex   |  34 |
|  5 | simle  |  23 |
+----+--------+-----+
3 rows in set (0.00 sec)

下面開始進行場景模擬

[root@node01 ~]#crontab -lbash

0 4 * * * /usr/bin/mysqldump -uroot -p -B test -F -R -x --master-data=2 gzip >/tmp/test_$(date +%F).sql.gzide

命令的語法格式:
mysqldump [OPTIONS] database [tables]:備份單個庫,或庫指定的一個或多個表
mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]:備份一個或多個庫
mysqldump [OPTIONS] --all-databases [OPTIONS]:備份全部庫函數

[root@node01 ~]# mysqldump -uroot -B test -F -R -x --master-data=2 |gzip >/tmp/test_$(date +%F).sql.gz

[root@node01 ~]# ll /tmp/
total 504
-rw-r--r-- 1 root root 513534 Apr 17 01:32 test_2018-04-17.sql.gz

參數說明:

 -A, --all-databases  備份全部表

-x, --lock-all-tables:鎖定全部表

-l, --lock-tables:鎖定備份的表

--single-transaction:啓動一個大的單一事務實現備份

-B, --databases db_name1 db_name2 ...:備份指定的數據庫

-C, --compress:壓縮傳輸;

-E, --events:備份指定庫的事件調度器;
-R, --routines:備份存儲過程和存儲函數;

--master-data[=#]:
    1:記錄CHANGE MASTER TO語句;此語句未被註釋;
    2:記錄爲註釋語句;

--flush-logs, -F:鎖定表以後執行flush logs命令;

 

-----------------
待到數據庫備份完成,就不用擔憂數據丟失了,由於有徹底備份數據在!!

因爲上面在全備份的時候使用了-F選項,那麼當數據備份操做剛開始的時候系統就會自動刷新log,這樣就會自動產生
一個新的binlog日誌,這個新的binlog日誌就會用來記錄備份以後的數據庫「增刪改」操做

[root@node01 ~]# mysql -e "show master status"
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 | 245 | | |
+------------------+----------+--------------+------------------+

也就是說, mysql-bin.000003 是用來記錄4:00以後對數據庫的全部「增刪改」操做。

 

2)
早上9點上班了,因爲業務的需求會對數據庫進行各類「增刪改」操做。
好比:在ops庫下member表內插入、修改了數據等等:

先是早上進行插入數據:

MariaDB [(none)]> 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

Database changed
MariaDB [test]> insert into tb1(name,age)values('張三',23),('李四',24),('店小二',28);
Query OK, 3 rows affected (0.52 sec)
Records: 3 Duplicates: 0 Warnings: 0

MariaDB [test]> update tb1 set name='諸葛亮' where id=5;
Query OK, 1 row affected (0.52 sec)
Rows matched: 1 Changed: 1 Warnings: 0

MariaDB [test]> select * from tb1;
+----+-----------+-----+
| id | name | age |
+----+-----------+-----+
| 3 | simple | 23 |
| 4 | alex | 34 |
| 5 | 諸葛亮 | 23 |
| 6 | 張三 | 23 |
| 7 | 李四 | 24 |
| 8 | 店小二 | 28 |
+----+-----------+-----+
6 rows in set (0.00 sec)

在中午12:00的時候,誤刪了一條數據,過了一會才知道數據被誤刪了,此時表裏又插入了許多數據

MariaDB [test]> delete from tb1 where id=5;

MariaDB [test]> insert into tb1(name,age)values('張三丰',23),('李奎',24),('曹操',28);
Query OK, 3 rows affected (0.03 sec)
Records: 3 Duplicates: 0 Warnings: 0

這種時候,必定不要慌張!!!
先仔細查看最後一個binlog日誌,並記錄下關鍵的pos點,究竟是哪一個pos點的操做致使了數據庫的破壞(一般在最後幾步);

先備份一下最後一個binlog日誌文件

[root@node01 mysql]# cp -a mysql-bin.000003 /root/

接着執行一次刷新日誌索引操做,從新開始新的binlog日誌記錄文件。按理說mysql-bin.000003

這個文件不會再有後續寫入了,由於便於咱們分析緣由及查找ops節點,之後全部數據庫操做都會寫入到下一個日誌文件

[root@node01 mysql]# mysql -e "flush logs"

[root@node01 mysql]# mysql -e "show master status"
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000004 | 245 | | |
+------------------+----------+--------------+------------------+

 

讀取binlog日誌,分析問題

MariaDB [(none)]> show binlog events in 'mysql-bin.000003'\G;
*************************** 1. row ***************************
Log_name: mysql-bin.000003
Pos: 4
Event_type: Format_desc
Server_id: 1
End_log_pos: 245
Info: Server ver: 5.5.56-MariaDB, Binlog ver: 4
*************************** 2. row ***************************
Log_name: mysql-bin.000003
Pos: 245
Event_type: Query
Server_id: 1
End_log_pos: 313
Info: BEGIN
*************************** 3. row ***************************
Log_name: mysql-bin.000003
Pos: 313
Event_type: Intvar
Server_id: 1
End_log_pos: 341
Info: INSERT_ID=6
*************************** 4. row ***************************
Log_name: mysql-bin.000003
Pos: 341
Event_type: Query
Server_id: 1
End_log_pos: 479
Info: use `test`; insert into tb1(name,age)values('張三',23),('李四',24),('店小二',28)
*************************** 5. row ***************************
Log_name: mysql-bin.000003
Pos: 479
Event_type: Xid
Server_id: 1
End_log_pos: 506
Info: COMMIT /* xid=143 */
*************************** 6. row ***************************
Log_name: mysql-bin.000003
Pos: 506
Event_type: Query
Server_id: 1
End_log_pos: 574
Info: BEGIN
*************************** 7. row ***************************
Log_name: mysql-bin.000003
Pos: 574
Event_type: Query
Server_id: 1
End_log_pos: 679
Info: use `test`; update tb1 set name='諸葛亮' where id=5
*************************** 8. row ***************************
Log_name: mysql-bin.000003
Pos: 679
Event_type: Xid
Server_id: 1
End_log_pos: 706
Info: COMMIT /* xid=144 */
*************************** 9. row ***************************
Log_name: mysql-bin.000003
Pos: 706
Event_type: Query
Server_id: 1
End_log_pos: 774
Info: BEGIN
*************************** 10. row ***************************
Log_name: mysql-bin.000003
Pos: 774
Event_type: Query
Server_id: 1
End_log_pos: 863
Info: use `test`; delete from tb1 where id=5
*************************** 11. row ***************************
Log_name: mysql-bin.000003
Pos: 863
Event_type: Xid
Server_id: 1
End_log_pos: 890
Info: COMMIT /* xid=146 */
*************************** 12. row ***************************
Log_name: mysql-bin.000003
Pos: 890
Event_type: Query
Server_id: 1
End_log_pos: 958
Info: BEGIN
*************************** 13. row ***************************
Log_name: mysql-bin.000003
Pos: 958
Event_type: Intvar
Server_id: 1
End_log_pos: 986
Info: INSERT_ID=9
*************************** 14. row ***************************
Log_name: mysql-bin.000003
Pos: 986
Event_type: Query
Server_id: 1
End_log_pos: 1124
Info: use `test`; insert into tb1(name,age)values('張三丰',23),('李奎',24),('曹操',28)
*************************** 15. row ***************************
Log_name: mysql-bin.000003
Pos: 1124
Event_type: Xid
Server_id: 1
End_log_pos: 1151
Info: COMMIT /* xid=147 */
*************************** 16. row ***************************
Log_name: mysql-bin.000003
Pos: 1151
Event_type: Rotate
Server_id: 1
End_log_pos: 1194
Info: mysql-bin.000004;pos=4
16 rows in set (0.00 sec)

ERROR: No query specified

經過分析,形成數據庫破壞的pos點區間是介於 774--863 之間(這是按照日誌區間的pos節點算的)。

先把凌晨4點全備份的數據恢復:

[root@node01 ~]# mysql -uroot </tmp/test_2018-04-17.sql 

可是這僅僅只是恢復了當天凌晨4點以前的數據,在4:00--12:00之間的數據尚未恢復回來!!
怎麼辦呢?
莫慌!這能夠根據前面提到的mysql-bin.000003的新binlog日誌進行恢復。

恢復命令的語法格式:
mysqlbinlog mysql-bin.0000xx | mysql -u用戶名 -p密碼 數據庫名

經過剛剛分析binlog日誌,咱們已經找到了形成數據庫破壞的pos點區間是介於 774--863 之間

a)徹底恢復(須要手動vim編輯mysql-bin.000003,將那條drop語句剔除掉)

b)指定pos結束點恢復(部分恢復):

-stop-position=706 pos結束節點(按照事務區間算,是706)恢復截止到706

--start-position=958 pos開始點

[root@node01 ~]# mysqlbinlog mysql-bin.000003 --stop-position=706 > step1.sql
[root@node01 ~]# mysqlbinlog mysql-bin.000003 --start-position=958 > step2.sql
[root@node01 ~]# mysql -uroot --database=test <step1.sql
[root@node01 ~]# mysql -uroot --database=test <step2.sql

MariaDB [(none)]> 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

Database changed
MariaDB [test]> select * from tb1;
+----+-----------+-----+
| id | name | age |
+----+-----------+-----+
| 3 | simple | 23 |
| 4 | alex | 34 |
| 5 | 諸葛亮 | 23 |
| 6 | 張三 | 23 |
| 7 | 李四 | 24 |
| 8 | 店小二 | 28 |
| 9 | 張三丰 | 23 |
| 10 | 李奎 | 24 |
| 11 | 曹操 | 28 |
+----+-----------+-----+
9 rows in set (0.00 sec)

 

本文參照     http://www.cnblogs.com/kevingrace/p/5907254.html

相關文章
相關標籤/搜索