MySql日志管理

## 1.MySQL常用日志种类 ```bsh 1 错误日志(Error log) #当数据库启动、运行、停止时产生该日志 ==>error.log 2 普通查询日志(General query log) #==>nginx access.log 客户端连接数据库执行语句时产生该日志 3 二进制日志(Binary log) ***** 当数据库内容[发生改变时产生该日志],也被用来实现主从复制功能 4 慢查询日志(Slow query log) ***** SQL语句在数据库查询超过指定时间产生该日志 ``` ## 2.错误日志 ```bsh 1 介绍 记录数据库从启动以来,状态\报错\警告等. 2 查询和配置 mysql> show variables like '%log_error'; +---------------+------------+ | Variable_name | Value | +---------------+------------+ | log_error | ./db01.err | +---------------+------------+ 1 row in set (0.00 sec) [root@db01 ~]# ll /data/3306/data/db01.err -rw-r----- 1 mysql mysql 23653 4月 21 10:57 /data/3306/data/db01.err 配置:my.cnf [mysqld_safe] log-error = /data/3306/data/oldgboy.err [root@db01 ~]# systemctl restart mysqld 默认路径:/data/3306/data/oldgboy.err mysql> show variables like '%log_error'; +---------------+-----------------------------+ | Variable_name | Value | +---------------+-----------------------------+ | log_error | /data/3306/data/oldgboy.err | +---------------+-----------------------------+ 1 row in set (0.01 sec) 3 错误日志怎么用 每天定时巡检,主要关注[ERROR]和[WARNING]。 4 错误日志切割 [root@db01 data]# cd /data/3306/data/ [root@db01 data]# mv oldboy.err oldboy-$(date +%F).err [root@db01 data]# mysqladmin -uroot -poldboy123 flush-logs [root@db01 data]# ls|grep oldboy oldboy-2022-04-21.err oldboy.err 5 排查错误 新手安装数据库时,遇到数据库无法启动时的排查方法为: 1)先把错误日志文件清空,然后重新启动MySQL服务, 再查看日志文件报有什么错误,并根据错误日志进行处理。 2)如果无法解决,则删除数据文件,重新初始化数据库。 3)遇到错误,关键字百度。 ``` ## 3.普通日志(access.log) 了解 ```bsh 1 介绍 默认是关闭的,因为会大量消耗磁盘IO. 可以记录MySQL中发生过的所有操作日志.一般用来调试. mysql> show variables like '%general%'; +------------------+--------------------------+ | Variable_name | Value | +------------------+--------------------------+ | general_log | OFF | | general_log_file | /data/3306/data/db01.log | +------------------+--------------------------+ 2 如何配置 [mysqld] general_log = ON general_log_file = /data/3306/data/oldboy.log [root@oldboy ~]# cat /data/3306/data/oldboy.log /usr/local/mysql/bin/mysqld, Version: 8.0.26 (MySQL Community Server - GPL). started with: Tcp port: 3306 Unix socket: /tmp/mysql.sock Time Id Command Argument 2021-12-12T03:15:48.572994Z 8 Connect root@localhost on using Socket 2021-12-12T03:15:48.573597Z 8 Query select @@version_comment limit 1 2021-12-12T03:15:49.916995Z 8 Query show variables like '%general_log%' 2021-12-12T03:15:54.772789Z 8 Query show variables like '%general_log%' 2021-12-12T03:16:02.494293Z 8 Query show databases 2021-12-12T03:16:03.967361Z 8 Quit 3 普通查询日志作用 审计\调试 真正要审计,在客户端用堡垒机,跳板机审计. 实际生产工作中极少使用普通查询日志,最多临时开一下.. ``` ## 4.二进制日志 (binlog) ```bsh 1.介绍 以event形式,记录MySQL数据库中【变更类】的SQL操作日志(DDL\DCL\DML). 举例: select,show不会记录 crate,drop会记录 2.作用 1)数据增量恢复 2)主从复制 3.参数及配置 mysql> show variables like '%log_bin%'; +---------------------------------+------------------------------+ | Variable_name | Value | +---------------------------------+------------------------------+ | log_bin | ON | | log_bin_basename | /data/3306/data/binlog | | log_bin_index | /data/3306/data/binlog.index | | log_bin_trust_function_creators | OFF | | log_bin_use_v1_row_events | OFF | | sql_log_bin | ON | +---------------------------------+------------------------------+ #4个价参 log_bin=1 #开关,是否开启binlog日志记录。 log_bin_basename=/data/3306/data/binlog #路径和名字。 log_bin_index =/data/3306/data/binlog.index #binlog文件名列表。 sql_log_bin = 1 #是否记录binlog,临时使用. mysql> show variables like '%binlog%'; +------------------------------------------------+----------------------+ | Variable_name | Value | +------------------------------------------------+----------------------+ | binlog_cache_size | 32768 | | binlog_format | ROW | | max_binlog_cache_size | 18446744073709547520 | | max_binlog_size | 1073741824 | | max_binlog_stmt_cache_size | 18446744073709547520 | | sync_binlog | 1 | +------------------------------------------------+----------------------+ 其他binlog参数: sync_binlog=1 # 数据安全参数,数据落盘。性能差. max_binlog_size # 最大binlog文件最大1G max_binlog_ _size # 最大binlog缓存大小 binlog_cache_size # 当前binlog缓存大小. binlog_format=row/statement/mixed # binlog日志记录格式,默认ROW格式,早期statement格式. ``` #### binlog_format格式有几种,区别. ```bsh 格式区别: 1.行模式row(RBR)(8.0默认) 日志记录每一行数据的真实变化,所以日志量会比较大,消耗IO大,但是记录足够准确. 2.statement(SBR)(5.6以前默认): 记录发生的语句本身,不会按行记录.日志量相对少.记录有可能不准确. 3.mixed混合模式 企业选择:row 注意:binlog_format #只影响DML语句,DDL和DCL都是Statement模式记录 ``` ## 5.binlog应用 #### 1)查看和分析binlog ```bsh 1)查看二进制日志文件和大小. mysql> show binary logs; +---------------+-----------+-----------+ | Log_name | File_size | Encrypted | +---------------+-----------+-----------+ | binlog.000001 | 179 | No | | binlog.000002 | 179 | No | | binlog.000003 | 179 | No | | binlog.000004 | 179 | No | 2)查看当前库记录二进制的文件及位置点. mysql> show master status; +---------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+-------------------+ | binlog.000020 | 490 | | | | +---------------+----------+--------------+------------------+-------------------+ 3)查看某个日志具体信息 mysql> show binlog events in 'binlog.000020'; +---------------+-----+----------------+-----------+-------------+-----------------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +---------------+-----+----------------+-----------+-------------+-----------------------------------------------------+ | binlog.000020 | 4 | Format_desc | 1 | 125 | Server ver: 8.0.26, Binlog ver: 4 | | binlog.000020 | 125 | Previous_gtids | 1 | 156 | | | binlog.000020 | 156 | Anonymous_Gtid | 1 | 235 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | binlog.000020 | 235 | Query | 1 | 324 | BEGIN | | binlog.000020 | 324 | Query | 1 | 459 | update oldboy.stu set sname="oldgirl" where age>20 | | binlog.000020 | 459 | Xid | 1 | 490 | COMMIT /* xid=33 */ | +---------------+-----+----------------+-----------+-------------+-----------------------------------------------------+ 4)查看分析binlog mysqlbinlog # 解析binlog命令 --base64-output=decode-rows # 行模式查看 -vvv # 输出 binlog.000018 例子: mysqlbinlog --base64-output=decode-rows -vvv binlog.000018 #按时间截取日志参数 start-datetime (No default value) stop-datetime (No default value) #按位置截取日志参数(推荐) start-position 4 stop-position 18446744073709551615 #gtid参数 --skip-gtids ##忽略GTID --include-gtids ##包含GTID --exclude-gtids ##排除GTID ``` #### 2)数据损坏模拟和恢复--binlog应用增量恢复 ```bsh 故障模拟: mysql> flush logs; ##从新文件,从0位置开始. mysql> show master status; +---------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+-------------------+ | binlog.000020 | 156 | | | | +---------------+----------+--------------+------------------+-------------------+ mysql> drop database oldboy; mysql> create database oldboy; mysql> use oldboy; mysql> create table t1 (id int); mysql> insert into t1 values(1); mysql> insert into t1 values(2); mysql> insert into t1 values(3); mysql> select * from oldboy.t1; mysql> drop table t1; #破坏语句 恢复过程: mysql> show master status; ###确认日志文件命名为binlog.000021 mysql> show binlog events in 'binlog.000021'; ``` ```bsh 恢复方法1: 将记录的binlog文件解析成sql文件,然后编辑sql文件,删除破坏的drop命令. cd /data/3306/data mysqlbinlog --skip-gtids binlog.000021 >/tmp/tmp.sql #删除破坏的drop语句 [root@db01 data]# sed -n '/^DROP TABLE/p' /tmp/tmp.sql DROP TABLE `t1` /* generated by server */ [root@db01 data]# sed -i '/^DROP TABLE/d' /tmp/tmp.sql [root@db01 data]# sed -n '/^DROP TABLE/p' /tmp/tmp.sql 还原: mysql -uroot -poldboy123 oldboy </tmp/tmp.sql mysql: [Warning] Using a password on the command line interface can be insecure. 错误坑:如果解析不加--skip-gtids,会报错. ERROR 1790 (HY000) at line 198: @@SESSION.GTID_NEXT cannot be changed by a client that owns a GTID. The client owns ANONYMOUS. Ownership is released on COMMIT or ROLLBACK. ``` ```bsh 恢复方法2: 指定位置点恢复,恢复drop命令位置点以前的数据,drop语句不恢复. 截取传统binlog日志(GTID) cd /data/3306/data mysqlbinlog --skip-gtids --stop-position=1706 binlog.000021 >/tmp/bin.sql mysqlbinlog --skip-gtids --start-position=156 --stop-position=1706 binlog.000021>/tmp/bin.sql mysql> set sql_log_bin=0; # 临时不记录binlog mysql> source /tmp/bin.sql mysql> set sql_log_bin=1; # 开启binlog. mysql> use oldboy; mysql> show tables; +------------------+ | Tables_in_oldboy | +------------------+ | t1 | +------------------+ 1 row in set (0.00 sec) mysql> select * from t1; +------+ | id | +------+ | 1 | | 2 | | 3 | 位置点记录binlog问题:位置是相对的,将来恢复可能是多个binlog文件,或者多台mysql的binlog文件。 ``` ## 6.GTID #### 1)介绍 ```bsh GTID全称Global Transaction ID,全局事务ID,5.6开始起用的功能。 在整个binlog中每行日志加一个唯一ID值,不管有多少个binlog,都是连续生成的. 具备幂等性(运行过的就不会在运行了). 1ced0886-23d4-11eb-9768-000c29f4772b:1 server_uuid : NO. server_uuid是自动生成的,如需改变/data/3306/data/auto.cnf删除。 ``` #### 2)配置 ```bsh mysql> show variables like "%gtid_%"; set global gtid_mode=ON; set global enforce_gtid_consistency=ON; #强制一致性。 [root@db01 data]# cat /data/3306/data/auto.cnf [auto] server-uuid=3d5846bb-bec3-11ec-bd1d-000c296ebb8f ``` #### 3)基于GTID截取日志 ```bsh 截取1-6:6个事务 --skip-gtids ##忽略GTID --include-gtids ##包含GTID --exclude-gtids ##排除GTID #假设1-6是drop语句 mysqlbinlog --skip-gtids --include-gtids='3d5846bb-bec3-11ec-bd1d-000c296ebb8f:1-5' /data/3306/data/binlog.000023 >/tmp/gtid.sql #恢复1-8,排除6 mysqlbinlog --skip-gtids --include-gtids='3d5846bb-bec3-11ec-bd1d-000c296ebb8f:1-8' --exclude-gtids='3d5846bb-bec3-11ec-bd1d-000c296ebb8f:6' /data/3306/data/binlog.000023 >/tmp/gtid1.sql 注意:如果需要截取的日志需要在原库恢复,需要加--skip-gtids参数,跳过导出文件gtid的记录. #恢复13-16 #17是drop语句 mysqlbinlog --skip-gtids --include-gtids='3d5846bb-bec3-11ec-bd1d-000c296ebb8f:13-16' /data/3306/data/binlog.000023 >/tmp/gtid.sql #恢复13-17,排除17 mysqlbinlog --skip-gtids --include-gtids='3d5846bb-bec3-11ec-bd1d-000c296ebb8f:13-17' --exclude-gtids='3d5846bb-bec3-11ec-bd1d-000c296ebb8f:17' /data/3306/data/binlog.000023 >/tmp/gtid1.sql 注意:如果需要截取的日志需要在原库恢复,需要加--skip-gtids参数,跳过导出文件gtid的记录. ``` #### 4)binlog日志切割 ```bsh 日志切换文件的触发机制:4种. 1)mysql内部命令刷新,启动新binlog记录日志 mysql> flush logs; 2)命令行mysqladmin刷新 [root@oldboy data]# mysqladmin -uroot -poldboy123 flush-logs 3)文件大小达到1G,自动切割 mysql> select @@max_binlog_size; 4)重启数据库 ``` #### 5)binlog日志删除 ```bsh 1.什么删除策略? 每天/每周/每月,保留3天/7天?? 生成环境中binlog删除策略: 1)取决于数据库的备份频率 每天全备,只留一天binlog日志就够了,建议3-7天。 每周一个备份,只留7天binlog日志就够了,建议7-15天。 PB,EB数据,一般会每周一个备份甚至一个月一次全备,binlog也要备份。 2.删除方法 a. 设置自动过期时间 mysql> show variables like '%_logs_%'; +----------------------------+---------+ | Variable_name | Value | +----------------------------+---------+ | binlog_expire_logs_seconds | 2592000 | ##默认30天,8.0新参数 | expire_logs_days | 0 | ###8.0以前老的参数8.0可能不生效 +----------------------------+---------+ binlog_expire_logs_seconds=2592000 ###30天过期,默认值是一个月. binlog_expire_logs_seconds=3600*24*7 mysql> select 3600*24*7; +-----------+ | 3600*24*7 | +-----------+ | 604800 | +-----------+ b.手工清理 show BINARY LOGS; ##基于文件清理,删除14以前,不含14. PURGE BINARY LOGS TO 'binlog.000014'; ##按时间清理 PURGE BINARY LOGS BEFORE '2022-04-21 23:15'; c.全部重置 reset master; [root@db01 data]# ls -l bin* -rw-r----- 1 mysql mysql 156 4月 22 10:24 binlog.000001 -rw-r----- 1 mysql mysql 16 4月 22 10:24 binlog.index 能用rm -f在binlog日志目录下删除么? 尽量不要.. 如果非要删,最后reset master; ``` ##### 单机如何备份binlog ```bsh 1.rsync定时每分钟 2.rsync+sersync实时,基于文件系统。 3.mysqlbinlog --read-from-remote-server --raw --host=10.0.0.51 --port=3306 --user=repl --password=oldboy123 --stop-never binlog.000001 --result-file=/opt/ 解释如下: --read-from-remote-server:用于备份远程服务器的binlog。如果不指定该选项,则会查找本地的binlog。 --raw:binlog日志会以二进制格式存储在磁盘中,如果不指定该选项,则会以文本形式保存。 --user:复制的MySQL用户,只需要授予REPLICATION SLAVE权限。 --stop-never:mysqlbinlog可以只从远程服务器获取指定的几个binlog,也可将不断生成的binlog保存到本地。指定此选项,代表只要远程服务器不关闭或者连接未断开,mysqlbinlog就会不断的复制远程服务器上的binlog。 mysql-bin.000001:代表从哪个binlog开始复制。 实践: mysql> create user repl@'10.0.0.%' identified by 'oldboy123'; Query OK, 0 rows affected (0.01 sec) mysql> grant replication slave on *.* to repl@'10.0.0.%'; Query OK, 0 rows affected (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) 在B机器上执行; mysqlbinlog --read-from-remote-server --raw --host=10.0.0.51 --port=3306 --user=repl --password=oldboy123 --stop-never binlog.000001 --result-file=/opt/ & ``` ## 7.慢查询日志 #### 1)介绍 ```bsh 记录执行较慢的select查询语句. DBA工作中,找出慢的SQL并优化,是DBA核心工作。 为什么要记录? 找到慢查询语句,让数据库运行效率更高. ``` #### 2)配置 ```bsh [root@db01 ~]# cat /etc/my.cnf #by oldboy weixin:oldboy0102 [mysqld] #慢查询 slow_query_log = ON #<==慢查询开启开关 long_query_time = 1 #<==记录大于1秒的SQL语句。 log_queries_not_using_indexes = ON #<==没有使用到索引的SQL语句。 slow-query-log-file = /data/3306/data/slow.log #<==记录SQL语句的文件。 min_examined_row_limit = 800 #<==记录结果集大于800行的SQL语句。 在线修改; mysql> set global slow_query_log=on; mysql> set global long_query_time=0.01; mysql> set global log_queries_not_using_indexes=1; mysql> select @@slow_query_log; mysql> select @@long_query_time; mysql> select @@log_queries_not_using_indexes; ``` #### 3)分析慢日志 ```bsh mysqlsla 和 mysqldumpslow慢查询分析工具外,还有一些第三方分析工具, 如:pt-query-diges、 myprofi、mysql-explain-slow-log、mysqllogfilter等等 ``` ```bsh mysqldumpslow分析方法: [root@oldboy data]# mysqldumpslow -s c -t 3 oldboy-slow.log Reading mysql slow query log from oldboy-slow.log Count: 4 Time=0.00s (0s) Lock=0.00s (0s) Rows=10.0 (40), root[root]@localhost select * from t100w where num<N limit N Count: 3 Time=0.55s (1s) Lock=0.00s (0s) Rows=20.0 (60), root[root]@localhost select count(*) from t100w where num<N group by k2,k1 limit N Count: 3 Time=0.53s (1s) Lock=0.00s (0s) Rows=13.3 (40), root[root]@localhost select count(*) from t100w where num<N group by num,k1 limit N mysqlsla分析方法: Count : 23 (8.52%) Time : 102 s total, 4.434783 s avg, 3 s to 7 s max (6.79%) 95% of Time : 88 s total, 4.190476 s avg, 3 s to 6 s max Lock Time (s) : 0 total, 0 avg, 0 to 0 max (0.00%) 95% of Lock : 0 total, 0 avg, 0 to 0 max Rows sent : 1 avg, 1 to 1 max (0.02%) Rows examined : 11.53k avg, 5.70k to 17.60k max (1.07%) Database : bbsdb Users : oldboy@ 172.16.1.51 : 86.96% (20) of query, 11.11% (30) of all users bbs@ 172.16.1.52 : 13.04% (3) of query, 2.96% (8) of all users Query abstract: SELECT MIN(BBS_HI_id) AS BBS_HI_id FROM t_******** WHERE BBS_HI_isteammate=N AND BBS_HI_editor_user_id_encrypt='S'; Query sample: select min(BBS_HI_ID) AS BBS_HI_ID from t_******** where BBS_HI_ISTEAMMATE=1 and BBS_HI_EDITOR_USER_ID_ENCRYPT='asdfEWERADFS'; ``` ```bsh SQL优化流程: 运维[dba]-运维总监--研发项目程序员--核心架构师--研发经理--研发总监--CTO ``` ```bsh 慢查询日志切割: Date=`date +%F -d -1day` cd /data/3306/data/slow &&\ mv slow.log slow.log_$Date &&\ mysqladmin -uroot -poldboy123 flush-log 慢查询切割脚本 #!/bin/bash #Author: oldboy #Organization: www.oldboyedu.com #Created Time : 2018-03-19 23:47:21 export PATH=/data/3306/data/slow/bin:/sbin:/bin:/usr/sbin:/usr/bin Date=`date +%F -d -1day` #cut slow log # 切割 cd /data/3306/data/slow &&\ mv slow.log slow.log_$Date &&\ mysqladmin -uroot -poldboy123 flush-log #analyze slow log # 分析 #Time=`date +%F` #Path=/usr/local/bin/mysqlsla #cd /data/3306/data/slow &&\ #$Path/mysqlsla -lt slow slow.log_$Date >analyzed_slow_$Date.log 2>&1 #rsync analyzed_slow to backup server同步到备份服务器 #备份服务器发邮件 #send analyzed slow log to adminstrator on backup server by mail. 自动化运维: devops平台: ELK日志手机,慢查询日志收集到ELK平台. 当然还可以把日志收集到数据库中或使用ELK等流行的工具收集慢查询日志, 最后分析后可视化展现, ```