1. 程式人生 > 實用技巧 >《MySQL資料庫》MySQL ERRORLOG,BINLOG,SLOWLOG日誌詳解

《MySQL資料庫》MySQL ERRORLOG,BINLOG,SLOWLOG日誌詳解

前言

MySQL 經常出現啟動錯誤或者執行錯誤等等,這個時候我們需要查詢error日誌

在資料庫使用中,經常會出現需要恢復資料的情況,MySQL如果需要恢復資料的話需要開啟binlog(二進位制日誌)。

Error Log

錯誤日誌預設設定如下:

1. error log 預設路徑在資料檔案下。

2.error log 預設檔名為主機名.err,例如:iZm5e5v2zi93osbr5z21fvZ.err。

自定義設定檔名和路徑:

開啟MySQL的配置檔案vim /etc/my.cnf 加入如下配置

log_error=/usr/local/mysql/log/mysql.log

Bin Log

1. 配置

mysql 8.0 版本之前,預設不開啟,生成建議開啟。

my.cnf 資料夾下面引數設定。

server_id = 5 ;                   # 服務編號,5.7必須要。
log_bin=/data/binlog/mysql-bin    # binlog 日誌存放目錄+字首,日誌檔名例如:mysql-bin.0001 ,注意目錄需要提前存在。
sync_binlog=1                     # binlog 刷寫的策略。1:表示提交只有立即寫入磁碟。
binlog_format=row                 # binlog的記錄格式為row模式

重啟MySQL之後再對應目錄下可以看到如下日誌:

其中 mysql-bin.index 是日誌索引檔案。

重要:binlog 日誌建議和資料盤分開存放,防止硬碟壞了的情況。

mysql> select @@log_bin_basename;    -- 查詢bin_log 存放位置
mysql> select @@log_bin;             -- 查詢bin_log 是否開啟 1:開啟

2. 說明

1. binlog 記錄內容

binlog 會記錄下以下操作:

DDL 操作表結構,欄位的語句。
DCL 許可權等一些控制語句。
DML 操作表的語句(insert,update,delete),並且是已經提交的,未提交的不會記錄

DDL 和 DCL 記錄的是你寫了啥就記錄啥。 DML語句記錄方式可以通過引數控制

mysql> select @@binlog_format;    -- 5.7 預設ROW, statement:寫啥記啥,ROW:記錄資料頁變化,mixed:混合前兩種記錄

statement : 可讀性高(文字),日誌量少,不夠嚴謹(遇到獲取當前日期的時候,因為語句是故障時執行的,但是後續通過這種方式無法獲取當時的時間點)。

row : 可讀性低(二進位制),日誌量大,嚴謹。

3. bin log 檢視

mysql> show binary logs;     -- 查詢mysql存在的binlog日誌檔案

mysql> show master status;   -- 查詢現在正在使用binlog 日誌檔案

mysql> show binlog events in 'mysql-bin.000002';   -- 檢視當前被使用的binlog 資訊

mysqlbinlog mysql-bin.000002 -- 使用mysqlbinlog 命令檢視binlog 日誌。

mysqlbinlog --base64-output=decode-rows -vvv mysql-bin.000002 -- 該命令可以翻譯binlog 下的DML 操作語句,只能用於檢視

mysql> flush logs    -- 建立新的日誌。後續binlog 就從這個新日誌開始

查詢日誌就可以看到新的日誌:

4. 通過binlog 恢復資料

模擬誤操作的情況:第9步刪除和第13步的drop。

(0) drop database if exists testdb ;
(1) create database testdb charset utf8;     
(2) use testdb;
(3) create table t1 (id int);
(4) insert into t1 values(1),(2),(3);
(5) insert into t1 values(4),(5),(6);
(6) commit
(7) update t1 set id=30 where id=3;
(8) commit;
(9) delete from t1 where id=4;
(10)commit;
(11)insert into t1 values(7),(8),(9);
(12)commit;
(13)drop database testdb;

我們要恢復第9步刪除和第13步的drop 操作之前的資料

擷取binlog 日誌,找到起點和終點。 我現在要恢復到drop 操作前: 找到開始位置點和結束位置點, 我需要的 383 到 2048 ,下面的語句就是將日誌轉化成語句。

mysqlbinlog --start-position=383 --stop-position=2048 /usr/local/mysql/binlog/mysql-bin.000003 > /usr/local/mysql/bin2.sql

還有一種通過實踐擷取的方式:

mysqlbinlog --start-datetime=200812 21:08:26 --stop-datetime=200912 21:09:09 mysql-bin.000001 mysql-bin.000002 mysql-bin.000003 > /usr/local/mysql/bin2.sql

接下來就是匯入SQL檔案即可,重點因為這是恢復,所以我們不需要他再記錄binlog日誌,故匯入SQL檔案前,先臨時關閉binlog. 操作如下:

mysql> set sql_log_bin = 0;    -- 關閉binlog日誌
mysql> source /usr/local/mysql/bin2.sql     -- 匯入sql指令碼(通過binlog截取出來的)
mysql> set sql_log_bin = 1;    -- 開啟binlog日誌

指定資料庫的binlog匯出(-d 資料庫名):

mysqlbinlog -d testdb --start-position=383 --stop-position=2048 /usr/local/mysql/binlog/mysql-bin.000003 > /usr/local/mysql/bin2.sql

