MySQL日志功能詳解
作者:尹正傑
版權聲明:原創作品,謝絕轉載!否則將追究法律責任。
一.查詢日志
它是用來保存所有跟查詢相關的日志,這種日志類型默認是關閉狀態的,因為MySQL的用戶有很多,如果將每個用戶的查詢操作都記錄下來的話,對服務器的資源開銷也是一件令人煩惱的事情。
查詢日志常見的幾個參數:
1 mysql> show global variables like 'log'; #查看是否記錄所有語句的日志信息於一般查詢日志文件(general_log),默認是關閉狀態。 2 +---------------+-------+ 3 | Variable_name | Value | 4 +---------------+-------+ 5 | log | OFF | 6 +---------------+-------+ 7 1 row in set (0.00 sec) 8 9 mysql> show global variables like 'log_output'; #它有三個值,即{TABLE|FILE|NONE},分別表示記錄在表中(table),文件(file)中或是不記錄(none)。注意,只有og_output的值等於 FILE時,general_log_file的參數才會有意義。且 table和file 可以同時出現,用逗號分隔即可 10 +---------------+-------+ 11 | Variable_name | Value | 12 +---------------+-------+ 13 | log_output | FILE | 14 +---------------+-------+ 15 1 row in set (0.00 sec) 16 17 mysql> show global variables like 'general_log'; #查看是否啟用查詢日志功能 18 +---------------+-------+ 19 | Variable_name | Value | 20 +---------------+-------+ 21 | general_log | OFF | 22 +---------------+-------+ 23 1 row in set (0.00 sec) 24 25 mysql> show global variables like 'general_log_file'; #定義了一般查詢日志保存的文件 26 +------------------+----------------------------+ 27 | Variable_name | Value | 28 +------------------+----------------------------+ 29 | general_log_file | /var/run/mysqld/mysqld.log | 30 +------------------+----------------------------+ 31 1 row in set (0.00 sec) 32 33 mysql>

1 mysql> set global log='on'; 2 Query OK, 0 rows affected, 1 warning (0.00 sec) 3 4 mysql> set global log_file='on'; 5 ERROR 1193 (HY000): Unknown system variable 'log_file' 6 mysql> 7 mysql> set global log_output='table'; 8 Query OK, 0 rows affected (0.00 sec) 9 10 mysql> show tables from mysql; 11 +---------------------------+ 12 | Tables_in_mysql | 13 +---------------------------+ 14 | columns_priv | 15 | db | 16 | event | 17 | func | 18 | general_log | 19 | help_category | 20 | help_keyword | 21 | help_relation | 22 | help_topic | 23 | host | 24 | ndb_binlog_index | 25 | plugin | 26 | proc | 27 | procs_priv | 28 | servers | 29 | slow_log | 30 | tables_priv | 31 | time_zone | 32 | time_zone_leap_second | 33 | time_zone_name | 34 | time_zone_transition | 35 | time_zone_transition_type | 36 | user | 37 +---------------------------+ 38 23 rows in set (0.05 sec) 39 40 mysql> select * from mysql.genral_log; 41 ERROR 1146 (42S02): Table 'mysql.genral_log' doesn't exist 42 mysql> 43 mysql> 44 mysql> 45 mysql> select * from mysql.general_log; 46 +---------------------+---------------------------+-----------+-----------+--------------+---------------------------------+ 47 | event_time | user_host | thread_id | server_id | command_type | argument | 48 +---------------------+---------------------------+-----------+-----------+--------------+---------------------------------+ 49 | 2017-11-23 07:15:45 | root[root] @ localhost [] | 34 | 0 | Query | show tables from mysql | 50 | 2017-11-23 07:16:10 | root[root] @ localhost [] | 34 | 0 | Query | select * from mysql.genral_log | 51 | 2017-11-23 07:16:49 | root[root] @ localhost [] | 34 | 0 | Query | select * from mysql.general_log | 52 +---------------------+---------------------------+-----------+-----------+--------------+---------------------------------+ 53 3 rows in set (0.00 sec) 54 55 mysql>
二.慢查詢日志
查詢執行時長超過指定時長的查詢,即為慢查詢。這里的慢不一定是查詢語句存在問題,可能是因為訪問你的資源當時不被許可訪問,就好比你將一個一個MySQL庫中的一個表添加寫鎖,那么別人就沒有辦法去查詢這個表的內容啦,等到你將這個表鎖解開之后,訪問這張表的查詢語句才會被執行。
慢查詢日志是我們通常拿來定位系統上查詢操作執行速度過慢時常用到的一個評估工具,所以在生產環境中很有必要啟用慢查詢日志功能的喲!它默認情況下也是沒有啟用的喲。慢查詢常見的幾個參數:
1 mysql> show global variables like 'slow_query_log'; #是否啟用慢查詢日志,它的輸出位置也取決log_output={table|file|none}。 2 +----------------+-------+ 3 | Variable_name | Value | 4 +----------------+-------+ 5 | slow_query_log | OFF | 6 +----------------+-------+ 7 1 row in set (0.01 sec) 8 9 mysql> show global variables like 'slow_query_log_file'; #查看定義慢查詢日志的文件 10 +---------------------+---------------------------------+ 11 | Variable_name | Value | 12 +---------------------+---------------------------------+ 13 | slow_query_log_file | /var/run/mysqld/mysqld-slow.log | 14 +---------------------+---------------------------------+ 15 1 row in set (0.02 sec) 16 17 mysql> show global variables like 'long_query_time'; #慢查詢的時長,超出這個時長的都被記錄為慢查詢。 18 +-----------------+-----------+ 19 | Variable_name | Value | 20 +-----------------+-----------+ 21 | long_query_time | 10.000000 | 22 +-----------------+-----------+ 23 1 row in set (0.00 sec) 24 25 mysql>

