MySql(50)MySQL日志

本文详细介绍了MySQL的各种日志类型,包括慢查询日志、通用查询日志、错误日志、二进制日志和中继日志。二进制日志在数据恢复和主从同步中的重要性得到强调,而日志管理涉及到的日志启动、查看、删除和刷新等操作也进行了说明。此外,还讨论了日志对性能的影响和磁盘空间的占用。
摘要由CSDN通过智能技术生成

MySQL支持的日志

日志类型

MySQL有不同类型的日志文件,用来存储不同类型的日志,分为二进制日志、错误日志、通用查询日志和慢查询日志,这也是常用的4种。MySQL 8又新增两种支持的日志:中继日志和数据定义语句日志。使用这些日志文件,可以查看MySQL内部发生的事情。

这6类日志分别为:

  • 慢查询日志:记录所有执行时间超过long_query_time的所有查询,方便对查询进行优化。
  • 通用查询日志:记录所有连接的起始时间和终止时间,以及连接发送给数据库服务器的所有指令,对复原操作的实际场景、发现问题,甚至是对数据库操作的审计都有很大的帮助。
  • 错误日志:记录MySQL服务的启动、运行或停止MySQL服务时出现的问题,方便我们了解服务器的状态,从而从而对服务器进行维护。
  • 二进制日志:记录所有更改数据的语句,可以用于主从服务器之间的数据同步,以及服务器遇到故障时数据的无损失恢复。
  • 中继日志:用于主从服务器架构中,从服务器用来存放主服务器二进制日志内容的一个中间文件。从服务器通过读取中继日志的内容,来同步主服务器上的操作。
  • 数据定义语句日志:记录数据定义语句执行的元数据操作。除二进制日志外,其他日志都是文本文件。默认情况下,所有日志创建于MySQL数据目录中。

日志的弊端

  • 日志功能会降低MySQL数据库的性能。例如,在查询非常频繁的MySQL数据库系统中,如果开启了通用查询日志和慢查询日志,MySQL数据库会花费很多时间记录日志。
  • 日志会占用大量的磁盘空间。对于用户量非常大、操作非常频繁的数据库,日志文件需要的存储空间设置比数据库文件需要的存储空间还要大。

慢查询日志(slow query log)

性能分析工具的使用

通用查询日志

查看当前状态

SHOW VARIABLES LIKE '%general%';
/*
+------------------+------------------------------+
| Variable_name    |           Value   |
+------------------+------------------------------+
| general_log          | OFF                      | #通用查询日志处于关闭状态
| general_log_file | /var/lib/mysql/ttst01.log | #通用查询日志文件的名称是ttst01.log
+------------------+------------------------------+
*/

说明1∶系统变量general_log的值是OFF,即通用查询日志处于关闭状态。在MySQL中,这个参数的默认值是关闭的。因为一旦开启记录通用查询日志,MySQL 会记录所有的连接起止和相关的SQL操作,这样会消耗系统资源并且占用磁盘空间。我们可以通过手动修改变量的值,在需要的时候开启日志。

说明2:通用查询日志文件的名称是atguiguo1.log。存储路径是/var/lib/mysql/,默认也是数据路径。这样我们就知道在哪里可以查看通用查询日志的内容了

启动日志

永久启动

[mysqld]
general_log=ON
general_log_file="/path/filename" #日志文件所在目录路径,filename为日志文件名

如果不指定目录和文件名,通用查询日志将默认存储在MySQL数据目录中的hostname.log文件中,hostname表示主机名。

临时启动

SET GLOBAL general_log=on; # 开启通用查询日志
SET GLOBAL general_log_file=’path/filename’; # 设置日志文件保存位置

查看日志

通用查询日志是以文本文件 的形式存储在文件系统中的,可以使用文本编辑器 直接打开日志文件。每台MySQL服务器的通用查询日志内容是不同的。

/usr/sbin/mysqld, Version: 8.0.26 (MySQL Community Server - GPL). started with:

Tcp port: 3306  Unix socket: /var/lib/mysql/mysql.sock	
Time	Id Command	Argument		
2022-01-04T07:44:58.052890Z	10	Query	SHOW VARIABLES LIKE '%general%'
2022-01-04T07:45:15.666672Z	10	Query	SHOW VARIABLES LIKE 'general_log%'
2022-01-04T07:45:28.970765Z	10	Query	select * from student	
2022-01-04T07:47:38.706804Z	11	Connect	root@localhost on  using Socket
2022-01-04T07:47:38.707435Z	11	Query	select @@version_comment limit 1
2022-01-04T07:48:21.384886Z	12	Connect	root@172.16.210.1 on	using TCP/IP
2022-01-04T07:48:21.385253Z	12	Query	SET NAMES utf8	
2022-01-04T07:48:21.385640Z	12	Query	USE `atguigu12`	
2022-01-04T07:48:21.386179Z	12	Query	SHOW FULL TABLES WHERE Table_Type !=
'VIEW'					
2022-01-04T07:48:23.901778Z	13	Connect	root@172.16.210.1 on	using TCP/IP
2022-01-04T07:48:23.902128Z	13	Query	SET NAMES utf8	
2022-01-04T07:48:23.905179Z	13	Query	USE `atguigu`	
2022-01-04T07:48:23.905825Z	13	Query	SHOW FULL TABLES WHERE Table_Type !=
'VIEW'					
2022-01-04T07:48:32.163833Z	14	Connect	root@172.16.210.1 on	using TCP/IP
2022-01-04T07:48:32.164451Z	14	Query	SET NAMES utf8	
2022-01-04T07:48:32.164840Z	14	Query	USE `atguigu`	
2022-01-04T07:48:40.006687Z	14	Query	select * from account	

在通用查询日志里面,我们可以清楚地看到,什么时候开启了新的客户端登陆数据库,登录之后做了什么 SQL 操作,针对的是哪个数据表等信息。

删除\刷新日志

如果数据的使用非常频繁,那么通用查询日志会占用服务器非常大的磁盘空间。数据管理员可以删除很长时间之前的查询日志,以保证MySQL服务器上的硬盘空间。

手动删除文件

SHOW VARIABLES LIKE 'general_log%';

可以看出,通用查询日志的目录默认为MySQL数据目录。在该目录下手动删除通用查询日志atguigu01.log。

使用如下命令重新生成查询日志文件,具体命令如下。刷新MySQL数据目录,发现创建了新的日志文件。前提一定要开启通用日志。

mysqladmin -uroot -p flush-logs

如果希望备份旧的通用查询日志,就必须先将旧的日志文件复制出来或者改名,然后执行上面的mysqladmin命令。正确流程如下

cd mysql-data-directory #输入自己的通用日志文件所在目录
mv mysql.general.log mysql.general.log.old #指名就的文件名 以及新的文件名
mysqladmin -uroot -p flush-logs

错误日志(error log)

错误日志记录了MySQL服务器启动、停止运行的时间,以及系统启动、运行和停止过程中的诊断信息,包括错误、警告和提示等。

通过错误日志可以查看系统的运行状态,便于即时发现故障、修复故障。如果MysQL服务出现异常,错误日志是发现问题、解决故障的首选。

在MySQL数据库中,错误日志功能是 默认开启 的。而且,错误日志 无法被禁止 。

删除\刷新日志

对于很久以前的错误日志,数据库管理员查看这些错误日志的可能性不大,可以将这些错误日志删除,以保证MySQL服务器上的 硬盘空间 。MySQL的错误日志是以文本文件的形式存储在文件系统中的,可以直接删除。

install -omysql -gmysql -m0644 /dev/null /var/log/mysqld.log

mysqladmin -uroot -p flush-logs
Enter password:
mysqladmin: refresh failed; error: 'Could not open file '/var/log/mysqld.log' for error logging.'

二进制日志(bin log)

binlog可以说是MySQL中比较 重要 的日志了,在日常开发及运维过程中,经常会遇到。

binlog即binary log,二进制日志文件,也叫作变更日志(update log)。它记录了数据库所有执行的DDL 和 DML 等数据库更新事件的语句,但是不包含没有修改任何数据的语句(如数据查询语句select、show等)。

它以事件形式记录并保存在二进制文件中。通过这些信息,我们可以再现数据更新操作的全过程。

如果想要记录所有语句(例如,为了识别有问题的查询),需要使用通用查询日志。

binlog主要应用场景:

  1. 是用于数据恢复,如果MySQL数据库意外停止,可以通过二进制日志文件来查看用户执行了哪些操作,对数据库服务器文件做了哪些修改,然后根据二进制日志文件中的记录来恢复数据库服务器。
  2. 是用于数据复制,由于日志的延续性和时效性,master把它的二进制日志传递给slaves来达到master-slave数据—致的目的。

