摘要:本文学习了数据库常见的日志类型及其作用。
环境
Windows 10 企业版 LTSC 21H2
MySQL 5.7.40
Perl 5.40.2.1
1 日志类型
1.1 错误日志(Error log)
1.1.1 说明
错误日志主要记录服务器的启动和关闭,以及在运行过程中发生的错误和警告相关信息。
默认开启,将主机名作为错误日志文件名保存在数据目录。
1.1.2 配置
修改配置文件:
1 | [mysqld] |
1.2 一般查询日志(General query log)
1.2.1 说明
一般查询日志又称为通用查询日志,是记录最详细的日志,当客户端建立连接或断开连接时,服务器将信息写入此日志,并记录客户端执行的每个SQL语句。
默认关闭,开启通用查询日志会增加很多磁盘IO,所以不建议开启,当需要调试排错时才会开启。
1.2.2 配置
修改配置文件:
1 | [mysqld] |
临时修改,不支持会话修改,只能全局修改:
1 | set global general_log=off; |
查看配置:
1 | show variables like 'general_log%'; |
1.3 慢查询日志(Slow query log)
1.3.1 说明
慢查询日志用来记录执行时间超过指定时间的查询语句。通过慢查询日志,可以查找出哪些查询语句的执行效率很低,以便进行优化。
默认关闭,一般建议开启,它对服务器性能的影响微乎其微,但是可以记录服务器上的慢查询语句,帮助定位性能问题。
1.3.2 配置
修改配置文件:
1 | [mysqld] |
临时修改,不支持会话修改,只能全局修改:
1 | set global slow_query_log=off; |
查看配置:
1 | show variables like 'slow_query_log%'; |
1.4 二进制日志(Binary log)
1.4.1 说明
二进制日志也叫作变更日志,主要用于记录修改数据或有可能引起数据改变的SQL语句,以事件形式记录并保存在二进制文件中。
默认关闭,通常用于数据恢复和主从复制。
1.4.2 配置
修改配置文件:
1 | [mysqld] |
临时修改,不支持全局修改,只能会话修改:
1 | set sql_log_bin=off; |
查看配置:
1 | show variables like 'log_bin%'; |
查看二进制日志列表:
1 | show master logs; |
创建二进制日志:
- 在日志内容超过最大值或者重启服务器后,自动滚动生成新的日志文件,并将数字扩展名累加。
- 也可以通过命令手动滚动生成新的日志文件:
sql 1
flush logs;
清除二进制日志:
1 | purge master logs to '文件名称'; |
重置主库,清除二进制日志并重置序号,如果已经存在从库,会导致从库同步报错:
1 | reset master; |
1.4.3 日志格式
支持三种格式:
- statment:基于sql语句的日志记录,记录的是SQL语句,对数据进行修改的SQL都会记录在日志文件中。优缺点:
- 优点:不需要记录每一行的变化,减少了日志量,节约了IO,从而提高了性能。
- 缺点:在某些情况下的数据不一致,比如将
now()
等函数得到的结果插入数据库。
- row:基于行的日志记录,记录的是数据变更,不记录每条SQL语句的上下文信息。优缺点:
- 优点:不会出现某些情况下的数据不一致的问题。
- 缺点:会产生大量的日志。
- mixed:基于statment和row两种模式的混合,一般的复制使用statement模式,对于statement模式无法复制的操作使用row模式。
默认使用ROW格式。
修改配置文件:
1 | [mysqld] |
临时修改:
1 | set binlog_format='row'; |
查看配置:
1 | show variables like 'binlog_format'; |
1.4.4 刷盘策略
系统会为每个线程分配一块内存作为缓存,在执行SQL命令时,将日志写入缓存,在提交事务时,将缓存里的日志写入磁盘文件。
刷盘的时机可以通过sync_binlog
参数控制:
- 0:事务提交只写缓存,由系统自行判断什么时候刷盘。
- 1:事务提交会执行刷盘。
- N:事务提交只写缓存,当累计N个事务后才刷盘。
修改配置文件:
1 | [mysqld] |
临时修改,不支持会话修改,只能全局修改:
1 | set global sync_binlog=0; |
查看配置:
1 | show variables like 'sync_binlog'; |
1.5 中继日志(Relay log)
1.5.1 说明
中继日志保存了主服务器的二进制日志,SQL线程会根据中继日志的内容进行同步,从而使从服务器和主服务器的数据保持一致。
默认关闭,主要用于主从复制,需要联合使用二进制日志和中继日志。
1.5.2 配置
修改配置文件:
1 | [mysqld] |
重置从库,清除中继日志,如果已经存在从库,会删除主库关联:
1 | reset slave; |
1.6 DDL日志(DDL log)
DDL日志记录由DDL语句执行的元数据操作,使用此日志从元数据操作中间发生的崩溃中恢复。
DDL日志最多可容纳4GB的条目,超过此限制后必须先重命名或删除文件,然后才能执行DDL语句。
1.7 回滚日志(Undo log)
1.7.1 说明
回滚日志是InnoDB存储引擎在执行增删改的SQL命令时产生的逻辑日志,用来保证事务的原子性,主要用于事务回滚和多版本并发控制。
回滚日志是逻辑日志,记录数据被修改前的值。
回滚日志主要分为两种:
- insert undo log:当执行insert的时候,产生的回滚日志只在回滚时需要,在事务提交后,可被立即删除。因为insert操作只是对本事务可见,其他事务不可见,所以当事务提交后,对应的回滚日志就会被系统直接删除回收,占用的链表也被释放。
- update undo log:当执行update和delete的时候,产生的回滚日志不仅在事务回滚时需要,在多版本并发控制的快照读时也需要,所以不能在事务提交后马上删除,只在提交后放入链表,等待purge线程进行最后的删除。
1.7.2 原理
在执行增删改的SQL命令前,会在回滚日志中记录操作前的数据,并且会记录三个隐藏字段:
- DB_TRX_ID:最近修改事务ID,记录最近插入或者修改这条记录的事务ID。
- DB_ROLL_PTR:回滚指针,记录最近修改这条记录的上一版本,通过这个字段可以在回滚日志中找到最近的历史版本。
- DB_ROW_ID:隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。
在对同一条记录进行增删改操作时,会在回滚日志中生成一系列这条记录的版本链,链表的头部是最新的旧记录,链表尾部是最早的旧记录。
当发生回滚时,根据记录的操作前的数据进行回滚。
1.8 重做日志(Redo log)
1.8.1 说明
重做日志是InnoDB存储引擎在执行增删改的SQL命令时产生的物理日志,用来保证事务的持久性,主要用于掉电等故障恢复。
重做日志是物理日志,记录的是物理数据页修改后的信息。
1.8.2 原理
在执行增删改的SQL命令后,会将重做日志写入到缓存中,记录数据被修改后的值。在提交事务前,会将缓存中的重做日志写入到磁盘上的日志文件,然后将提交事务并将改动保存到数据库。
重做日志采用循环写入机制,写满一个文件后就自动切换到下一个文件,直到所有文件都写满后又回到第一个文件,覆盖之前的内容。
1.8.3 两阶段提交
在提交事务时,需要记录重做日志和二进制日志,为了解决日志之间的逻辑一致问题,使用了两阶段提交的方案。
提交事务前的两阶段提交流程:
- 将缓存里的重做日志写入到磁盘文件,并标记为prepare阶段。
- 将缓存里的二进制日志写入到磁盘文件。
- 将重做日志中的状态改为commit阶段。
如果没有使用两阶段提交,在宕机时会出现数据不一致问题:
- 假设先写入重做日志,在写入二进制日志前发生宕机,重启后根据重做日志执行操作并提交事务,此时二进制日志没有记录该事务,数据不一致。
- 假如先写入二进制日志,在写入重做日志前发生宕机,重启后根据重做日志没有执行操作,此时二进制日志已经记录该事务,数据不一致。
如果使用了两阶段提交,在宕机时就能避免数据不一致问题:
- 假设在写入二进制日志前发生宕机,重启后根据重做日志执行操作,在二进制日志找不到对应记录,回滚事务,数据一致。
- 假如在写入二进制日志后发生宕机,重启后根据重做日志执行操作,在二进制日志能找到对应记录,提交事务,数据一致。
1.8.4 刷盘策略
在将缓存的重做日志写入到磁盘上时,先将重做日志写入到操作系统的缓存中,然后由操作系统将重做日志写到日志文件。
刷盘的时机可以通过innodb_flush_log_at_trx_commit
参数控制:
- 0(延迟写):事务提交不会写入系统缓存,而是每隔1秒写入系统缓存并调用操作系统刷盘。当系统崩溃时会丢失数据。
- 1(实时写并且实时刷盘):事务提交会写入系统缓存并调用操作系统刷盘。当系统崩溃时不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能差。
- 2(实时写但是延时刷盘):事务提交只写入系统缓存,每隔1秒调用操作系统刷盘。当系统崩溃时会丢失数据。
修改配置文件:
1 | [mysqld] |
临时修改,不支持会话修改,只能全局修改:
1 | set global innodb_flush_log_at_trx_commit=0; |
查看配置:
1 | show variables like 'innodb_flush_log_at_trx_commit'; |
2 慢查询分析
2.1 配置
慢查询分析是通过分析慢查询日志,结合explain进行全面分析。
查看慢查询日志的配置:
1 | show variables like 'slow_query_log%'; |
2.2 安装Perl
在生产环境中,手工查找分析SQL显然是个体力活,建议使用mysqldumpslow日志分析工具。
在Windows系统中使用mysqldumpslow需要先安装Perl环境,有ActiveState Perl和Strawberry Perl两种:
- ActiveState Perl:ActiveState为Perl提供了一个免费的社区版本和一个商业支持的版本。
- Strawberry Perl:专为Windows设计的100%开源的Perl实现,使用CPAN模块不需要二进制包。
为了使用方便,在Windows上安装Strawberry Perl,官网地址:http://strawberryperl.com
安装包分为安装版和便携版,安装版会在安装时自动配置环境变量,便携版需要手动配置环境变量,建议下载安装版并按提示进行安装。
安装结束后在cmd命令行执行perl -v
命令查看版本:
1 | This is perl 5, version 40, subversion 2 (v5.40.2) built for MSWin32-x64-multi-thread |
说明Perl环境安装成功。
2.3 查看SQL
进入MySQL安装目录的bin目录。
语法:
1 | perl mysqldumpslow.pl [选项] 日志位置 |
选项:
- -s 参数:表示按照何种方式排序。
- -s c:表示按照访问次数排序。
- -s l:表示按照锁定时间排序。
- -s r:表示按照返回时间排序。
- -s t:表示按照查询时间排序。
- -s al:表示按照平均访问次数排序。
- -s ar:表示按照平均返回时间排序。
- -s at:表示按照平均查询时间排序。
- -t n:表示返回前面n条的数据。
- -g 表达式:后边搭配一个正则匹配模式,大小写不敏感。
查询返回结果最慢的10个SQL:
1 | perl mysqldumpslow.pl -s t -t 10 D:\Work\MySQL\mysql-5.7.40\data\mysql-slow.log |
查询访问次数最多的10个SQL:
1 | perl mysqldumpslow.pl -s c -t 10 D:\Work\MySQL\mysql-5.7.40\data\mysql-slow.log |
得到按照时间排序的前10条里面含有左连接的查询语句:
1 | perl mysqldumpslow.pl -s t -t 10 -g "left join" D:\Work\MySQL\mysql-5.7.40\data\mysql-slow.log |
另外建议在使用这些命令时结合more使用,否则有可能出现爆屏情况:
1 | perl mysqldumpslow.pl -s r -t 10 D:\Work\MySQL\mysql-5.7.40\data\mysql-slow.log | more |
2.4 分析SQL
使用explain工具分析慢查询SQL的索引使用情况,根据结果优化查询,缩短查询时间。
3 误操作恢复
3.1 配置
查看二进制日志的配置:
1 | show variables like 'log_bin%'; |
查看日志列表:
1 | show master logs; |
3.2 查看内容
3.2.1 使用命令查看
使用SQL命令查看日志内容:
1 | show binlog events |
示例:
1 | show binlog events |
结果中每条记录的Pos
字段就是该记录的位置。
3.2.2 使用工具查看
使用mysqlbinlog工具查看日志内容:
1 | mysqlbinlog [选项] 文件位置 |
选项:
- –no-defaults:不要读取任何选项文件,如果使用时有如下报错
mysqlbinlog: [ERROR] unknown variable
可以使用该选项绕过。 - –base64-output=decode-rows -v:将BINLOG语句解码为SQL语句进行显示。
- –base64-output=decode-rows -vv:将BINLOG语句解码为SQL语句进行显示,同时显示字段数据类型和某些元数据的注释。
- –start-position:设置开始位置。
- –stop-position:设置结束位置。
- –start-datetime:设置开始日期,优先级比位置低。
- –stop-datetime:设置结束日期,优先级比位置低。
- –database:设置数据库。
示例:
1 | mysqlbinlog --no-defaults --base64-output=decode-rows -v D:\Work\MySQL\mysql-5.7.40\data\mysql-bin.000001 |
结果中每行以# at
开头的数字就是该条记录的位置。
3.3 恢复数据
使用mysqlbinlog工具恢复数据:
1 | mysqlbinlog [选项] 文件位置 | mysql –u用户名 -p[密码]; |
示例:
1 | mysqlbinlog --no-defaults --stop-position=1038 D:\Work\MySQL\mysql-5.7.40\data\mysql-bin.000001 | mysql -uroot -p |
设置结束时间和结束位置时,需要选择事务提交之后的记录,才能保证最后执行的SQL命令被提交到了服务器。
条