概述
MySQL二進制日誌(Binary Log,簡稱binlog)記錄着數據庫中所有更新數據的SQL語句,也就是數據庫的增,刪,改操作語句,將其寫入到二進制日誌中,以時間的形式保存。
優缺
優點:
- 恢復數據庫
- 可用於MySQL數據庫的主從架構
缺點:
- 消耗一部分性能
- 花費時間維護二進制日誌
開啓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.13Vԡ^
**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 |
+--------------------+