初步瞭解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日誌列表
[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