跳至主要內容

Server层四个日志

张威大约 9 分钟mysqlmysql日志数据备份

Server 层四个日志

一、MySQL Server层日志简介

一个mysql client发起一个连接请求,处理请求的过程如下图所示:

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_20,color_FFFFFF,t_70,g_se,x_16.png)

MySQL日志是在MySQL server上生成的,不管更改哪个存储引擎,这些日志都是需要有的,包括:

  • 错误日志:记录mysqld服务运行过程中出现的

  • 查询日志:记录MySQL Server收到的由于上线项目的SQL太多了,开启查询日志IO太多导致MySQL效率低下,我们一般都不会开启查询日志,只有调试时才开启

  • 二进制日志,非常重要,可用于数据恢复,主从复制。

  • 慢查询日志,可供开发人员分析耗时SQL,从而针对性优化

查看日志相关变量

mysql> show variables like 'log%';

![](Server 层四个日志.assets/image-20240421014049849.png)

show variables #查看变量
show status #查看状态

二、配置文件参数

my.cnf

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_19,color_FFFFFF,t_70,g_se,x_16.png)

linux下重启mysqld服务的命令:sudo service mysqld restart

我们查看一下配置文件 /etc/mysql/mysql.conf.d/mysqld.cnf

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_16,color_FFFFFF,t_70,g_se,x_16.png)

  • 给出log-error的路径就是开启了log-error,如果不自定义log-error的路径,默认在data_dir

expire_log_days=7;

三、错误日志

错误日志是 MySQL 中最重要的日志之一,它记录了mysqld 启动和停止,以及服务器在运行过程中发生任何严重错误(coredump,error,exception…)时的相关信息。当数据库出现故障导致无法正常使用时,可以首先查看此日志

mysqld 使用的错误日志名为 host_name.err(host_name 为主机名) ,并默认在参数data_dir(数据目录)指定的目录中写入日志文件

![](Server 层四个日志.assets/image-20240421114121369.png)

![](Server 层四个日志.assets/image-20240421114020759.png)

四、查询日志

查询日志记录了client发送的所有SQL语句

由于上线项目sql特别多,开启查询日志IO太多导致MySQL效率低,我们一般都不会开启,只有在调试时才开启,比如通过从而可以进行缓存

show global variables like '%genera%';

![](Server 层四个日志.assets/01caeb58b8a141a390482e91923d36bc.png)

打开全局变量general_log开关:

![](Server 层四个日志.assets/d76e9880719c4ff181c3b1841cf71a97.png)

五、二进制日志

不是明文(记录数据库的详细内容,明文不安全),不能直接查看,需要通过mysqlbinlog工具(mysql原生自带)解析binlog日志文件

二进制日志(BINLOG)记录了所有的 DDL(数据定义语言)语句和 DML(数据操纵语言) 语句,但是不包括数据查询语句(

语句以“事件”的形式保存,它描述了数据的更改过程。二进制日志对于灾难时的数据恢复起着极其重要的作用。

两个重要的应用场景:

主从复制主库所有的更新操作(update、delete、insert、alter …)都记录在binlog中,从库读主库的binlog,把binlog的所有操作在从库上在进行一遍

查看当前的binlog:

show binary logs;  -- show master logs;

![](Server 层四个日志.assets/d508ea09b0b44e77a66982dbe8894d08.png)

binlog默认在MySQL的配置文件/etc/mysql/my.cnf配置的data_dir下

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_20,color_FFFFFF,t_70,g_se,x_16-171363507402613.png)

1. 演示binlog记录更改

我们先刷新一下,生成一个新的binlog

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_11,color_FFFFFF,t_70,g_se,x_16.png)

切换数据库

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_18,color_FFFFFF,t_70,g_se,x_16.png)

更改一下数据

![](Server 层四个日志.assets/58acce702aa9441a86491432ea8315c3.png)

再次查看binlog

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_11,color_FFFFFF,t_70,g_se,x_16-171363514679822.png)

我们发现日志的filesize从154字节—>710字节,肯定记录我们刚才的数据更改操作

如果我们直接cat日志查看,会发现不是明文,无法直接查看

![](Server 层四个日志.assets/9c810ccb629b445eaa9205e384e5e415.png)

我们需要通过mysqlbinlog进行查看,如下:

mysqlbinlog --no-defaults --database=school --base64-output=decode-rows -v --start-datetime='2022-03-01 00:00:00' --stop-datetime='2022-03-31 00:00:00' mysql-bin.000003 | more 
  • database:指定查看某个库的更改

  • base64-output:binlog解码方式

  • start-datetime & stop-datetime:指定查看某个时间段内的更改,不写则查看所有的更改

  • mysql-bin.000003:查看的二进制日志文件路径

我们查看一下binlog

