MySql-日誌詳解

錯誤日誌
MySQL的錯誤信息是在data目錄下的
錯誤日誌本身所定義的內容本身是可以定義的
編輯配置文件,定義錯誤日誌:

log-error=/path/to/xx.err   #定義是否啓動錯誤日誌的功能
log-warnings={1|0}              #定義是否將警告信息也記錄在錯誤日誌中

默認情況下錯誤日誌也記錄以下幾個方面的消息:
1、服務器啓動和關閉過程中的信息
未必是錯誤信息,比如mysql是如何去初始化存儲引擎的過程記錄在錯誤日誌裏等等

2、服務器運行過程中的錯誤信息
比如sock文件找不到,無法加載mysql數據庫的數據文件,如果忘記初始化mysql或data dir路徑找不到,或權限不正確等,都會記錄在此

3、事件調度器運行一個事件時產生的信息
一旦mysql調度啓動一個計劃任務的時候,它也會將相關信息記錄在錯誤日誌中

4、在從服務器上啓動從服務器進程時產生的信息
在複製環境下,從服務器進程的信息也會被記錄進錯誤日

一般情況下錯誤日誌不會特別大,可以放心安全的開啓,對於診斷服務器故障或問題也是非常有幫助的

如何定義mysql服務器錯誤日誌相關功能

mysql> show global variables like '%log%';
| log_error                               |/mydata/data/localhost.err         |
| log_warnings                            | 1                                 |
log_error={1 | 0 | /PATH/TO/ERROR_LOG_FILENAME}
log_warnings = {1|0}

eg,

[root@localhostdata]# tail -20 localhost.err
140331 14:32:02[Note] /usr/local/mysql/bin/mysqld: Shutdown complete

140331 14:32:02mysqld_safe mysqld from pid file /mydata/data/localhost.pid ended
140331 14:32:02mysqld_safe Starting mysqld daemon with databases from /mydata/data
140331 14:32:03[Note] Plugin 'FEDERATED' is disabled.                              #初始化存儲引擎
140331 14:32:03InnoDB: The InnoDB memory heap is disabled                          #innodb禁用了堆功能
140331 14:32:03InnoDB: Mutexes and rw_locks use GCC atomic builtins                #互斥量和行級鎖是GCC編制的

140331 14:32:03InnoDB: Compressed tables use zlib 1.2.3
140331 14:32:03InnoDB: Using Linux native AIO
140331 14:32:03InnoDB: Initializing buffer pool, size = 128.0M                     #innodb存儲引擎的緩衝池(buff poll)一般需要改的,而且需要改的特別大,一般8G內存分配給其5G都不足爲過(專用於mysql場景)
因此可以觀察此文件來觀察緩衝池到底佔用多少內存

140331 14:32:03InnoDB: Completed initialization of buffer pool
140331 14:32:03InnoDB: highest supported file format is Barracuda.
140331 14:32:03  InnoDB: Waiting for the background threads tostart
140331 14:32:04InnoDB: 5.5.33 started; log sequence number 2856278
140331 14:32:04[Note] Server hostname (bind-address): '0.0.0.0'; port: 3306        #服務已經運行並監聽在本地0.0.0.0的 3306端口
140331 14:32:04[Note]   - '0.0.0.0' resolves to'0.0.0.0';                         #0.0.0.0反解失敗
140331 14:32:04[Note] Server socket created on IP: '0.0.0.0'.
140331 14:32:04[Note] Event Scheduler: Loaded 0 events                             #時間調度器沒有進行任何調度
140331 14:32:04[Note] /usr/local/mysql/bin/mysqld: ready for connections.
Version:'5.5.33-log'  socket:'/tmp/mysql.sock'  port: 3306  MySQL Community Server (GPL)   #mysql已經啓動並在/tmp/目錄下生成mysql.sock文件

查詢日誌
查詢日誌一般情況下mysql是沒有啓用的,因爲mysql本身爲關係型數據庫,用戶連接進數據庫的時候,用戶的一切行爲 增刪查改 都會生成查詢日誌
insert查詢爲了避免數據衝突,如果此前插入過數據,而如果跟主鍵或唯一鍵的數據重複那肯定會報錯
update時也會查詢因爲更新的時候很可能會更新某一塊數據
delete查詢,只刪除符合條件的數據
因此都會產生日誌,在併發操作非常多的場景下,查詢信息會非常多,那麼如果都記錄下來會導致IO非常大 影響mysql性能,因此如果不是在調試環境下,是不建議開啓查詢日誌功能的