可以说MySQL数据库的数据备份、主备、主主、主从都离不开binlog,需要依靠binlog来同步数据,保证数据—致性。

在这里插入图片描述

查看默认情况

查看记录二进制日志是否开启:在MySQL8中默认情况下,二进制文件是开启的。

 show variables like '%log_bin%';	
/*
+---------------------------------	+----------------------------------	+
| Variable_name	| Value	|
+---------------------------------	+----------------------------------	+
| log_bin	| ON	|
| log_bin_basename	| /var/lib/mysql/binlog	|
| log_bin_index	| /var/lib/mysql/binlog.index	|
| log_bin_trust_function_creators	| OFF	|
| log_bin_use_v1_row_events	| OFF	|
| sql_log_bin	| ON	|
+---------------------------------	+----------------------------------	+
6 rows in set (0.00 sec)	
*/
  • log_bin_basename : 是binlog日志的基本文件名,后面会追加标识来表示每一个文件
  • log_bin_index:是binlog文件的索引文件,这个文件管理了所有的binlog文件的目录
  • log_bin_trust_function_creators:限制存储过程,前面我们已经讲过了,这是因为二进制日志的一个重要功能是用于主从复制,而存储函数有可能导致主从的数据不一致。所以当开启二进制日志后,需要限制存储函数的创建、修改、调用
  • log_bin_use_v1_row_events 此只读系统变量已弃用。ON表示使用版本1二进制日志行,OFF表示使用版本2二进制日志行(MysQL 5.6的默认值为2)。

日志参数设置

新建的文件夹需要使用mysql用户,使用下面的命令即可。

chown -R -v mysql:mysql binlog
[mysqld]
#启用二进制日志
log-bin="/var/lib/mysql/binlog/atguigu-bin"
binlog_expire_logs_seconds=600
max_binlog_size=100M