![](Server 层四个日志.assets/0aff49012e1e4ad5ba404436fed4022e.png)

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_20,color_FFFFFF,t_70,g_se,x_16-171363526798929.png)

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_20,color_FFFFFF,t_70,g_se,x_16-171363528522132.png)

  • @1、@2、@3、@4:表示数据库表的4个字段
  • server id:表示我们在my.cnf中设置的id,用于标识当前MySQL的身份
  • at 565、at 621:指的是当前事件在binlog记录的位置,数据恢复的时候使用

2. 演示binlog数据恢复

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_11,color_FFFFFF,t_70,g_se,x_16-171363531440435.png)

现在创建数据库mytest,并创建表,添加数据

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_16,color_FFFFFF,t_70,g_se,x_16-171363533193338.png)

假如现在有人把库删除了:

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_14,color_FFFFFF,t_70,g_se,x_16.png)

我们现在知道,我们建库、建表、插入数据的操作都记录在mysql-bin.00003文件中

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_12,color_FFFFFF,t_70,g_se,x_16.png)

我们现在,这就可以让我们接下来数据恢复的操作被记录在mysql-bin.00004文件中,而不会在追加到mysql-bin.00003

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_10,color_FFFFFF,t_70,g_se,x_16.png)

我们先查看mysql-bin.00003,找需要恢复的区间

![](Server 层四个日志.assets/image-20240421015016270.png)

从mysql-bin.000003中拿出区间内所有的操作,通过管道放到MySQL shell上执行

mysqlbinlog --start-position=775 --stop-position=1410 binlog.000003 | mysql -uroot -p

![](Server 层四个日志.assets/d3b2c91361144652ae6c23c89c4b300e.png)

start-position和stop-position表示左闭右开区间:[start-position, stop-position)

查看一下当前的库

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_9,color_FFFFFF,t_70,g_se,x_16.png)

再查看一下表和数据

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_20,color_FFFFFF,t_70,g_se,x_16-171363548398851.png)

到这里,数据已经全部恢复了

我们不仅可以通过binlog记录的位置,得到需要恢复的区间,也可以通过binlog记录的时间得到需要恢复的区间

![](Server 层四个日志.assets/808c1b4abe9b4249acdb95968b5c7109.png)

mysqlbinlog --start-datetime='2021-05-06 04:34:32' --stop-datetime='2022-04-24 04:36:02' binlog.000003 | mysql -uroot -p

参数为:start-datetime、stop-datetime,也是左闭右开区间

,没有过期的数据可以直接通过binlog恢复,如果,通过以下命令即可:

mysql> source ~/data.sql #备份文件的恢复

$cat ~/data.sql | mysql -u  root -p #shell命令恢复备份数据

MysqL数据恢复小结

![](Server 层四个日志.assets/image-20240421115737534.png)

MySQL数据恢复分为两部分,一部分由数据备份完成,另一部分由bin-log完成

  • 如果设置日志过期时间为7天,那么我们可以每七天备份一次
  • 七天以内的数据恢复由bin-log完成
  • 超过七天的数据备份在sql脚本,如备份在~/data.sql中
  • 恢复备份文件 source ~/data.sql

六、慢查询日志

MySQL可以设置慢查询日志,当SQL执行的时间超过我们设定的时间,那么这些SQL就会被记录在慢查询日志当中

我们通过查看日志,用explain分析这些SQL的执行计划,来判定为什么效率低下,是没有使用到索引?还是索引本身创建的有问题?或者是索引使用到了,但是由于表的数据量太大,花费的时间就是很长,那么此时我们可以把表分成n个小表,比如订单表按年份分成多个小表等

慢查询日志相关的参数如下所示:

![](Server 层四个日志.assets/46a5eb2d893d4b059475252bb4a70b69.png)

慢查询日志记录了包含所有执行时间超过参数 long_query_time(单位:秒)所设置值的 SQL语句的日志,在MySQL上用命令可以查看,如下:

![](Server 层四个日志.assets/eb0bab49501445e3aaf1c8251a48515e.png)

这个值是可以修改的:

![](Server 层四个日志.assets/14ba37259316444580233aac35698e7b.png)

现在修改成执行时间超过1秒的SQL都会被记录在慢查询日志当中!可以设置为0.01秒,表示10毫秒

慢查询日志,默认名称是host_name-slow.log,存放在MySQL的配置文件/etc/mysql/my.cnf配置的data_dir下,内容格式显示大致如下:

![](Server 层四个日志.assets/9433aa85c0e746a89a74883d5a0daa01.png)

show profiles命令可有查看sql详细的运行时间,全局变量的名字是:profiling

首先需要:set profiling=on

![](Server 层四个日志.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnTWFrZXItc2hlbg==,size_20,color_FFFFFF,t_70,g_se,x_16-171363566787064.png)