設置
編輯 my.cnf,修改 general-log 參數爲 1,同時設定 log-output 參數(日誌輸出類型)和 general_log_file 參數(查詢日誌路徑):

log-output=FILE
general-log=1
general_log_file="filename.log"

慢查詢日誌
慢查詢日誌中記錄了市場,明確說明了哪個時間段執行和結束,中間執行了多長時間
對於非常繁忙的服務器,如果中途出現了查詢速度非常慢的場景中,通常需要啓動慢查詢日誌功能,慢查詢日誌對性能的影響微乎其微,但是可以詳細記錄了服務器上的慢查詢,因此可以去定位服務器的瓶頸

設置
編輯 my.cnf ,設置 log_slow_queries 參數爲 1,同時設定 log-output 參數(日誌輸出類型)、slow-query-log_file 參數(慢查詢日誌路徑)和 long_query_time 參數:

log-output=FILE
log_slow_queries=1    //MySQL 5.6將此參數修改爲了slow_query_log
slow_query_log_file="filename.log"
long_query_time=10    //慢查的時長單位爲秒,可以精確到小數點後6位(微秒)

eg,

開啓慢查詢
mysql> setglobal slow_query_log=1;
Query OK, 0 rowsaffected (0.17 sec)

mysql> showglobal variables like '%slow_qu%';
+---------------------+---------------------------------+
|Variable_name       | Value                           |
+---------------------+---------------------------------+
|log_slow_queries    | ON                              |
|slow_query_log      | ON                              |
|slow_query_log_file | /mydata/data/localhost-slow.log |
+---------------------+---------------------------------+
3 rows in set (0.00sec)

設置慢查詢時間
mysql> setglobal long_query_time=0.000001;
Query OK, 0 rowsaffected (0.00 sec)

新建會話,並進行簡單操作
[root@localhost ~]#mysql
mysql> showdatabases;
mysql> usetest1;
mysql> showtables;

由於調整的時間間隔極小,所以mysql認爲每個操作都是慢查詢,都一一記錄了我們的操作過程,如下所示:
[root@localhost data]#tail -F localhost-slow.log
# Time: 14033115:50:21
# User@Host:root[root] @ localhost []
# Query_time:0.000093  Lock_time: 0.000000 Rows_sent:1  Rows_examined: 0
SETtimestamp=1396252221;
select@@version_comment limit 1;
# Time: 14033115:50:28
# User@Host:root[root] @ localhost []
# Query_time:0.030523  Lock_time: 0.029807 Rows_sent:10  Rows_examined: 10
SETtimestamp=1396252228;
show databases;
# Time: 14033115:50:59
# User@Host:root[root] @ localhost []
# Query_time:0.000084  Lock_time: 0.000000 Rows_sent:1  Rows_examined: 0
SETtimestamp=1396252259;
SELECT DATABASE();
# User@Host:root[root] @ localhost []
# Query_time:0.000029  Lock_time: 0.000000 Rows_sent:1  Rows_examined: 0
use test1;
SETtimestamp=1396252259;
# administrator command:Init DB;
# Time: 14033115:51:22
# User@Host:root[root] @ localhost []
# Query_time:0.000290  Lock_time: 0.000087 Rows_sent:1  Rows_examined: 1
SETtimestamp=1396252282;
show tables;
我們在數據庫進行了4次操作,都一一被記錄到日誌裏
[root@localhostdata]# grep 'Time' localhost-slow.log  |wc -l        
4

如果服務器非常繁忙,經常會產生慢查詢的話,那麼日誌量會非常大,那麼需要手工去設置日誌滾動功能

關閉慢查詢日誌

log-output=NONE
log_slow_queries=0   //MySQL 5.6將此參數修改爲了slow_query_log
slow_query_log_file="filename.log"
long_query_time=10

二進制日誌 (binlog)
二進制日誌記錄 MySQL 數據庫中所有與更新相關的操作,即二進制日誌記錄了所有的 DDL(數據定義語言)語句和 DML(數據操縱語言)語句,但是不包括數據查詢語句。常用於恢復數據庫和主從複製。

查看 log_bin 狀態

mysql> SHOW VARIABLES LIKE 'log_bin%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| log_bin                         | OFF   |
| log_bin_basename                |       |
| log_bin_index                   |       |
| log_bin_trust_function_creators | OFF   |
| log_bin_use_v1_row_events       | OFF   |
+---------------------------------+-------+