1 mysql> show global variables like 'slow_query_log'; 2 +----------------+-------+ 3 | Variable_name | Value | 4 +----------------+-------+ 5 | slow_query_log | OFF | 6 +----------------+-------+ 7 1 row in set (0.00 sec) 8 9 mysql> set global slow_query_log=1; 10 Query OK, 0 rows affected (0.00 sec) 11 12 mysql> set global log_output='FILE,TABLE'; 13 Query OK, 0 rows affected (0.00 sec) 14 15 mysql> show global variables like 'slow_query_log'; 16 +----------------+-------+ 17 | Variable_name | Value | 18 +----------------+-------+ 19 | slow_query_log | ON | 20 +----------------+-------+ 21 1 row in set (0.00 sec) 22 23 mysql> show global variables like 'log_output'; 24 +---------------+------------+ 25 | Variable_name | Value | 26 +---------------+------------+ 27 | log_output | FILE,TABLE | 28 +---------------+------------+ 29 1 row in set (0.00 sec) 30 31 mysql> select database(); 32 +------------+ 33 | database() | 34 +------------+ 35 | NULL | 36 +------------+ 37 1 row in set (0.00 sec) 38 39 mysql> use yinzhengjie 40 Reading table information for completion of table and column names 41 You can turn off this feature to get a quicker startup with -A 42 43 Database changed 44 mysql> show tables; 45 +-----------------------+ 46 | Tables_in_yinzhengjie | 47 +-----------------------+ 48 | Classes | 49 | students | 50 | tearchers | 51 +-----------------------+ 52 3 rows in set (0.00 sec) 53 54 mysql> lock tables students write; 55 Query OK, 0 rows affected (0.00 sec) 56 57 mysql> select * from mysql.general_log; 58 ERROR 1100 (HY000): Table 'general_log' was not locked with LOCK TABLES 59 mysql> unlock tables; 60 Query OK, 0 rows affected (0.00 sec) 61 62 mysql> select * from mysql.general_log; 63 +---------------------+---------------------------------------------+-----------+-----------+--------------+--------------------------------------------------+ 64 | event_time | user_host | thread_id | server_id | command_type | argument | 65 +---------------------+---------------------------------------------+-----------+-----------+--------------+--------------------------------------------------+ 66 | 2017-11-23 07:15:45 | root[root] @ localhost [] | 34 | 0 | Query | show tables from mysql | 67 | 2017-11-23 07:16:10 | root[root] @ localhost [] | 34 | 0 | Query | select * from mysql.genral_log | 68 | 2017-11-23 07:16:49 | root[root] @ localhost [] | 34 | 0 | Query | select * from mysql.general_log | 69 | 2017-11-23 07:17:11 | yzj[yzj] @ www.yinzhengjie.com [10.0.0.115] | 31 | 0 | Quit | | 70 | 2017-11-23 07:18:36 | root[root] @ localhost [] | 34 | 0 | Quit | | 71 | 2017-11-23 07:18:45 | root[root] @ localhost [] | 35 | 0 | Connect | root@localhost on | 72 | 2017-11-23 07:18:45 | root[root] @ localhost [] | 35 | 0 | Query | select @@version_comment limit 1 | 73 | 2017-11-23 07:19:56 | root[root] @ localhost [] | 35 | 0 | Query | show global variables like 'slow_query_log' | 74 | 2017-11-23 07:20:11 | root[root] @ localhost [] | 35 | 0 | Query | show global variables like 'slow_query_log_file' | 75 | 2017-11-23 07:20:26 | root[root] @ localhost [] | 35 | 0 | Query | show global variables like 'long_query_time' | 76 | 2017-11-23 07:20:38 | root[root] @ localhost [] | 35 | 0 | Query | show global variables like 'long_slow_filter' | 77 | 2017-11-23 07:24:50 | root[root] @ localhost [] | 35 | 0 | Query | show global variables like 'slow_query_log' | 78 | 2017-11-23 07:24:55 | root[root] @ localhost [] | 35 | 0 | Query | set global slow_query_log=1 | 79 | 2017-11-23 07:25:57 | root[root] @ localhost [] | 35 | 0 | Query | set global log_output='FILE,TABLE' | 80 | 2017-11-23 07:26:10 | root[root] @ localhost [] | 35 | 0 | Query | show global variables like 'slow_query_log' | 81 | 2017-11-23 07:26:21 | root[root] @ localhost [] | 35 | 0 | Query | show global variables like 'log_output' | 82 | 2017-11-23 07:27:09 | root[root] @ localhost [] | 35 | 0 | Query | select database() | 83 | 2017-11-23 07:27:14 | root[root] @ localhost [] | 35 | 0 | Query | SELECT DATABASE() | 84 | 2017-11-23 07:27:14 | root[root] @ localhost [] | 35 | 0 | Init DB | yinzhengjie | 85 | 2017-11-23 07:27:14 | root[root] @ localhost [] | 35 | 0 | Query | show databases | 86 | 2017-11-23 07:27:14 | root[root] @ localhost [] | 35 | 0 | Query | show tables | 87 | 2017-11-23 07:27:14 | root[root] @ localhost [] | 35 | 0 | Field List | Classes | 88 | 2017-11-23 07:27:14 | root[root] @ localhost [] | 35 | 0 | Field List | students | 89 | 2017-11-23 07:27:14 | root[root] @ localhost [] | 35 | 0 | Field List | tearchers | 90 | 2017-11-23 07:27:27 | root[root] @ localhost [] | 35 | 0 | Query | show tables | 91 | 2017-11-23 07:27:41 | root[root] @ localhost [] | 35 | 0 | Query | lock tables students write | 92 | 2017-11-23 07:28:00 | root[root] @ localhost [] | 36 | 0 | Connect | root@localhost on | 93 | 2017-11-23 07:28:00 | root[root] @ localhost [] | 36 | 0 | Query | select @@version_comment limit 1 | 94 | 2017-11-23 07:28:10 | root[root] @ localhost [] | 36 | 0 | Query | select * from yinzhengjie.students | 95 | 2017-11-23 07:29:28 | root[root] @ localhost [] | 35 | 0 | Query | select * from mysql.general_log | 96 | 2017-11-23 07:29:53 | root[root] @ localhost [] | 35 | 0 | Query | unlock tables | 97 | 2017-11-23 07:29:55 | root[root] @ localhost [] | 35 | 0 | Query | select * from mysql.general_log | 98 +---------------------+---------------------------------------------+-----------+-----------+--------------+--------------------------------------------------+ 99 32 rows in set (0.00 sec) 100 101 mysql>
三.錯誤日志
顧名思義,這是用來記錄錯誤的日志,但是不僅僅是記錄錯誤信息,還包括MySQL啟動,關閉,復制線程(指的是從服務器)的信息喲。錯誤日志默認是開啟的。它主要記錄的信息如下:
1>.服務器啟動和關閉過程中的信息;
2>.服務器運行過程中的錯誤信息
3>.事件調度器運行一個事件時產生的信息
4>.在復制架構中的從服務器上啟動從服務器線程時產生的信息
常見參數如下:
1 mysql> show global variables like 'log_error'; #指定錯誤日志文件位置。 2 +---------------+---------------------+ 3 | Variable_name | Value | 4 +---------------+---------------------+ 5 | log_error | /var/log/mysqld.log | 6 +---------------+---------------------+ 7 1 row in set (0.00 sec) 8 9 mysql> 10 mysql> show global variables like 'log_warnings'; #是否將經過日志也記錄在錯誤日志文件中去。 11 +---------------+-------+ 12 | Variable_name | Value | 13 +---------------+-------+ 14 | log_warnings | 1 | 15 +---------------+-------+ 16 1 row in set (0.00 sec) 17 18 mysql>
四.二進制日志
1>.什么是二進制文件
只記錄修改相關的操作,記錄了當前服務器的數據修改和有潛在可能性影響數據修改的語句。它用來實現復制的基本憑據。也就是說,你可以將生成環境中的MySQL的二進制文件拿到線下的服務器上運行一下,理論上你會拿到和生成環境中一樣的數據喲,因此,二進制日志也叫復制日志。二進制日志文件默認在數據目錄下,通常情況下為mysql-bin#(例如:mysql-bin.000001,mysql-bin000002)。
2>.查看MySQL日志文件
由於二進制文件格式是二進制類型的,我們不能用cat等查看普通文本類命令去查看這些二進制日志,我們可以通過mysqlbinlog來查看。注意“show master status; ”查看當前使用的二進制日志和下一個事件開始時的基於的位置。
1 MariaDB [(none)]> show binlog events\G #查看mysql的日志 2 *************************** 1. row *************************** 3 Log_name: mysql-bin.000001 4 Pos: 4 5 Event_type: Format_desc #事件類型 6 Server_id: 1 #指定服務器的唯一標識。 7 End_log_pos: 245 8 Info: Server ver: 5.5.36-MariaDB-log, Binlog ver: 4
3>.日志滾動
為了避免一個文件過大,我們可以適當的將文件的內容分開存儲,這就是日志滾動,比如:當超過1G,日志會滾動。當然,你也可以按照文件大小自定義, 時間定義。想要手動滾動日志,執行“flush logs;”即可。
4>.查看當前正在使用的log日志
1 MariaDB [(none)]> show binary logs; 2 +------------------+-----------+ 3 | Log_name | File_size | 4 +------------------+-----------+ 5 | mysql-bin.000001 | 1043 | 6 | mysql-bin.000002 | 245 | 7 +------------------+-----------+ 8 2 rows in set (0.00 sec)
5>.二進制的主要兩個功能是:
時間點恢復;(它的功能不亞於事務日志喲!)
復制;
6>.清除日志
不要手動去刪除,而是用專業的工具去干這件事情,即purge工具
1 mysql> help PURGE 2 Name: 'PURGE BINARY LOGS' 3 Description: 4 Syntax: 5 PURGE { BINARY | MASTER } LOGS 6 { TO 'log_name' | BEFORE datetime_expr (某個時間之前) } 7 mysql>
7>.Mysql 記錄二進制日志的格式
基於語句(statement):
只把語句服務器執行的SQL語句記錄下來,但是可能存在不精准的情況。例如:“INSERT INTO t1 value(current_date())”,明銳的你可能發現有"current_date()"這個參數,如果從服務器執行了想用的語句,如果存在網絡延遲的情況,就會導致主從同步存在誤差!
基於行(row):
可以更精確的記錄數據,但是會面臨記錄的數據量過大的情況,可能一個語句的操作,匹配了1w多行,那么這1w多行數據的修改都會記錄在這個二進制文件中去的。
混合模式(mixed):
既有了statement的模型,也用了mixed的特點。這種模式據反映不是很好,建議還是用基於行的模式,因為它能夠保證數據更加精確,換來更加精確的同時,可能對你的存儲空間和I/O的使用率會有所提高喲。
8>.指定從那個位置開始讀取
1 mysqlbinlog的常用的[options]: 2 a>--start-time #起始時間 3 b>.--stop-time #結束時間 4 c>.--start-position #基於起始位置來顯示信息 5 d>.--stop-position #指定結束位置來顯示 6 命令行查詢方式如下(可以將讀取的內容保存下來,在另一台服務器上可以情景再現): 7 [root@yinzhengjie ~]# mysqlbinlog --start-position=153 mysql-bin.000001 >/yinzhengjie/backup.sql 8 SQL命令查詢方法如下: 9 MariaDB [(none)]> show binlog events in 'mysql-bin.000001' from 153\G
9>.二進制日志文件內容格式
1 事件發生的日期和時間(會在關鍵字“at”) 2 服務器ID(server id) 3 事件結束位置(end_log_pos) 4 事件的類型(如:Query,Stop等等) 5 原服務器生成此事件時的線程ID號(thead_id,可以通過“show processlist;”進行查詢) 6 語句時間戳和寫入二進制文件的時間差,單位為秒(exec_time,表示記錄日志所用的時間戳,當他等於0時表示沒有用到1秒鍾。) 7 錯誤代碼,0表示正常執行(error_code,排查方法就得查看官方文檔。) 8 事件內容(修改的SQL語句) 9 事件位置(相當於下一事件的開始位置,還是用“at”關鍵字標志)
10>.二進制日志文件常用的相關參數詳解
1 mysql> show global variables like 'log_bin'; #查看是否開啟二進制日志功能,當然我們可以在MySQL的配置文件(my.cnf)中指定文件路徑(如:log_bin=/yinzhengjie/log/mysql-bin); 2 +---------------+-------+ 3 +---------------+-------+ 4 | Variable_name | Value | 5 +---------------+-------+ 6 | log_bin | OFF | 7 +---------------+-------+ 8 1 row in set (0.01 sec) 9 10 mysql> 11 mysql> show global variables like 'log_bin_trust_function_creators'; #不阻止任何存儲函數,存在一定風險,默認關閉即可; 12 +---------------------------------+-------+ 13 | Variable_name | Value | 14 +---------------------------------+-------+ 15 | log_bin_trust_function_creators | OFF | 16 +---------------------------------+-------+ 17 1 row in set (0.00 sec) 18 19 mysql> 20 mysql> show global variables like 'sql_log_bin'; #當前會話是否將二進制文件進入進二進制文件,默認為ON; 21 +---------------+-------+ 22 | Variable_name | Value | 23 +---------------+-------+ 24 | sql_log_bin | ON | 25 +---------------+-------+ 26 1 row in set (0.02 sec) 27 28 mysql> 29 mysql> show global variables like 'sql_log_off'; #是否將一般查詢日志記入查詢日志 30 +---------------+-------+ 31 | Variable_name | Value | 32 +---------------+-------+ 33 | sql_log_off | OFF | 34 +---------------+-------+ 35 1 row in set (0.00 sec) 36 37 mysql> 38 mysql> show global variables like 'sync_binlog'; #同步緩沖中的二進制到硬盤的時間,0不基於時間同步,只在事件提交時同步 39 +---------------+-------+ 40 | Variable_name | Value | 41 +---------------+-------+ 42 | sync_binlog | 0 | 43 +---------------+-------+ 44 1 row in set (0.00 sec) 45 46 mysql> 47 mysql> show global variables like 'binlog_format'; #指定記錄二進制日志的格式 有三種格式:基於語句(statement),基於行(row),混合模式(mixed) 48 49 +---------------+-----------+ 50 | Variable_name | Value | 51 +---------------+-----------+ 52 | binlog_format | STATEMENT | 53 +---------------+-----------+ 54 1 row in set (0.00 sec) 55 56 mysql> 57 mysql> show global variables like 'max_binlog_cache_size'; #mysql二進制日志的緩沖區大小,僅用於緩存事務類的語句 58 +-----------------------+----------------------+ 59 | Variable_name | Value | 60 +-----------------------+----------------------+ 61 | max_binlog_cache_size | 18446744073709547520 | 62 +-----------------------+----------------------+ 63 1 row in set (0.01 sec) 64 65 mysql> 66 mysql> show global variables like 'max_binlog_size'; #二進制日志文件的上限,單位為字節 67 +-----------------+------------+ 68 | Variable_name | Value | 69 +-----------------+------------+ 70 | max_binlog_size | 1073741824 | 71 +-----------------+------------+ 72 1 row in set (0.00 sec) 73 74 mysql>
友情提示:
MySQL的很多默認設置並不適合生成環境,我們需要調整很多東西。給出兩點提示:
a>.切勿將二進制日志與數據文件放在同一設備;
b>.可以臨時通過sql_log_bin來控制二進制的寫入;
五.中繼日志
1 從服務器上的二進制日志。說白了中繼日志其實就是從主服務器上的二進制日志中取數據,然后寫入中級之日里面,在從服務器上,執行中繼日志的sql信息,這樣從服務器就會得到和主服務器一樣的內容,與此同時每次執行之后從服務器的二進制日志也會記錄,聰明的你可能也會想到,這個從服務器的二進制日志內容應該是和主服務器是一致的,所以我們通常采取的操作就是將從服務器的二進制日志關閉掉。 2 對於非從服務器的中繼日志並沒有啟用,可能會用到以下兩個參數: 3 relay_log_purge = {ON|OFF} # 是否自動清理不在需要的中繼日志 4 relay_log_space_limit #中繼(空間)大小是否限制
六.事務日志.
1 先暫存事物提交的數據而后在同步到數據文件中去的一種日志。它的主要目的是將隨機I/O轉換為順序I/O並保證事物的兼容性的。(順序I/O是早期提升寫入的速度一個不錯的解決方案,它比隨機I/O的性能可能會高出100倍呢!不過后來固態硬盤的出現順序I/O起到的作用就不是很明顯啦。) 2 事務日志我們也稱之為日志文件組,它至少要存在兩個日志文件以實現輪詢。我們知道,MySQL的innodb是支持事物的,當啟動一個事務時,修改的數據是存儲在innodb的緩存(innodb_buffer)中的,當這個緩存存儲不下之后,它就會將數據寫入到日志文件組(事務日志)中的一個文件,當其中的一個文件寫滿之后,又開始寫第二個文件,與此同時,第一個文件的內容開始網磁盤中寫,已達事務持久化的特性之一。這也就意味着當事務回滾時,很可能會將已經寫入磁盤中的數據進行刪除操作,這樣性能就會降低,而如果事務較小的話,也就不會存在將數據寫入到磁盤中,甚至不用寫入事務日志中,直接在innodb的緩存中就將問題解決,因此,盡可能使用小事務來替代大事務來提升事務引擎的性能。 3
友情提示:
當存儲事務日志的磁盤壞掉是,數據是無法恢復的喲!因此選擇一個可靠的磁盤還是相當有必要的,比如我們可以給我們的數據做raid10或者raid1(推薦使用raid10)來提供這種保障。事務日志不能幫助我們恢復數據,它的作用在於當操作系統崩潰時(比如異常斷電)它能夠保障已經提交的事物不丟失,而未提交的事物能回滾。如果想要恢復日志還得依賴於二進制日志。