MySQL二進制日誌(BINARY LOG)說明及使用

概述

MySQL二進制日誌(Binary Log,簡稱binlog)記錄着數據庫中所有更新數據的SQL語句,也就是數據庫的增,刪,改操作語句,將其寫入到二進制日誌中,以時間的形式保存。

優缺

優點:

  1. 恢復數據庫
  2. 可用於MySQL數據庫的主從架構

缺點:

  1. 消耗一部分性能
  2. 花費時間維護二進制日誌

開啓binlog日誌

注:案例中MySQL版本爲8.0.13

mysql --version
mysql  Ver 8.0.13 for Linux on x86_64 (Source distribution)

查看二進制日誌是否開啓

mysql> show variables like 'log_bin%';
+---------------------------------+-------------------------------+
| Variable_name                   | Value                         |
+---------------------------------+-------------------------------+
| log_bin                         | ON                            |
| log_bin_basename                | /data/mysql/data/binlog       |
| log_bin_index                   | /data/mysql/data/binlog.index |
| log_bin_trust_function_creators | OFF                           |
| log_bin_use_v1_row_events       | OFF                           |
+---------------------------------+-------------------------------+

log_bin爲OFF表示binlog日誌沒有開啓。

開啓二進制日誌
MySQL二進制日誌默認是關閉的,可以通過編輯/etc/my.cnf配置文件

server-id=1
log-bin=/data/mysql/log/mysql-bin
expire_logs_days = 30
max_binlog_size = 200M

配置項說明:
sever-id:設置MySQL數據庫id,MySQL5.7及以上版本需加
log-bin:binlog日誌存放路徑
expire_logs_days:binlog日誌的保存時間,超過將會自動刪除
max_binlog_size:binlog日誌文件大小,根據環境而定

添加完成後,重啓MySQL,首先確認有沒有創建二進制日誌文件

查看binlog文件

 ls /data/mysql/log/
mysql-bin.000001  mysql-bin.index  mysqld.log

其中mysql-bin.000001 就是binlog文件,而mysql-bin.index的功能是記錄所有Binary Log的絕對路徑,保證MySQL各種線程能夠順利的根據他找到所有需要的Binary Log文件。

cat /data/mysql/log/mysql-bin.index 
/data/mysql/log/mysql-bin.000001

查看binlog是否開啓

mysql> show variables like 'log_bin%';
+---------------------------------+---------------------------------+
| Variable_name                   | Value                           |
+---------------------------------+---------------------------------+
| log_bin                         | ON                              |
| log_bin_basename                | /data/mysql/log/mysql-bin       |
| log_bin_index                   | /data/mysql/log/mysql-bin.index |
| log_bin_trust_function_creators | OFF                             |
| log_bin_use_v1_row_events       | OFF                             |
+---------------------------------+---------------------------------+

其中log_bin爲NO,表示二進制日誌已經開啓了。

除以上配置項外,binlog還有其他一些附加的選項參數:

max_binlog_size:設置binlog的最大存儲上限,一般設置爲512M或者1G,一般不能超過1G。當日志達到該上限時,MySQL 會重新創建一個日誌開始繼續記錄。不過偶爾也有超出該設置的binlog 產生,一般都是因爲在即將達到上限時,產生了一個較大的事務,爲了保證事務安全,MySQL 不會將同一個事務分開記錄到兩個binlog 中。

注:已在my.cnf文件中設置爲200MB

mysql> show variables like '%max_binlog_size%';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| max_binlog_size | 209715200 |
+-----------------+-----------+

binlog_cache_size:一個事務在沒有提交之前,產生的日誌記錄到cache中,等到事務提交的時候,則把日誌持久化到磁盤。一般來說,如果我們的數據庫中沒有什麼大事務,寫入也不是特點頻繁,2MB~4MB是個合適的選擇。但是如果我們的數據庫大事務較多,寫入量比較大,可與適當調高binlog_cache_size,默認值32768。

mysql> show variables like 'binlog_cache_size%';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| binlog_cache_size | 32768 |
+-------------------+-------+

binlog_format:二進制日誌類型,共三種,分別是:STATEMENT,ROW,MIXED。