啓用二進制日誌功能

log-bin="filename-bin"

設定二進制日誌文件上限,單位爲字節,最小值爲4K,最大值爲1G,默認爲1G。某事務所產生的日誌信息只能寫入一個二進制日誌文件,因此,實際上的二進制日誌文件可能大於這個指定的上限。作用範圍爲全局級別,可用於配置文件,屬動態變量。

max_binlog_size={4096 .. 1073741824} ;

查看所有的二進制文件

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |    276665 |
+------------------+-----------+
1 row in set (0.03 sec)

查看當前正在使用的二進制文件

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      107 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

二進制日誌滾動
當 MySQL 服務進程啓動、當前二進制日誌文件的大小已經超過上限時、執行 FLUSH LOG 時,MySQL 會創建一個新的二進制日誌文件。新的編號大1的日誌用於記錄最新的日誌,而原日誌名字不會被改變。

手動滾動命令:flush logs;

定義二進制格式日誌
binlog_format= Mixed|Statement|Row

二進制日誌的有效天數
expire_logs_days = 5

實時將緩存中數據同步到硬盤中
sync_binlog
sync_binlog 的默認值是0,像操作系統刷其他文件的機制一樣,MySQL不會同步到磁盤中去而是依賴操作系統來刷新binary log。
當sync_binlog =N (N>0) ,MySQL 在每寫 N次 二進制日誌binary log時,會使用fdatasync()函數將它的寫二進制日誌binary log同步到磁盤中去。

(如果啓用了autocommit,那麼每一個語句statement就會有一次寫操作;否則每個事務對應一個寫操作)

在MySQL中系統默認的設置是sync_binlog=0,也就是不做任何強制性的磁盤刷新指令,這時候的性能是最好的,但是風險也是最大的。因爲一旦系統Crash,在binlog_cache中的所有binlog信息都會被丟失。而當設置爲“1”的時候,是最安全但是性能損耗最大的設置。因爲當設置爲1的時候,即使系統Crash,也最多丟失binlog_cache中未完成的一個事務,對實際數據沒有任何實質性影響。從以往經驗和相關測試來看,對於高併發事務的系統來說,“sync_binlog”設置爲0和設置爲1的系統寫入性能差距可能高達5倍甚至更多。

清除二進制日誌
清除所有日誌(不存在主從複製關係)

mysql> RESET MASTER;

清除指定日誌之前的所有日誌

mysql> PURGE MASTER LOGS TO 'mysql-bin.000003';

清除某一時間點前的所有日誌

mysql> PURGE MASTER LOGS BEFORE '2015-01-01 00:00:00';

清除 n 天前的所有日誌

mysql> PURGE MASTER LOGS BEFORE CURRENT_DATE - INTERVAL 10 DAY;

由於二進制日誌的重要性,請僅在確定不再需要將要被刪除的二進制文件,或者在已經對二進制日誌文件進行歸檔備份,或者已經進行數據庫備份的情況下,才進行刪除操作,且不要使用 rm 命令刪除。

清除二進制日誌的最佳實踐
清除之前必須將日誌文件備份,備份完畢後再次確認,如果確實可以刪除則使用以上命令進行刪除
假設binglog備份文件已經備份到日誌服務器中,當前本地的數據庫日誌已經確保無誤可以刪除

備份
[root@localhostdata]# cp mysql-bin.0000* /tmp/
備份數據庫
mysqldump-u root -p'123456' -A > /tmp/bak.sql
接下來就可以清除無用的日誌了
[root@localhost data]# tail -5 mysql-bin.index
./mysql-bin.000056
./mysql-bin.000057
./mysql-bin.000058
./mysql-bin.000059
./mysql-bin.000060
刪除000056之前的二進制文件
mysql>purge binary logs to 'mysql-bin.000056';
QueryOK, 0 rows affected (0.01 sec)
[root@localhostdata]# cat  mysql-bin.index
./mysql-bin.000056
./mysql-bin.000057
./mysql-bin.000058
./mysql-bin.000059
./mysql-bin.000060
刪除某一事件之前的信息
mysql>show binlog events in 'mysql-bin.000060' limit 10;

查看日誌詳細
1. SHOW BINLOG EVENTS [IN ‘log_name’] [FROM pos] [LIMIT [offset,]row_count]

