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 两种可执行的脚本。 特色功能除了统计信息外,还针对输出内容做了排版和格式化,保证整体输出的简洁。喜欢简洁报表的朋友,推荐使用一下。

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