提示:

  1. log-bin=mysql-bin #打开日志(主机需要打开),这个mysql-bin也可以自定义,这里也可以加上路径,如: /home/www/mysql_bin_log/mysql-bin
  2. binlog_expire_logs_seconds:此参数控制二进制日志文件保留的时长,单位是秒,默认2592000 3(天-- 14400 4小时; 86400 1天; 259200 3天;
  3. max_binlog_size:控制单个二进制日志大小,当前日志文件大小超过此变量时,执行切换动作。此参数的最大和默认值是1GB,该设置并不能严格控制Binlog的大小,尤其是Binlog比较靠近最大值而又遇到一个比较大事务时,为了保证事务的完整性,可能不做切换日志的动作,只能将该事务的所有SQL都记录进当前日志,直到事务结束。一般情况下可采取默认值

查看日志

当MySQL创建二进制日志文件时,先创建一个以“filename”为名称、以“.index”为后缀的文件,再创建一个以“filename”为名称、以“.000001”为后缀的文件。

MySQL服务 重新启动一次 ,以“.000001”为后缀的文件就会增加一个,并且后缀名按1递增。即日志文件的个数与MySQL服务启动的次数相同;如果日志长度超过了 max_binlog_size 的上限(默认是1GB),就会创建一个新的日志文件。

查看当前的二进制日志文件列表及大小。指令如下:

SHOW BINARY LOGS;	
/*	
+	--------------------	+	-----------	+-----------	+
| Log_name		|	File_size | Encrypted |
+	--------------------	+	-----------	+-----------	+
| atguigu-bin.000001	|	156	| No	|
+	--------------------	+	-----------	+-----------	+
1	行于数据集 (0.02	秒)				
*/						

下面命令将行事件以 伪SQL的形式 表现出来

mysqlbinlog -v "/var/lib/mysql/binlog/atguigu-bin.000002"
#220105	9:16:37 server id 1	end_log_pos 324 CRC32 0x6b31978b
Query
thread_id=10
exec_time=0	error_code=0
SET TIMESTAMP=1641345397/*!*/;
SET @@session.pseudo_thread_id=10/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1168113696/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C utf8mb3 *//*!*/;
SET
@@session.character_set_client=33,@@session.collation_connection=33,@@session.collatio n_server=255/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
/*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/;
BEGIN
/*!*/;
# at 324
#220105	9:16:37 server id 1	end_log_pos 391 CRC32 0x74f89890	Table_map:
`atguigu14`.`student` mapped to number 85
# at 391
#220105	9:16:37 server id 1	end_log_pos 470 CRC32 0xc9920491	Update_rows: table id
85 flags: STMT_END_F
BINLOG '
dfHUYRMBAAAAQwAAAIcBAAAAAFUAAAAAAAEACWF0Z3VpZ3UxNAAHc3R1ZGVudAADAw8PBDwAHgAG
AQEAAgEhkJj4dA==
dfHUYR8BAAAATwAAANYBAAAAAFUAAAAAAAEAAgAD//8AAQAAAAblvKDkuIkG5LiA54+tAAEAAAAL
5byg5LiJX2JhY2sG5LiA54+tkQSSyQ==
'/*!*/;
###	UPDATE `atguigu`.`student`
###	WHERE
###	@1=1
###	@2='张三'
###	@3='一班'
###	SET
###	@1=1
###	@2='张三_back'
###	@3='一班'
# at 470
#220105 9:16:37 server id 1 end_log_pos 501 CRC32 0xca01d30f Xid = 15 COMMIT/*!*/;

前面的命令同时显示binlog格式的语句,使用如下命令不显示它

mysqlbinlog -v --base64-output=DECODE-ROWS "/var/lib/mysql/binlog/atguigu-bin.000002" #220105 9:16:37 server id 1 end_log_pos 324 CRC32 0x6b31978b Query thread_id=10
exec_time=0	error_code=0
SET TIMESTAMP=1641345397/*!*/;
SET @@session.pseudo_thread_id=10/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1168113696/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C utf8mb3 *//*!*/;
SET
@@session.character_set_client=33,@@session.collation_connection=33,@@session.collatio n_server=255/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
/*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/;
BEGIN
/*!*/;
# at 324
#220105	9:16:37 server id 1	end_log_pos 391 CRC32 0x74f89890	Table_map:
`atguigu14`.`student` mapped to number 85
# at 391
#220105	9:16:37 server id 1	end_log_pos 470 CRC32 0xc9920491	Update_rows: table id
85 flags: STMT_END_F
###	UPDATE `atguigu14`.`student`
###	WHERE
###	@1=1
###	@2='张三'
###	@3='一班'
###	SET
###	@1=1
###	@2='张三_back'
###	@3='一班'
# at 470
#220105	9:16:37 server id 1	end_log_pos 501 CRC32 0xca01d30f	Xid = 15

使用日志恢复数据

如果MySQL服务器启用了二进制日志,在数据库出现意外丢失数据时,可以使用MySQLbinlog工具从指定的时间点开始(例如,最后一次备份)直到现在或另一个指定的时间点的日志中恢复数据。

mysqlbinlog恢复数据的语法如下:

mysqlbinlog [option] filename|mysql –uuser -ppass;

这个命令可以这样理解:使用mysqlbinlog命令来读取filename中的内容,然后使用mysql命令将这些内容恢复到数据库中。

filename :是日志文件名。

  • option :可选项,比较重要的两对option参数是–start-date、–stop-date 和
    • –start-position、-- stop-position。
    • –start-date 和 --stop-date :可以指定恢复数据库的起始时间点和结束时间点。
    • –start-position和–stop-position :可以指定恢复数据的开始位置和结束位置。

删除二进制日志

MySQL的二进制文件可以配置自动删除,同时MySQL也提供了安全的手动删除二进制文件的方法。PURGE MASTER LOGS 只删除指定部分的二进制日志文件, RESET MASTER 删除所有的二进制日志文件。具体如下:

PURGE MASTER LOGS:删除指定日志文件

PURGE {MASTER | BINARY} LOGS TO ‘指定日志文件名’ PURGE {MASTER | BINARY} LOGS BEFORE ‘指定日期’

再谈二进制日志(binlog)

写入机制

binlog的写入时机也非常简单,事务执行过程中,先把日志写到 binlog cache ,事务提交的时候,再把binlog cache写到binlog文件中。因为一个事务的binlog不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache。

我们可以通过binlog_cache_size参数控制单个线程binlog cache大小,如果存储内容超过了这个参数,就要暂存到磁盘(Swap)。binlog日志刷盘流程如下:

在这里插入图片描述

上图的write,是指把日志写入到文件系统的page cache,并没有把数据持久化到磁盘,所以速度比较快

上图的 fsync,才是将数据持久化到磁盘的操作

binlog与redolog对比

  • redo log 它是 物理日志 ,记录内容是“在某个数据页上做了什么修改”,属于 InnoDB 存储引擎层产生的。

  • 而 binlog 是逻辑日志 ,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”,属于 MySQL Server层。
    虽然它们都属于持久化的保证,但是侧重点不同。

  • redo log让InnoDB存储引擎拥有了崩溃恢复能力

  • binlog 保证了MySQL集群架构的数据一致性。

两阶段提交

在执行更新语句过程,会记录redo log与binlog两块日志,以基本的事务为单位,redo log在事务执行过程中可以不断写入,而binlog只有在提交事务时才写入,所以redo log与binlog的 写入时机 不一样
在这里插入图片描述

redo log与binlog两份日志之间的逻辑不一致,会出现什么问题?

以update语句为例,假设id=2的记录,字段c值是0,把字段c值更新成1,SQL语句为update T set c=1 where id=2。

假设执行过程中写完redo log日志后,binlog日志写期间发生了异常,会出现什么情况呢?

在这里插入图片描述

由于binlog没写完就异常,这时候binlog里面没有对应的修改记录。因此,之后用binlog日志恢复数据时,就会少这一次更新,恢复出来的这一行c值是0,而原库因为redo log日志恢复,这一行c值是1,最终数据不一致

在这里插入图片描述

为了解决两份日志之间的逻辑一致问题,InnoDB存储引擎使用两阶段提交方案。原理很简单,将redo log的写入拆成了两个步骤prepare和commit,这就是两阶段提交。

在这里插入图片描述

使用两阶段提交后,写入binlog时发生异常也不会有影响,因为MySQL根据redo log日志恢复数据时,发现redolog还处于prepare阶段,并且没有对应binlog日志,就会回滚该事务。

在这里插入图片描述

中继日志(relay log)

中继日志只在主从服务器架构的从服务器上存在。从服务器为了与主服务器保持一致,要从主服务器读取二进制日志的内容,并且把读取到的信息写入本地的日志文件 中,这个从服务器本地的日志文件就叫中继日志。然后,从服务器读取中继日志,并根据中继日志的内容对从服务器的数据进行更新,完成主从服务器的数据同步 。

搭建好主从服务器之后,中继日志默认会保存在从服务器的数据目录下。

文件名的格式是: 从服务器名 -relay-bin.序号 。中继日志还有一个索引文件: 从服务器名 -relay-bin.index ,用来定位当前正在使用的中继日志。

查看中继日志

SET TIMESTAMP=1618558728/*!*/;
BEGIN
/*
/*!*/;
# at 950
#210416 15:38:48 server id 1	end_log_pos 832 CRC32 0xcc16d651	Table_map:
`atguigu`.`test` mapped to number 91
# at 1000
#210416 15:38:48 server id 1	end_log_pos 872 CRC32 0x07e4047c	Delete_rows: table id
91 flags: STMT_END_F	-- server id 1 是主服务器,意思是主服务器删了一行数据
BINLOG '
CD95YBMBAAAAMgAAAEADAAAAAFsAAAAAAAEABGRlbW8ABHRlc3QAAQMAAQEBAFHWFsw=
CD95YCABAAAAKAAAAGgDAAAAAFsAAAAAAAEAAgAB/wABAAAAfATkBw==
'/*!*/;
# at 1040
*/

定位到表 atguigu.test 编号是 91 的记录,日志位置是 832;

删除编号是 91 的记录,日志位置是 872。
:38:48 server id 1 end_log_pos 872 CRC32 0x07e4047c Delete_rows: table id
91 flags: STMT_END_F – server id 1 是主服务器,意思是主服务器删了一行数据
BINLOG ’
CD95YBMBAAAAMgAAAEADAAAAAFsAAAAAAAEABGRlbW8ABHRlc3QAAQMAAQEBAFHWFsw=
CD95YCABAAAAKAAAAGgDAAAAAFsAAAAAAAEAAgAB/wABAAAAfATkBw==
'/!/;
#at 1040
*/


> 定位到表 atguigu.test 编号是 91 的记录,日志位置是 832;
> 
> 删除编号是 91 的记录,日志位置是 872。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值