mysql>show binlog events in 'mysql-bin.000059';
+------------------+-----+-------------+-----------+-------------+-----------------------------------------+
|Log_name         | Pos | Event_type  | Server_id | End_log_pos | Info                                    |
+------------------+-----+-------------+-----------+-------------+-----------------------------------------+
|mysql-bin.000059 |   4 | Format_desc|         1 |         107 | Server ver: 5.5.33-log, Binlogver: 4     |
|mysql-bin.000059 | 107 | Query      |         1 |         192 | create database test2                    |
|mysql-bin.000059 | 192 | Query      |         1 |         281 | use `test2`; create table tb1(id INT)    |
|mysql-bin.000059 | 281 | Query      |         1 |         350 | BEGIN                                    |
|mysql-bin.000059 | 350 | Query      |         1 |         440 | use `test2`; insert into tb1values (1)   |
|mysql-bin.000059 | 440 | Xid        |         1 |         467 | COMMIT /* xid=22 */                      |
+------------------+-----+-------------+-----------+-------------+-----------------------------------------+
6 rowsin set (0.00 sec)

在位置000059中有以下幾個事件:

|mysql-bin.000059 |   4 | Format_desc|         1 |         107 | Server ver: 5.5.33-log, Binlogver: 4   |

在第4個位置開始到第106個位置爲頭部信息
從位置107到191記錄了第一個事件操作createdatabase test2
在位置192開始記錄了第二個操作use test2; create table tb1(id INT)
位置281begin了一個事件
所以每個語句執行結束後都會向日志記錄的,因此如果數據量非常龐大的話會影響性能下降的

也可以明確說明從哪個位置開始
比如從位置192開始並且顯示2行,如下所示:

mysql>show binlog events in 'mysql-bin.000059' from 192 limit 2;
+------------------+-----+------------+-----------+-------------+----------------------------------------+
|Log_name         | Pos | Event_type |Server_id | End_log_pos | Info                                   |
+------------------+-----+------------+-----------+-------------+----------------------------------------+
| mysql-bin.000059| 192 | Query      |         1 |         281 | use `test2`; create table tb1(id INT) |
|mysql-bin.000059 | 281 | Query     |         1 |         350 | BEGIN                                  |
+------------------+-----+------------+-----------+-------------+----------------------------------------+
2 rowsin set (0.00 sec)
  1. 使用mysqlbinlog命令行。
    mysqlbinlog直接在命令行直接去操作二進制文件
    建議對日誌操作之前先將其flush logs 滾動一次再對其進行編輯
    查看二進制日誌內容信息
[root@localhostdata]# mysqlbinlog mysql-bin.000060  |more

文件頭

/*!50530SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019SET @@session.max_insert_delayed_threads=0*/;
/*!50003SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER/*!*/;

初始化版本信息
用戶通過mysql服務器進行通告

# at 4                 #結束的位置
#14033116:07:45 server id 1  end_log_pos 107  Start: binlog v 4, server v 5.5.33-log created140331 16:07:45 at startup
#Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG'
USI5Uw8BAAAAZwAAAGsAAAABAAQANS41LjMzLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAABRIjlTEzgNAAgAEgAEBAQEEgAAVAAEGggAAAAICAgCAA==
'/*!*/;

真正的事件是從107開始的

# at107               #開始處,表明了上一個事件結束的時候開始
#14033116:10:01 server id 1 end_log_pos 177Querythread_id=1exec_time=0error_code=0

server id : 用在複製場景中避免循環複製而設定的,任何服務器只是從其複製讀取非自己服務器的事,#因此每個mysql server都有自己的server id 每個server id 都爲1
end_log_pos 177: 結束的位置,顯示的結束位置是下個事件開始的位置
Query : 查詢語句
thread_id=1: 會話線程創建的語句
exec_time=0 : 執行時長,單位爲秒
error_code=0: 錯誤代碼 0爲沒有錯誤

境預設再下面就是sql語句了

SETTIMESTAMP=1396253401/*!*/;
SET@@session.pseudo_thread_id=1/*!*/;
SET@@session.foreign_key_checks=1, @@session.sql_auto_is_null=0,@@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET@@session.sql_mode=0/*!*/;
SET@@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\Clatin1 *//*!*/;
SET@@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
SET@@session.lc_time_names=0/*!*/;
SET@@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;

到176處結束,並在177位置處開始信的事件