mysql> show variables like '%binlog_f%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+

查看&刪除二進制日誌

查看binlog日誌

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       155 |
+------------------+-----------+

查看binlog日誌內容

mysql> show binlog events in 'mysql-bin.000001';
+------------------+-----+----------------+-----------+-------------+-----------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                              |
+------------------+-----+----------------+-----------+-------------+-----------------------------------+
| mysql-bin.000001 |   4 | Format_desc    |         1 |         124 | Server ver: 8.0.13, Binlog ver: 4 |
| mysql-bin.000001 | 124 | Previous_gtids |         1 |         155 |                                   |
+------------------+-----+----------------+-----------+-------------+-----------------------------------+

查看master日誌狀態

注:MySQL開啓主從複製時使用

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000001
         Position: 155
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 

刷新binlog日誌

注:刷新完成後,會自動創建一個新的二進制日誌,是在當前二進制日誌名稱後基礎上+1,例如,mysql-bin.000001刷新完成後名稱爲mysql-bin.000002,之後的數據更新的SQL語句將存放在mysql-bin.000002中。

mysql> flush logs;
mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       202 |
| mysql-bin.000002 |       155 |
+------------------+-----------+

清空binlog日誌

注:其實過程是將之前的二進制日誌刪除,然後重新創建一個二進制日誌,用於存放數據更新的SQL語句。

mysql> reset master;
mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       155 |
+------------------+-----------+

查看binlog日誌文件內容

二進制日誌爲二進制格式存儲,使用此格式可以存儲更多的信息,並且可以使用寫入二進制日誌的效率更高。但缺點是無法直接linux命令(如cat,less等)查看二進制日誌。

例如:

cat /data/mysql/log/mysql-bin.000001                                
`þbinVԡ^x|8.0.13^               
**4

mysqlbinlog命令

想要查看二進制日誌文件中具體的內容,還得藉助MySQL組件中的mysqlbinlog這個工具。

語法格式:mysqlbinlog 參數 文件路徑

具體參數可以通過- -help來自行查看,若是查看文件內容,只需要加上-v參數即可。

進入mysql數據庫,執行一些SQL語句,並查看二進制日誌內容。

create database test;
use test;
create table binlog(id int,name varchar(11));
insert into binlog values(1,'測試');

查看二進制日誌內容

mysqlbinlog -v /data/mysql/log/mysql-bin.000001 
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#200611 15:02:53 server id 1  end_log_pos 124 CRC32 0xb8a56743 	Start: binlog v 4, server v 8.0.13 created 200611 15:02:53 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
HdfhXg8BAAAAeAAAAHwAAAABAAQAOC4wLjEzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAd1+FeEwANAAgAAAAABAAEAAAAYAAEGggAAAAICAgCAAAACgoKKioAEjQA
CgFDZ6W4
'/*!*/;
# at 124
#200611 15:02:53 server id 1  end_log_pos 155 CRC32 0xa2e2079b 	Previous-GTIDs
# [empty]
# at 155
#200611 15:03:11 server id 1  end_log_pos 228 CRC32 0x553603b4 	Anonymous_GTID	last_committed=0	sequence_number=1	rbr_only=no	original_committed_timestamp=1591858992368103	immediate_commit_timestamp=1591858992368103	transaction_length=181
# original_commit_timestamp=1591858992368103 (2020-06-11 15:03:12.368103 CST)
# immediate_commit_timestamp=1591858992368103 (2020-06-11 15:03:12.368103 CST)
/*!80001 SET @@session.original_commit_timestamp=1591858992368103*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 228
#200611 15:03:11 server id 1  end_log_pos 336 CRC32 0xa17df524 	Query	thread_id=10	exec_time=1	error_code=0	Xid = 45
SET TIMESTAMP=1591858991/*!*/;
SET @@session.pseudo_thread_id=10/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1168113696/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb4 *//*!*/;
SET @@session.character_set_client=45,@@session.collation_connection=45,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
/*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/;
/*!80013 SET @@session.sql_require_primary_key=0*//*!*/;
create database test
/*!*/;
# at 336
#200611 15:03:38 server id 1  end_log_pos 409 CRC32 0xad6609b8 	Anonymous_GTID	last_committed=1	sequence_number=2	rbr_only=no	original_committed_timestamp=1591859018545646	immediate_commit_timestamp=1591859018545646	transaction_length=205
# original_commit_timestamp=1591859018545646 (2020-06-11 15:03:38.545646 CST)
# immediate_commit_timestamp=1591859018545646 (2020-06-11 15:03:38.545646 CST)
/*!80001 SET @@session.original_commit_timestamp=1591859018545646*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 409
#200611 15:03:38 server id 1  end_log_pos 541 CRC32 0x0bbfaccc 	Query	thread_id=10	exec_time=0	error_code=0	Xid = 50
use `test`/*!*/;
SET TIMESTAMP=1591859018/*!*/;
/*!80013 SET @@session.sql_require_primary_key=0*//*!*/;
create table binlog(id int,name varchar(11))
/*!*/;
# at 541
#200611 15:03:54 server id 1  end_log_pos 616 CRC32 0xd6ca34b1 	Anonymous_GTID	last_committed=2	sequence_number=3	rbr_only=yes	original_committed_timestamp=1591859034487911	immediate_commit_timestamp=1591859034487911	transaction_length=288
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
# original_commit_timestamp=1591859034487911 (2020-06-11 15:03:54.487911 CST)
# immediate_commit_timestamp=1591859034487911 (2020-06-11 15:03:54.487911 CST)
/*!80001 SET @@session.original_commit_timestamp=1591859034487911*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 616
#200611 15:03:54 server id 1  end_log_pos 693 CRC32 0xa6d0298b 	Query	thread_id=10	exec_time=0	error_code=0
SET TIMESTAMP=1591859034/*!*/;
/*!80013 SET @@session.sql_require_primary_key=0*//*!*/;
BEGIN
/*!*/;
# at 693
#200611 15:03:54 server id 1  end_log_pos 751 CRC32 0x388491fc 	Table_map: `test`.`binlog` mapped to number 88
# at 751
#200611 15:03:54 server id 1  end_log_pos 798 CRC32 0xf79be854 	Write_rows: table id 88 flags: STMT_END_F

BINLOG '
WtfhXhMBAAAAOgAAAO8CAAAAAFgAAAAAAAEABHRlc3QABmJpbmxvZwACAw8CIQADAQEAAgEh/JGE
OA==
WtfhXh4BAAAALwAAAB4DAAAAAFgAAAAAAAEAAgAC/wABAAAABua1i+ivlVTom/c=
'/*!*/;
### INSERT INTO `test`.`binlog`
### SET
###   @1=1
###   @2='測試'
# at 798
#200611 15:03:54 server id 1  end_log_pos 829 CRC32 0x41beb43c 	Xid = 51
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

在二進制日誌記錄中,有兩種查看的方式:

1)第一種是基於時間查看,每條保存的SQL語句都有唯一的時間保存。
2)第二種是基於所在位置,每條保存的SQL語句再前面都有一個at並用唯一id標記。

例如以上例子中,at228 下就是創建test數據庫的SQL語句,插入的第一條記錄則在at751後。

二進制日誌恢復數據

查看的方式有兩種,恢復的方式也有兩種,基於時間點恢復,基於位置恢復。個人比較喜歡基於位置恢復。

首先,刪除創建的test數據庫,模擬數據丟失。

mysql> drop database test;

刷新一個新的二進制日誌

mysql> flush logs;

之前查看二進制日誌可以知道,at228-at751是全部的測試語句,之後就是其他SQL語句及誤操作的刪除語句。

基於位置恢復:
–start-position 從二進制日誌中讀取指定position 事件位置作爲開始。

–stop-position 從二進制日誌中讀取指定position 事件位置作爲結束。

注:將其理解爲從at哪裏開始,到at哪裏結束即可

拿此案例爲例,恢復語句爲

mysqlbinlog --start-position="228" --stop-position="798" /data/mysql/log/mysql-bin.000001 | mysql -uroot

可以發現–stop-position=“798” ,而不是751,這是因爲結束機制的問題,不會執行指定結束位置的SQL語句,所以結束位置要稍大於原位置。

再次進入數據庫,查看是否恢復

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章