MySQL的各种日志
MySQL中存在着很多种不同类型的日志,都有不同的作用,本文将简单说明日志种类,以及应用场景。
一、日志分类
- Error Log 错误日志
- General Log 普通日志
- Slow Query Log 慢查询日志
- Binary Log(bin log) 二进制日志
- Undo Log 回滚日志
- Redo Log 重写日志
二、日志说明
官方对错误日志的详细说明:dev.mysql.com/doc/refman/...
1.Error Log
用于保存错误日志:主要记录的MySQL在启动、关闭、运行过程中的错误信息。
概览:
ini
2020-08-06T14:25:02.835618Z 0 [Note] [MY-012487] [InnoDB] DDL log recovery : begin
2020-08-06T14:25:02.936146Z 0 [Warning] [MY-010068] [Server] CA certificate /var/mysql/sslinfo/cacert.pem is self signed.
2020-08-06T14:25:02.963127Z 0 [Note] [MY-010253] [Server] IPv6 is available.
2020-08-06T14:25:03.109022Z 5 [Note] [MY-010051] [Server] Event Scheduler: scheduler thread started with id 5
默认的日志格式:
time thread [label] [err_code] [subsystem] msg
[
和]
方括号字符是消息格式中的文本字符。它们不表示字段是可选的。错误日志格式化官方文档:dev.mysql.com/doc/refman/...
查看错误日志所在位置
sql
show variables like "%log_error%";
2.GeneralQuery Log
普通查询日志:通用查询日志是MySQL服务器的一种详细日志,它记录了服务器的所有活动。每当有客户端连接或断开连接时,服务器都会把这些信息写入到通用查询日志中。此外,客户端发送给MySQL服务器的每一条SQL语句,无论是查询、更新还是其他操作,都会被记录在这个日志中。
概览:
sql
2023-11-13T03:46:23.001162Z 187936 Query SELECT 1
2023-11-13T03:46:23.002168Z 187936 Query SET autocommit=0
2023-11-13T03:46:23.002983Z 187936 Query select * from xxl_job_lock where lock_name = 'schedule_lock' for update
这个日志会记录所有的查询,因此体积会非常的大,但是默认情况下GeneralQuery Log是关闭的,所以不会有什么影响,如果你需要排查查询相关问题的话,这个日志可能会对你有所帮助。
开启普通查询日志的方法
ini
# 开启
SET GLOBAL general_log = 'ON';
# 关闭
SET GLOBAL general_log = 'OFF';
# 查询日志位置
show variables like '%general_log%';
3.Slow Query Log
慢查询日志:用于记录慢查询的日志,当你有慢查询产生时,如果开启了这个功能就会去记录慢查询日志,清晰的告诉你,什么时间、什么库、什么sql、的慢查询信息。
查询是否开启慢查询日志
vbnet
# 查询慢查询日志是否开启,返回的第一列如果是ON则代表开启,OFF则关闭,无数据也是关闭
show variables like '%slow_query_log%';
开启慢查询日志
ini
# 开启
SET GLOBAL slow_query_log = 'ON';
# 关闭
SET GLOBAL slow_query_log = 'OFF';
设置慢查询时间
用于配置SQL运行耗时大于多少秒才记录这个SQL。
sql
# 设置如果sql超过了10秒,才记录这个sql为慢查询sql
SET GLOBAL long_query_time = 10;
# 验证是否更改成功,如果返回了你设置的时间,则代表设置成功
show global variables like '%long_query_time%';
慢查询日志概览
css
root@sss-mysql:/var/lib/mysql# cat /var/lib/mysql/sss-mysql-slow.log
/usr/sbin/mysqld, Version: 8.0.27 (MySQL Community Server - GPL). started with:
Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
# Time: 2023-11-13T04:23:19.312891Z
# User@Host: root[root] @ [192.168.40.178] Id: 188030
# Query_time: 1347.713874 Lock_time: 0.000673 Rows_sent: 1 Rows_examined: 34668
use sss;
SET timestamp=1699848051;
select count(c.id),sum(a.account_json),avg(a.id) FROM account_info a
inner join account_info b on a.id = b.id or a.account_json = b.account_json
inner join order_download_range c on a.id = c.id or a.id = c.deleted
inner join order_download_range d on a.id = d.id or a.id = c.deleted
inner join order_download_range e on a.id = e.id or a.id = c.deleted
where a.account_json like '%1%' or b.account_json like '%1%' and c.params like '%a%';
4.Binary Log
二进制日志: 通常被称为binlog,其中包含描述数据库更改的"事件",例如表创建操作或表数据更改。它还包含可能已进行更改的语句的事件(例如, DELETE
没有匹配任何行),除非使用基于行的日志记录。二进制日志还包含有关每个语句更新数据所需时间的信息。二进制日志有两个重要用途:
- 对于复制,复制源服务器上的二进制日志提供要发送到副本的数据更改的记录。源将其二进制日志中包含的信息发送到其副本,副本复制这些事务以进行与源上所做的相同的数据更改。
- 某些数据恢复操作需要使用二进制日志。恢复备份后,将重新执行备份后记录在二进制日志中的事件。这些事件使数据库从备份时起保持最新状态。
二进制日志不记录SELECT、SHOW语句 ,如果需要查看这些语句,你应该使用普通查询日志来查看。
通常binlog用于数据的同步,MySQL的主从复制,数据恢复等场景。
5.Undo Log
仅支持InnoDB
引擎
回滚日志:
6.Redo Log
什么是redolog?
redolog译为重做日志: 是一种基于磁盘数据结构的日志,在崩溃恢复期间用于纠正不完整事务写入的数据。用于MySQL宕机后的数据恢复。
redolog为什么可以保证数据不丢失?
通俗的来讲就是,MySQL在收到数据变更请求时(Update、Delete、Insert),会先记录一条日志日志中包含本次变更所需的各种参数,如果事务提交了但是MySQL宕机了,在MySQL再次重启的时候MySQL会去检查这个日志文件,发现你有一条数据有记录但是未更新成功,MySQL就会将这条记录刷新到磁盘,从而保证数据不会丢失。
redolog产生的时机
在事务提交之前MySQL会先写一条redolog日志,日志会记录下对磁盘中某某页,某某位置的修改记录,这个操作是顺序IO因此性能很好,每次事务前都会产生一条redolog。
增加了redolog机制为什么速度依然很快?
redolog也采用了缓冲池的概念,新产生的redolog并不会直接写入到磁盘中去,而是先在内存中进行存储,因为内存的速度要比磁盘快很多,在结合MySQL中的异步刷盘机制,完成redolog日志刷盘,刷盘的时机如下:
- 每秒1次
- 事务提交时
- redo log缓冲池空间小于一半时。
缓冲池 buffer pool
MySQL在存储数据的时候是随机存储的,因为不能保证被更改每个数据的位置顺序的,因此会产生大量的随机读写IO的操作,我们指定随机的性能都是非常差的,即使你使用的是
SSD
,那么MySQL中就衍生出了一个缓冲池的功能,它会现将需要变更的数据写到缓存池内,缓冲池是一片内存空间,因此效率非常高,然后会异步的将数据随机写入到磁盘里,完成数据的落盘操作。也是因此InnoDB的性能才会这么的高。
redolog的checkpoint_lsn
如果发生数据变更MySQL会将数据写入到redolog中,再由异步线程将redolog中的数据写入到磁盘,而checkpoint_lsn就起到了告诉MySQL要从哪里开始刷数据了,redolog文件中会记录当前事务对应的LSN(Log Sequence Number)
,MySQL会记录当前刷新到的LSN,然后去不断的刷新大于自己的LSN序列化对应的redolog日志。
崩溃恢复也是一样的道理,MySQL重启时会检查redolog文件中是否有大于自己的LSN,如果有的话就根据规则将数据落库,实现崩溃恢复数据不丢失的效果。
问题来了,MySQL是怎么保证日志一定是存在的呢?
MySQL为了解决这个问题,就使用了WAL(Write-Ahead Logging)
日志先行的机制:在事务提交之前MySQL会先写一条redolog日志,只有redolog刷盘成功了,这个事务才代表成功。否则就会触发回滚。
redolog详细流程
假设我们现在执行了一次update:begin;update users set name='张三' where id=1;commit;
,innoDB的流程如下:
-
MySQL服务器收到指令后会生成一个全局的事务id,这个id会贯穿在binlog和redolog中
-
去缓冲池中查找id=1的数据,如果没有就去磁盘找,并加载到缓冲池。
-
修改缓冲池中id=1的数据。
-
记录数据到redolog buffer和binlog cache
- 根据redolog刷盘策略,数据很可能会被刷新到磁盘
-
服务器收到commit指令。
-
刷新redolog buffer到磁盘(保证redolog一定能刷到磁盘),并标记事务状态为
prepare
准备状态。 -
刷新binlog cache到磁盘
-
刷新redolog buffer到磁盘(保证redolog一定能刷到磁盘),并标记事务状态为
commit
提交。 -
返回事务结果
这种先标记为准备状态,在刷新binlog,在标记为提交状态称为二段式提交,也称为内部XA事务。
7.RedoLog插曲
1.为什么有了binlog还需要redolog
binlog不知道数据是哪个时刻出现了丢失。
2.为什么有了redolog还需要binlog
binlog是服务器层面的功能,并非InnoDB独享,而redolog是InnoDB独有的功能。
binlog和redolog都有很多的好处,MySQL设计时考虑到了多种不同的应用场景,因此设计成了两种日志,只能说两种功能互补。