# at177
#14033116:10:01 server id 1  end_log_pos 205  Intvar
SETINSERT_ID=2606/*!*/;
# at205

事務(重做)日誌
事物日誌是innodb專用功能,這裏只考慮innod存儲引擎

出於性能和故障恢復的考慮,MySQL 服務器不會立即執行事務,而是先將事務記錄在日誌裏面,這樣可以將隨機IO轉換成順序IO,從而提高IO性能。

事物日誌默認情況下會有兩個文件,名稱分別爲ib_logfile0和ib_logfile1。當其中一個寫滿時,MySQL會將事務日誌寫入另一個日誌文件(先清空原有內容)。當 MySQL 從崩潰中恢復時,會讀取事務日誌,將其中已經 commit 的事務寫入數據庫,沒有 commit 的事務 rollback 。

在事物提交時,innodb是否將緩衝到文件中同步,只要提交則立刻同步,同時又不會保證每個語句都同步,因此性能不會有特別大的影響

如果innodb_flush_log_at_trx_commit設置爲0,log buffer將每秒一次地寫入log file中,並且log file的flush(刷到磁盤)操作同時進行.該模式下,在事務提交的時候,不會主動觸發寫入磁盤的操作。
如果innodb_flush_log_at_trx_commit設置爲1,每次事務提交時MySQL都會把log buffer的數據寫入log file,並且flush(刷到磁盤)中去.
如果innodb_flush_log_at_trx_commit設置爲2,每次事務提交時MySQL都會把log buffer的數據寫入log file.但是flush(刷到磁盤)操作並不會同時進行。該模式下,MySQL會每秒執行一次 flush(刷到磁盤)操作。

這裏寫圖片描述

|innodb_flush_log_at_trx_commit           |1                 |
|innodb_locks_unsafe_for_binlog           |OFF               |

定義內存空間的大小,萬一都寫在buffer裏面,如果進程崩潰,也會丟失事物,因此避免這種情況,一旦事物提交了,那麼需要立即同步到磁盤中,而不是間斷同步,需要定義以下的參數:

|innodb_log_buffer_size                   |8388608               |

每個日誌的單位大小爲5MB,如果有些大數據的話,則需要將其調大,否則恢復起來會比較慢,但是太大了也會導致恢復比較慢

|innodb_log_file_size                  |5242880             |

在每個組裏面提供2個文件,上面有提到過

|innodb_log_files_in_group               |2                |

定義事物日誌組的位置,一般來講會有2個日誌,一個寫滿後會重建立文件(達到輪詢功能,寫滿後會同步到磁盤並將其清空)一般來講,日誌文件大小是固定的,凡是mysql已啓動日誌空間會在磁盤上立即分配,因爲他們的主要功能是將隨機IO轉爲順序IO ,默認大小是每個文件爲5MB,明確說明事物日誌的路徑保存在./ 表示在當前路徑下

|innodb_log_group_home_dir              |./               |

同一個日誌文件對日誌組做鏡像,當然,需要存放在不同的磁盤上

|innodb_mirrored_log_groups                |1                 |

中繼日誌
中繼日誌用於主從複製架構中的從服務器上,從服務器的 slave 進程從主服務器處獲取二進制日誌的內容並寫入中繼日誌,然後由 IO 進程讀取並執行中繼日誌中的語句。

日誌分析工具
mysqldumpslowmysql:官方提供的慢查詢日誌分析工具
mysqlsla:hackmysql.com 推出的一款日誌分析工具(該網站還維護了 mysqlreport,mysqlidxchk 等比較實用的mysql 工具)。 整體來說,功能非常強大。輸出的數據報表非常有利於分析慢查詢的原因,包括執行頻率、數據量、查詢消耗等。
myprofi:純 php 寫的一個開源分析工具.項目在 sourceforge 上。功能上,列出了總的慢查詢次數和類型、去重後的 sql 語句、執行次數及其佔總的 slow log 數量的百分比。從整體輸出樣式來看,比 mysql-log-filter 還要簡潔,省去了很多不必要的內容。對於只想看 sql 語句及執行次數的用戶來說,比較推薦。
mysql-log-filter:google code 上找到的一個分析工具,提供了 python 和 php 兩種可執行的腳本。 特色功能除了統計信息外,還針對輸出內容做了排版和格式化,保證整體輸出的簡潔。喜歡簡潔報表的朋友,推薦使用一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章