binlog實際場景中的運用方式:

binlog 主要是配和備份資料一起恢復資料庫, 先通過備份資料庫恢復到比如一個星期前的資料,然後剩下的資料由binlog恢復。

5. binlog 維護命令

mysql> select @@max_binlog_size;

binlog 不要直接刪除物理檔案:

mysql> select @@expire_logs_days;    -- binlog儲存天數,0特殊表示永久儲存。

mysql> purge binary logs to 'mysql-bin.000002';     -- 刪除binlog日誌到mysql-bin.000002,也就是把mysql-bin.000001 刪除。
purge binary logs before now() - interval 3 day;     根據時間刪除,刪除3天前的日誌。
mysql> reset master;    -- 全部刪除,操作不建議使用,主從必然會down。

6. binlog(GTID)

GTID(Global Transaction ID) :

mysql> select @@session.gtid_next = 'anonymous';     -- GTID是否開啟,1開啟

GTID 定義

GTID = source_id :transaction_id 例如:7E11FA47-31CA-19E1-9E56-C43AA21293967:29

gtid-mode=on                            -- 和引數enforce-gtid-consistency一起開啟gtid功能。
enforce-gtid-consistency=true     -- 見gtid-mode說明

開啟GTID之後對資料庫的操作會記錄GTID

binlog日誌中也記錄了GTID。

mysql> select @@server_uuid;      -- 檢視gtid的uuid

資料檔案目錄下會存在一個檔案:

/usr/local/mysql/mysql-5.7.22-linux-glibc2.12-x86_64/data/auto.cnf 裡面也記錄了server_uuid。

通過案例說明如何使用gtid恢復資料

(1) create database gtiddb charset utf8;     
(2) use gtiddb ;
(3) create table t1 (id int);
(4) insert into t1 values(1),(2),(3);
(5) insert into t1 values(4),(5),(6);
(6) commit
(7) update t1 set id=30 where id=3;
(8) commit;
(9) delete from t1 where id=4;
(10)commit;
(11)insert into t1 values(7),(8),(9);
(12)commit;
(13)glush logs;
(14)insert into t1 values(10);
(15)drop database gtiddb ;

第13步模擬切換日誌, 第15步誤操作。 需要恢復到第14步。

根據(show binlog events in 'mysql-bin.000002';) 找到恢復資料的gtid起點:8993a5f5-2921-11ea-a866-00163e046b75:2 終點:8993a5f5-2921-11ea-a866-00163e046b75:9

下面是擷取命令,我們取2到9 的gtid資料,並且排除7,delete 我們也不要刪除。

mysqlbinlog --include-gtids='8993a5f5-2921-11ea-a866-00163e046b75:2-9' --exclude-gtids='8993a5f5-2921-11ea-a866-00163e046b75:7' mysql-bin.000002 mysql-bin.000003 > /usr/local/mysql/gtid.sql

恢復操作和之前是一樣的

mysql> set sql_log_bin = 0;    -- 關閉binlog日誌
mysql> source /usr/local/mysql/gtid.sql;     -- 匯入sql指令碼(通過binlog截取出來的)
mysql> set sql_log_bin = 1;    -- 開啟binlog日誌

上述操作你會發現恢復不了資料,那是為什麼呢?

重點:GTID的冪等性:開啟GTID後,MySQL恢復Binlog時,重複GTID的事務不會再執行。 那要如何處理呢?

擷取日誌的時候過濾掉gtid 需要在擷取命令中加入引數 --skip-gtids。

mysqlbinlog --skip-gtids --include-gtids='8993a5f5-2921-11ea-a866-00163e046b75:2-9' --exclude-gtids='8993a5f5-2921-11ea-a866-00163e046b75:7' mysql-bin.000002 mysql-bin.000003 > /usr/local/mysql/gtid.sql

小結:binlog 重要性不言而喻,後續真正備份恢復中也需要binlog日誌,才能達到真正的恢復如初。

Slow Log

作用:記錄慢SQL語句的日誌,定位低效SQL語句的工具日誌,預設不開啟。

配置:

mysql> select @@slow_query_log;   -- 控制慢日誌是否開啟的開關0:不開啟,1:開啟

mysql> select @@slow_query_log_file;   -- 慢日誌存放的位置

mysql> select @@long_query_time;       --設定時間規則執行多少時間算慢。

mysql> select @@log_queries_not_using_indexes;   -- 開啟是否記錄不走索引的語句,0:關,1:開

案例:準備100萬資料量的表。然後執行查詢語句,然後檢視日誌

當你日誌龐大的時候,你會發現vi 看不方便,mysql給我們提供了方便看這個資訊的命令:

mysqldumpslow -s c -t 5 /usr/local/mysql/mysql-5.7.22-linux-glibc2.12-x86_64/data/iZm5e5v2zi93osbr5z21fvZ-slow.log -- c 表示數量,-t 5 顯示前5條。

擴充套件可以實現:更加方便的展示slowlog日誌資訊。

Anemometer基於pt-query-digest將MySQL慢查詢視覺化。

總結

會看MySQL日誌是非常重要的,並且MySQL提供的日誌非常重要,我們需要能夠理解日誌原理,更好為MySQL的資料安全,效能提供幫助。