一、MySQL支持的日志
MySQL有不同类型的日志文件,用来存储不同类型的日志,分为
二进制日志
、错误日志
、通用查询日志
和慢查询日志
,这也是常用的4种。MySQL 8又新增两种支持的日志:中继日志
和数据定义语句日志
。使用这些日志文件,可以查看MySQL内部发生的事情
-
慢查询日志:
记录所有执行时间超过long_query_time
的所有查询,方便我们对查询进行优化。 -
通用查询日志
:记录所有连接的起始时间和终止时间
,以及连接发送给数据库服务器的所有指令,对我们复原操作的实际场景、发现问题,甚至是对数据库操作的审计都有很大的帮助 -
错误日志:
记录MySQL服务的启动、运行或停止MySQL服务时出现的问题,方便我们了解服务器的状态,从而对服务器进行维护 -
二进制日志:
记录所有更改数据的语句,可以用于主从服务器之间的数据同步,以及服务器遇到故障时数据的无损失恢复 -
中继日志:
用于主从服务器架构中,从服务器用来存放主服务器二进制日志内容的一个中间文件。从服务器通过读取中继日志的内容,来同步主服务器上的操作 -
数据定义语句日志:
记录数据定义语句执行的元数据操作 -
小结:
除二进制日志
外,其他日志都是文本文件
。默认情况下,所有日志创建于MySQL数据目录
中。
1.1、日志的弊端
- 日志功能会
降低MySQL数据库的性能
。例如,在查询非常频繁的MySQL数据库系统中,如果开启了通用查询日志
和慢查询日志
,MysQL数据库会花费很多时间记录日志。 - 日志会
占用大量的磁盘空间
。对于用户量非常大、操作非常频繁的数据库,日志文件需要的存储空间设置比数据库文件需要的存储空间还要大。
二、慢查询日志(slow query log)
三、通用查询日志(general query log)
通用查询日志用来
记录用户的所有操作
,包括启动和关闭MysQL服务、所有用户的连接开始时间
和截止时间
、发给 MySQL 数据库服务器的所有 SQL 指令等。当我们的数据发生异常时,查看通用查询日志,还原操作时的具体场景
,可以帮助我们准确定位问题。
3.1问题场景
在电商系统中,购买商品并且使用微信支付完成以后,却发现支付中心的记录并没有新增,此时用户
再次使用支付宝支付
,就会出现重复支付
的问题。但是当去数据库中查询数据的时候,会发现只有一条记录存在。那么此时给到的现象就是只有一条支付记录,但是用户却支付了两次。
我们对系统进行了仔细检查,没有发现数据问题,因为用户编号
和订单编号
以及第三方流水号
都是对的。可是用户确实支付了两次
,这个时候,我们想到了检查通用查询日志
,看看当天到底发生了什么。
查看之后,发现:1月1日下午2点,用户使用微信支付
完以后,但是由于网络故障,支付中心没有及时收到微信支付的回调通知
,导致当时没有写入数据。1月1日下午2点30,用户又使用支付宝支付
,此时记录更新到支付中心。1月1日晚上9点,微信的回调通知过来了
,但是支付中心已经存在了支付宝的记录,所以只能覆盖记录
了。
3.2查看当前状态
SHOW VARIABLES LIKE '%general%';
查看当前通用查询日志状态.png
- 系统变量 general_log 的值是 OFF,即
通用查询日志处于关闭状态
。在MysQL中,这个参数的默认值是关闭的
。因为一旦开启记录通用查询日志,MySQL 会记录所有的连接起止和相关的 SQL操作,这样会消耗系统资源并且占用磁盘空间。我们可以通过手动修改变量的值,在需要的时候开启日志
-
通用查询日志文件
的名称是raven-mysql-0.log
。存储路径是/var/lib/mysql
,默认也是数据路径
。这样我们就知道在哪里可以查看通用查询日志的内容了
3.3 启动日志
3.3.1 永久性启动日志
修改
my.cnf
或者my.ini
配置文件来设置。在[mysqld]组下加入log选项,并重启MySQL服务。如果不指定目录和文件名,通用查询日志将默认存储在MySQL数据目录中的hostname.log文件中,hostname表示主机名
[mysqld]
general_log=ON
# 日志文件所在目录路径,filename为日志文件名
general_log_file=[path[filename]]
3.3.2 临时性启动日志
- 开启通用查询日志
SET GLOBAL general_log=on;
- 设置日志文件保存位置
SET GLOBAL general_log_file=’path/filename’;
- 关闭通用查询日志
SET GLOBAL general_log=off;
- 查看设置后情况
SHOW VARIABLES LIKE 'general_log%';
3.4 查看日志
通用查询日志是以
文本文件
的形式存储在文件系统中的,可以使用文本编辑器
直接打开日志文件。每台MySQL服务器的通用查询日志内容是不同的
- 查看
通用查询日志
路径
SHOW VARIABLES LIKE 'general_log%';
- 查看
通用查询日志
文件命令
cat raven-mysql-0.log
- 查看
通用查询日志
文件内容
usr/sbin/mysqld, Version: 8.0.31 (MySQL Community Server - GPL). started with:
Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
2022-12-14T15:17:44.115654Z 16 Query SHOW WARNINGS
2022-12-14T15:17:44.118549Z 16 Query SHOW WARNINGS
2022-12-14T15:17:44.119479Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ select database()
2022-12-14T15:17:44.123749Z 16 Query SHOW WARNINGS
2022-12-14T15:17:44.126374Z 16 Query SELECT @@session.transaction_isolation
2022-12-14T15:17:47.151800Z 16 Query SELECT @@session.transaction_isolation
2022-12-14T15:17:47.154022Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ set session transaction read write
2022-12-14T15:17:47.156549Z 16 Query SELECT @@session.transaction_read_only
2022-12-14T15:17:47.158780Z 16 Query SHOW WARNINGS
2022-12-14T15:17:47.160113Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ SET net_write_timeout=600
2022-12-14T15:17:47.160770Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ SHOW VARIABLES LIKE 'general_log%'
2022-12-14T15:17:47.180542Z 16 Query SHOW WARNINGS
2022-12-14T15:17:47.186542Z 16 Query SHOW WARNINGS
2022-12-14T15:17:47.188044Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ select database()
2022-12-14T15:17:47.191568Z 16 Query SHOW WARNINGS
2022-12-14T15:17:47.193943Z 16 Query SELECT @@session.transaction_isolation
2022-12-14T15:17:51.753388Z 16 Query SELECT @@session.transaction_isolation
2022-12-14T15:17:51.754277Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ set session transaction read write
2022-12-14T15:17:51.757078Z 16 Query SELECT @@session.transaction_read_only
2022-12-14T15:17:51.759036Z 16 Query SHOW WARNINGS
2022-12-14T15:17:51.760204Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ select database()
2022-12-14T15:17:51.764532Z 16 Query SHOW WARNINGS
2022-12-14T15:17:51.766647Z 16 Query SHOW WARNINGS
2022-12-14T15:17:51.768083Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ SET net_write_timeout=600
2022-12-14T15:17:51.768694Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ SET SQL_SELECT_LIMIT=501
2022-12-14T15:17:51.769289Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ SELECT *
FROM student
2022-12-14T15:17:51.784761Z 16 Query SHOW WARNINGS
2022-12-14T15:17:51.789334Z 16 Query SELECT @@session.transaction_isolation
2022-12-14T15:18:56.781345Z 16 Query SELECT @@session.transaction_isolation
2022-12-14T15:18:56.782926Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ set session transaction read write
2022-12-14T15:18:56.785348Z 16 Query SELECT @@session.transaction_read_only
2022-12-14T15:18:56.786850Z 16 Query SHOW WARNINGS
2022-12-14T15:18:56.788342Z 16 Query SELECT @@session.transaction_read_only
2022-12-14T15:18:56.788922Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ SET net_write_timeout=600
2022-12-14T15:18:56.789465Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ SET SQL_SELECT_LIMIT=DEFAULT
2022-12-14T15:18:56.790033Z 16 Query /* ApplicationName=DataGrip 2022.3.2 */ INSERT INTO student
VALUES (22, 'Raven-22', '五班'),
(23, 'Raven-23', '五班'),
(24, 'Raven-24', '五班')
3.5、停止日志
3.5.1、永久性停止日志
修改
my.cnf
或者my.ini
文件,把[mysqld]组下的general_log
值设置为OFF
或者把general_log
一项注释掉。修改保存后,再重启MySQL服务
,即可生效
[mysqld]
general_log=OFF
或
[mysqld]
#general_log=ON
3.5.2、临时性停止日志
- 使用SET语句停止MySQL通用查询日志功能
SET GLOBAL general_log=off;
- 查询通用日志功能
SHOW VARIABLES LIKE 'general_log%';
3.6 删除/刷新日志
如果数据的使用非常频繁,那么
通用查询日志
会占用服务器非常大的磁盘空间
。数据管理员可以删除很长时间
之前的查询日志,以保证MySQL服务器上的硬盘空间。
3.6.1 手动删除文件
- 1、
通用查询日志
的目录默认为MySQL数据目录。在该目录下手动删除通用查询日志
文件
# /var/lib/mysql/raven-mysql-0.log
SHOW VARIABLES LIKE 'general_log%';
- 2、重新生成查询日志文件
刷新MySQL数据目录,发现创建了新的日志文
件。前提一定要开启通用日志
mysqladmin -uroot -p flush-logs
- 3、先备份,再重新生产查询日志文件
如果
希望备份旧的通用查询日志
,就必须先将旧的日志文件复制出来或者改名
,然后执行上面的mysqladmin命令。正确流程如下
# 输入自己的通用日志文件所在目录
cd mysql-data-directory
# 指名就的文件名 以及 新的文件名
mv mysql.general.1og mysql.general.1og.old
mysqladmin -uroot -p flush-logs
四、错误日志(error log)
错误日志
记录了 MySQL 服务器启动
、停止
运行的时间,以及系统启动
、运行和停止
过程中的诊断信息
,包括错误
、警告
和提示
等。
通过错误日志
可以查看系统
的运行状态,便于即时发现故障
、修复故障
。如果MySQL服务出现异常
,错误日志是发现问题、解决故障的首选
。
4.1启动日志
在MySQL数据库中,错误日志功能是
默认开启
的。而且,错误日志无法被禁止
。
4.1.1启动日志文件路径配置
默认情况下,
错误日志
存储在MySQL数据库的数据文件夹下,名称默认为mysqld.log
(Linux系统)或hostname.err
(mac系统)。如果需要制定文件名,则需要在my.cnf
或者my.ini
中做如下配置,修改配置项后,需要重启MySQL服务
才能生效
[mysqld]
# path为日志文件所在的目录路径,filename为日志文件名
log-error=[path/[filename]]
4.2查看日志
- 查询错误日志的存储路径
SHOW VARIABLES LIKE 'log_err%';
image.png
4.3 删除/刷新日志
对于很久以前的错误日志,数据库管理员查看这些错误日志的可能性不大,可以将这些错误日志删除,以保证MySQL服务器上的
硬盘空间
。MySQL的错误日志是以文本文件的形式存储在文件系统中的,可以直接删除
。
- 第1步(方式1):删除操作
在运行状态下删除
错误日志
文件后,MySQL并不会自动创建日志文件
。
rm -f /var/lib/mysgl/mysqld.1og
- 第1步(方式2):重命名文件
mv /var/log/mysqld.log /var/log/mysqld.log.old
- 第2步:重建日志
mysqladmin -u root -p flush-logs
- 可能会报错或没有重新生成文件
mysqladmin: refresh failed;
error: 'Could not open file '/var/log/mysqld.log'
for error logging.'
- 解决错误 解决错误.png
install -omysql -gmysql -m0644 /dev/null /var/log/mysqld.log
-
flush-logs
指令操作- MySQL 5.5.7以前的版本,flush-logs将错误日志文件重命名为filename.err_old,并创建新的日志文件
- 从MysQL 5.5.7开始,flush-logs只是
重新打开日志文件
,并不做日志备份和创建
的操作。 - 如果
日志文件不存在
,MySQL启动或者执行flush-logs时会自动创建新的日志文件。重新创建错误日志,大小为0字节
4.4 MySQL8.0新特性
MySQL8.0里对错误日志的改进。MySQL8.0的错误日志可以理解为一个全新的日志,在这个版本里,接受了来自社区的广泛批评意见,在这些意见和建议的基础上生成了新的日志
4.4.1 来自社区的意见
- 默认情况下内容过于冗长
- 遗漏了有用的信息
- 难以过滤某些信息
- 没有标识错误信息的子系统源
- 没有错误代码,解析消息需要识别错误
- 引导消息可能会丟失
- 固定格式
4.4.2 针对这些意见,MySQL做了如下改变
- 采用
组件架构
,通过不同的组件执行日志的写入和过滤功能 - 写入错误日志的全部信息都具有唯一的错误代码从10000开始
- 增加了一个新的消息分类 《system》用于在错误日志中始终可见的非错误但服务器状态更改事件的消息
- 增加了额外的附加信息,例如关机时的版本信息,谁发起的关机等等
- 两种过滤方式,Internal和Dragnet
- 三种写入形式,经典、JSON和syseventlog
4.4.3 小结
通常情况下,管理员不需要查看错误日志。但是,
MySQL服务器发生异常
时,管理员可以从错误日志
中找到发生异常的时间、原因,然后根据这些信息来解决异常
五、二进制日志(bin log)
binlog
可以说是MySQL中比较重要
的日志了,在日常开发及运维过程中,经常会遇到。
binlog即binary log
,二进制日志文件,也叫作变更日志 (update log)
。它记录了数据库所有执行的DDL
和DML
等数据库更新事件的语句,但是不包含没有修改任何数据的语句 (如数据查询语句select、show等)。
它以事件形式
记录并保存在二进制文件
中。通过这些信息,我们可以再现数据更新操作的全过程。
5.1、binlog主要应用场景
5.1.1、数据恢复
如果MySQL数据库
意外停止
,可以通过二进制日志
文件来查看用户执行了哪些操作
,对数据库服务器文件做了哪些修改,然后根据二进制日志文件中的记录来恢复数据库服务器。
5.1.2、数据复制
image.png由于日志的
延续性
和时效性
,master把它的二进制日志传递给slaves
来达到master-slave数据一致的目的。可以说MySQL数据库的数据备份、主备、主主、主从
都离不开binlog,需要依靠binlog来同步数据,保证数据一致性
5.2、查看默认情况
查看记录
二进制日志
是否开启:在MySQL8中默认情况下,二进制文件是开启的
- 查看SQL
SHOW VARIABLES LIKE '%log_bin%';
image.png
-
log_bin_basename :
是binlog日志的基本文件名,后面会追加标识来表示每一个文件 -
log-bin_index:
是binlog文件的索引文件,这个文件管理了所有的binlog文件的目录 -
log_bin_trust_function_creators:
限制存储过程,前面我们已经讲过了,这是因为二进制日志的一个重要功能是用于主从复制
,而存储函数
有可能导致主从的数据不一致。所以当开启二进制日志后,需要限制存储函数的创建、修改、调用 -
log-bin_use_V1_row_events :此只读系统变量已弃用
。ON表示使用版本 1二进制日志行,OFF表示使用版本 2二进制日志行 (MysQL5.6 的默认值为2)
5.3、日志参数设置
5.3.1、永久性方式
修改MySQL的
my.cnf
或my.ini
文件可以设置二进制日志的相关参数,重新启动MySQL服务生效
[mysqld]
# 启用二进制日志
log-bin=atguigu-bin
binlog_expire_logs_seconds=600
max_binlog_size=100M
-
1、
log-bin=mysql-bin
#打开日志(主机需要打开)),这个mysal-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都记录进当前日志,直到事务结束。一般情况下可采取默认值。
5.3.2、设置带文件夹的bin-log日志存放目录
如果想改变日志文件的目录和名称,可以对my.cnf或my.ini中的log_bin参数修改如下
[mysqld]
log-bin="/var/lib/mysql/binlog/atguigu-bin"
5.3.3、新建的文件夹需要使用mysql用户,使用下面的命令即可
chown -R -v mysql:mysql binlog
5.3.4、小结
数据库文件最好不要与日志文件放在同一个磁盘上!
这样,当数据库文件
所在的磁盘发生故障时,可以使用日志文件恢复数据
。
5.3.5、临时性方式
如果不希望通过修改配置文件并重启的方式设置二进制日志的话,还可以使用如下指令,需要注意的是在mysql8中只有
会话级别
的设置,没有了global级别
的设置。
- GLOBAL 级别
# GLOBAL 级别
SET GLOBAL sql_log_bin = 0;
[HY000][1228] Variable 'sql_log_bin' is a SESSION variable and can't be used with SET GLOBAL
- SESSION 级别
# session级别
SET sql_log_bin=0;
5.4 查看日志
当MySQL创建二进制日志文件时,先创建一个以
filename
为名称、以.index
为后缀的文件,再创建一个以filename
为名称、以.000001
为后缀的文件。
MySQL服务重新启动一次
,以.000001
为后缀的文件就会增加一个,并且后缀名按1递增。即日志文件的个数与MySQL服务启动的次数相同;如果日志长度超过了max_binlog_size
的上限(默认是1GB),就会创建一个新的日志文件。
- 查看当前的二进制日志文件列表及大小
SHOW BINARY LOGS;
image.png
- 所有对数据库的
修改
都会记录在binglog
中。但binlog是二进制文件
,无法直接查看,想要更直观的观看就需要使用mysq1binlog
命令工具了。指令如下:在查看执行,先执行一条SQL语句
UPDATE student
SET name= '张三back'
WHERE id = 1;
- 开始查看binlog
mysqlbinlog /var/lib/mysql/binlog.000054;
-
执行结果可以看到,这是一个简单的日志文件,日志中记录了用户的一些操作,这里并没有出现具体的SQL语句,这是因为binlog关键字后面的内容是经过编码后的
二进制日志
-
这里一个update语句包含如下事件
- Query 事件 负责开始一个事务(BEGIN)
- Table_map事件 负责映射需要的表
- Update_rows事件 负责写入数据
- xid事件 负责结束事务
-
前面的命令同时显示binlog格式的语句,使用如下命令不显示它
mysqlbinlog -v --base64-output=DECODE-ROWS "/var/lib/mysql/binlog.000054"
-
关于mysqlbinlog工具的使用技巧还有很多,例如只解析对某个库的操作或者某个时间段内的操作等。简单分享几个常用的语句,更多操作可以参考官方文档。
-
可查看参数帮助
mysqlbinlog --no-defaults --help
- 查看最后100行
mysqlbinlog --no-defaults --base64-output=decode-rows -vv atguigu-bin.000002 |tail -100
- 根据position查找
mysqlbinlog --no-defaults --base64-output=decode-rows -vv atguigu-bin.000002 |grep -A
20 '4939002'
- 上面这种办法读取出binlog日志的全文内容比较多,不容易分辨查看到pos点信息,下面介绍一种更为方便的查询命令
show binlog events [IN 'log_name' ] [FROM pos] [LIMIT [offset,] row_count];
-
IN log_name:
指定要查询的binlog文件名(不指定就是第一个binlog文件) -
FROM pos :
指定从哪个pos起始点开始查起(不指定就是从整个文件首个pos点开始算) -
LIMIT [offset〕:
偏移量(不指定就是o) -
row-count :
查询总条数(不指定就是所有行)
show binlog events in 'binlog.000054';
- 上面这条语句可以将指定的binlog日志文件,分成有效事件行的方式返回,并可使用limit指定pos点的起始偏移查询条数。
#a、查询第一个最早的binlog日志
show binlog events\G;
#b、指定查询mysql-bin.000054这个文件
show binlog events in 'binlog.000054'\G;
#c、指定查询mysql-bin.000054这个文件,从pos点:391开始查起:
show binlog events in "binlog.000054' from 391\G;
#d、指定查询mysql-bin.000054这个文件,从pos点:391开始查起,查询5条(即5条语句)
show binlog events in 'binlog.000054' from 391 limit 5\G;
#e、指定查询 mysql-bin.000054这个文件,从pos点:391开始查起,偏移2行(即中间跳过2个)查询5条(即5条语句)
show binlog events in 'atguigu-bin.000054' from 391 limit 2,5\G;
- 上面我们讲了这么多都是基于binlog的默认格式,binlog格式查看
show variables like 'binlog_format';
- 除此之外,binlog还有2种格式,分别是
Statement
和Mixed
-
Statement:
每一条会修改数据的sql都会记录在binlog中-
优点:
不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能
-
-
Row:
5.1.5版本的MySQL才开始支持row level 的复制,它不记录sql语句上下文相关信息,仅保存哪条记录被修改。-
优点:
row level 的日志内容会非常清楚的记录下每一行数据修改的细节。而且不会出现某些特定情况下的存储过程,或function,以及trigger的调用和触发无法被正确复制的问题
-
-
Mixed:
从5.1.8版本开始,MySQL提供了Mixed格式,实际上就是Statement与Row的结合
-
5.5 使用日志恢复数据
如果MysQL服务器启用了
二进制日志
,在数据库出现意外丢失数据时,可以使用MySQLbinlog工具从指定的时间点开始(例如,最后一次备份)直到现在或另一个指定的时间点的日志中恢复数据
网友评论