网站建设知识
MySql-日志详解
2025-07-22 09:59  点击:0

错误日志
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.err140331 14:32:02[Note] /usr/local/mysql/bin/mysqld: Shutdown complete140331 14:32:02mysqld_safe mysqld from pid file /mydata/data/localhost.pid ended140331 14:32:02mysqld_safe Starting mysqld daemon with databases from /mydata/data140331 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.3140331 14:32:03InnoDB: Using Linux native AIO140331 14:32:03InnoDB: Initializing buffer pool, size = 128.0M                     #innodb存储引擎的缓冲池(buff poll)一般需要改的,而且需要改的特别大,一般8G内存分配给其5G都不足为过(专用于mysql场景)因此可以观察此文件来观察缓冲池到底占用多少内存140331 14:32:03InnoDB: Completed initialization of buffer pool140331 14:32:03InnoDB: highest supported file format is Barracuda.140331 14:32:03  InnoDB: Waiting for the background threads tostart140331 14:32:04InnoDB: 5.5.33 started; log sequence number 2856278140331 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=FILEgeneral-log=1general_log_file="filename.log"

慢查询日志
慢查询日志中记录了市场,明确说明了哪个时间段执行和结束,中间执行了多长时间
对于非常繁忙的服务器,如果中途出现了查询速度非常慢的场景中,通常需要启动慢查询日志功能,慢查询日志对性能的影响微乎其微,但是可以详细记录了服务器上的慢查询,因此可以去定位服务器的瓶颈

设置
编辑 my.cnf ,设置 log_slow_queries 参数为 1,同时设定 log-output 参数(日志输出类型)、slow-query-log_file 参数(慢查询日志路径)和 long_query_time 参数:

log-output=FILElog_slow_queries=1    //MySQL 5.6将此参数修改为了slow_query_logslow_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 ~]#mysqlmysql> 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: 0SETtimestamp=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: 10SETtimestamp=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: 0SETtimestamp=1396252259;SELECT DATAbase();# User@Host:root[root] @ localhost []# Query_time:0.000029  Lock_time: 0.000000 Rows_sent:1  Rows_examined: 0use 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: 1SETtimestamp=1396252282;show tables;我们在数据库进行了4次操作,都一一被记录到日志里[root@localhostdata]# grep 'Time' localhost-slow.log  |wc -l        4

如果服务器非常繁忙,经常会产生慢查询的话,那么日志量会非常大,那么需要手工去设置日志滚动功能

关闭慢查询日志

log-output=NONElog_slow_queries=0   //MySQL 5.6将此参数修改为了slow_query_logslow_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不做fsync之类的磁盘同步指令刷新binlog_cache中的信息到磁盘,而让Filesystem自行决定什么时候来做同步,或者cache满了之后才同步到磁盘。
sync_binlog=n,当每进行n次事务提交之后,MySQL将进行一次fsync之类的磁盘同步指令来将binlog_cache中的数据强制写入磁盘。

在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                       |+------------------+-----+-------------+-----------+-------------+-----------------------------------------+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)
使用mysqlbinlog命令行。
mysqlbinlog直接在命令行直接去操作二进制文件
建议对日志操作之前先将其flush logs 滚动一次再对其进行编辑
查看二进制日志内容信息
[root@localhostdata]# mysqlbinlog mysql-bin.000060  |more

文件头

;;;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'USI5Uw8BAAAAZwAAAGsAAAABAAQANS41LjMzLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRIjlTEzgNAAgAEgAEBAQEEgAAVAAEGggAAAAICAgCAA==';

真正的事件是从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;;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  IntvarSETINSERT_ID=2606;# at205

事务日志
事物日志是innodb专用功能,这里只考虑innod存储引擎

出于性能和故障恢复的考虑,MySQL 服务器不会立即执行事务,而是先将事务记录在日志里面,这样可以将随机IO转换成顺序IO,从而提高IO性能。

事物日志通常是一组至少两个固定大小的文件,当其中一个写满时,MySQL会将事务日志写入另一个日志文件(先清空原有内容)。当 MySQL 从崩溃中恢复时,会读取事务日志,将其中已经 commit 的事务写入数据库,没有 commit 的事务 rollback 。

在事物提交时,innodb是否将缓冲到文件中同步,只要提交则立刻同步,同时又不会保证每个语句都同步,因此性能不会有特别大的影响
1 表示事物提交后同步,一般是每间隔1秒钟同步一次,就算有事物丢失那么最多就丢失1秒钟的数据 ,但是定义为1对mysql的性能影响特别大的,因为不管事物是否提交,每隔1秒钟都会去在同步一次数据,意味着每1秒就消耗一次IO
2一般只有事物提交才同步,尤其是事物量非常大的时候,性能是非常明显的,但是如果出现问题会丢失整个事物

|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 推出的一款日志分析工具(该网站还维护了 mysqlreport,mysqlidxchk 等比较实用的mysql 工具)。 整体来说,功能非常强大。输出的数据报表非常有利于分析慢查询的原因,包括执行频率、数据量、查询消耗等。
myprofi:纯 php 写的一个开源分析工具.项目在 sourceforge 上。功能上,列出了总的慢查询次数和类型、去重后的 sql 语句、执行次数及其占总的 slow log 数量的百分比。从整体输出样式来看,比 mysql-log-filter 还要简洁,省去了很多不必要的内容。对于只想看 sql 语句及执行次数的用户来说,比较推荐。
mysql-log-filter:google code 上找到的一个分析工具,提供了 python 和 php 两种可执行的脚本。 特色功能除了统计信息外,还针对输出内容做了排版和格式化,保证整体输出的简洁。喜欢简洁报表的朋友,推荐使用一下。