上篇回顾:http://www.javashuo.com/article/p-xmusedzr-q.htmlhtml
本文的测试环境:MySQL5.7.26
、MariaDB5.5.60
、MySQL8.0.16
mysql
PS:版本查询
select version();
git
服务器层日志(存储引擎层有本身的日志)程序员
日志类型 | 描述 |
---|---|
error_log (错误日志) |
记录MySQL启动、运行或中止时出现的问题 |
general_log (常规日志) |
记录全部发送给MySQL的请求(耗性能) |
slow_query_log (慢查日志) |
记录符合条件的查询(eg:超过10s、没有使用索引等) |
binary_log (二进制日志) |
记录所有有效的数据修改日志(老版本数据库不会开启) |
relay_log (中继日志) |
用于主从复制,临时存储主从同步的二进制日志(增量复制) |
知识扩展:https://blog.csdn.net/zhang123456456/article/details/72811875github
实时查看文件:tail -f /var/log/mysqld.log
sql
tail -f 用于监视文件增加(默认是末尾10行)shell
通常记录MySQL运行错误
和和未受权的访问
数据库
- 老版:
log_error
+log_warnings
- 经常使用:
log_error
+log_error_verbosity
- 新版:
log_error
+log_error_verbosity
+log_error_services
查询MySQL配置:show variables like '%log_error%';
json
SQL查询能够这么干:ubuntu
-- Ubuntu下默认是:`/var/log/mysql/error.log` -- CentOS下默认是:`/var/log/mysqld.log` | `/var/log/mariadb/mariadb.log` select @@log_error; -- 尽量和Data分开存储 -- 0:不记录警告信息,1:告警信息写入错误日志,2:各种告警信息都写入(eg:网络故障和重连信息) select @@log_warnings; -- MySQL8中已经移除(MySQL5.7默认是2,MariaDB5.5.60默认是1) -- 错误级别(1:Error,2:Error、Warning,3:Error、Warning、Info select @@log_error_verbosity; -- MySQL8默认是2,MySQL5.7默认是3 -- PS:从MySQL 5.7.2开始,首选`log_error_verbosity`系统变量 -- 默认是`log_filter_internal; log_sink_internal` select @@log_error_services; -- MySQL8.0中新增
PS:其实MySQL在市面上有不少成熟解决方案(基本上都是基于5.六、5.7的)
这也是为何我开篇主推
MySQL5.7
系列和MariaDB5.5.60
(不少时候不是不用最新DB,而是架构依赖作不到啊)
知识拓展:http://www.javashuo.com/article/p-acredmax-m.html
PS:SQLServer的ErrorLog也是差很少的
日志服务组件:
日志服务组件名 | 描述 |
---|---|
log_sink_internal |
默认的日志输出组件(依赖log_error ) |
log_filter_internal |
默认的日志过滤组件(依赖log_error_verbosity ) |
log_sink_json |
将错误日志输出到json 文件 |
log_sink_syseventlog |
将错误日志输出到系统日志文件 |
PS:log_filter_internal
:过滤错误信息(达不到级别的不记录)
日记格式通常是这样的:UTC时间戳 进程id [日志级别] [错误代码] [由什么产生的日志(Server or Client)] 详细信息
eg:
2019-05-19T09:54:11.590474Z 8 [Warning] [MY-010055] [Server] IP address '192.168.36.144' could not be resolved: Name or service not known
通常log_sink_json
用的比较多:
官方文档参考:https://dev.mysql.com/doc/refman/8.0/en/error-log-json.html
PS:第一次使用须要安装一下json组件:install component 'file://component_log_sink_json';
经常使用设置:
set persist log_error_services='log_filter_internal;log_sink_json';
上面的时间默认是UTC的时间戳,和咱们是有时差的,这个时间戳能够经过设置log_timestamps
来本地化:
-- 查询 select @@log_timestamps; -- MySQL5.7新增 -- 从8开始,可经过SET PERSIST命令将全局变量的修改持久化到配置文件中 set persist log_timestamps='SYSTEM'; -- 须要root权限
PS:set persist
生成的配置文件路径在:/var/lib/mysql/mysqld-auto.cnf
之前开发调试的时候基本上都是会开启的,上线后关闭(系统V1初期的时候也会开启一段时间)
如今开发可使用go-sniffer来抓包查看客户端执行的SQL
-- 是否打开常规日志(0不打开,1打开) -- 通常不打开(性能) select @@general_log; -- 默认为0 -- Ubuntu默认:/var/lib/mysql/ubuntuserver.log -- CentOS默认:/var/lib/mysql/localhost.log select @@general_log_file; -- 常规日志的路径 -- 日志的存储方式(FILE | TABLE | NONE) select @@log_output; -- 默认是文件存储
简单看一下常规日志在数据库中的结构:
临时开启参考:
# 开启 set global general_log = 1; # set [global | persist] general_log_file = '日志路径'; set global log_output = 'TABLE';
slow_query_log
(慢查询日志)这个是最经常使用
的,把符合条件的查询语句记录在日志中,通常都是些须要优化的SQL
PS:出现性能瓶颈的时候,或者为了优化SQL会开启一段时间(小项目推荐直接开启)
先看下默认值:show variables like '%slow%';
、show variables like 'long%';
SQL查询:
-- 是否开启 select @@slow_query_log; -- 默认是关闭 -- CentOS:/var/lib/mysql/localhost-slow.log -- Ubuntu:/var/lib/mysql/ubuntuserver-slow.log select @@slow_query_log_file; -- 条件:设置超过多少秒为慢查询(通常设置1s) select @@long_query_time; -- 默认是10s(支持小数:0.003) -- PS:设置为0就会记录全部SQL(不推荐这么干) -- 条件:没有使用索引的查询记录到日志中 select @@log_queries_not_using_indexes; -- 默认是0(不开启) -- 记录optimize table、analyze table和alter table的管理语句 select @@log_slow_admin_statements; -- 默认是0(不开启) -- 记录由Slave所产生的慢查询 select @@log_slow_slave_statements;
经常使用设置:
PS:高并发下的互联网项目,对SQL执行时间的容忍度通常都是低于
300~500ms
的(long_query_time=0.05
)
# 经常使用以下:(须要MySQL的root权限) set global slow_query_log = 1; # 开启慢查询日志 set global long_query_time = 1; # 记录大于1s的SQL set global log_slow_admin_statements = 1; # 记录管理语句 set global log_queries_not_using_indexes = 1; # 记录没有使用索引的SQL # set [global | persist] slow_query_log_file = '路径'; # 设置log路径
设置long_query_time
时,须要从新链接才能生效(不须要重启DB)
PS:当前会话不生效,以后的会话就生效了(不想重连能够再设置下当前会话的
long_query_time
)
知识拓展:(chown mysql:mysql /work/log/xxx.log
)
先简单分析下慢查询日志:
# Time: 2019-05-22T21:16:28.759491+08:00 # User@Host: root[root] @ localhost [] Id: 11 # Query_time: 0.000818 Lock_time: 0.000449 Rows_sent: 5 Rows_examined: 5 SET timestamp=1558530988; select * from mysql.user order by host; # SQL语句
Time
:查询的执行时间(start_time
)User@Host: root[root] @ localhost [] Id:11
:执行 sql 的主机信息Query_time
:SQL查询
所耗的时间Lock_time
:锁定时间Rows_sent
:所发送的行数Rows_examined
:锁扫描的行数SET timestamp=1558530988;
:SQL执行时间如今能够说说工具了,推荐两款:
mysqldumpslow
percona-toolkit
)中的pt-query-digest
查询最慢的10条SQL:mysqldumpslow -s t -t 10 /var/lib/mysql/localhost-slow.log
-s 按照那种方式排序 t: 查询时间 c:访问计数 l:锁定时间 r:返回记录 al:平均锁定时间 ar:平均访问记录数 at:平均查询时间 -t 返回多少条数据(能够理解为top n) -g 能够跟上正则匹配模式,大小写不敏感。
PS:使用mysqldumpslow的分析结果不会显示具体完整的sql语句:
select * from tb_table where uid=20 group by createtime limit 10000, 1000;
==> select * from tb_table where uid=N group by createtime limit N, N;
官方文档:https://www.percona.com/doc/percona-toolkit/3.0/pt-query-digest.html
分析慢查询日志:
pt-query-digest /var/lib/mysql/localhost-slow.log
tcpdump -s 65535 -x -nn -q -tttt -i any -c 1000 port 3306 > mysql.tcp.txt
pt-query-digest --type tcpdump mysql.tcp.txt
pt-query-digest --processlist h=ip
安装能够参考:https://github.com/lotapp/awesome-tools/blob/master/README.md#4%E8%BF%90%E7%BB%B4
PS:percona-toolkit的经常使用工具我也在里面简单说了下,对应文档也贴了
PS:还有一款mysqlsla
我没用过,因此贴个参考文章,感兴趣的同志本身研究下
知识拓展:http://www.javashuo.com/article/p-pczgzxqq-bd.html
上节主要说了通用日志和慢查日志,今天说下二进制日志:
二进制日志算是最经常使用的了,主要就是记录对数据库的修改
,而后就是主从复制
用的比较多(好比增量备份)
PS:记录了修改操做,那么衍生出的场景就是:
增量备份和恢复
(基于时间点的备份和恢复)
PS:MySQL日志主要分为这两类:(互不干扰)
服务层
日志(和使用存储引擎无关)
存储引擎层
日志
redo log
)和回滚日志(undo log
)Q:那什么样的修改会记录下来呢?
A:记录全部对MySQL数据库的修改事件(包括增删改查事件和对表结构修改的事件),并且只记录已经成功执行的事件(失败的不会记录)
这么说可能有点抽象,熟悉SQLServer的同志看个图就秒懂:
参数 | 说明 |
---|---|
STATEMENT |
基于段的格式,记录执行数据修改时候所执行的SQL语句 |
ROW |
基于行的格式,记录增删改查操做所修改行的信息(每修改一行就会有一条信息) |
MIXED |
基于行和端的混合格式,根据SQL语句由系统决定是基于段仍是基于行的日志格式记录 |
查看方式:show variables like 'binlog_format';
statement
:基于段的记录格式(老版本的默认值)
uuid()
、user()
等结果非肯定的函数,可能会形成MySQL主从不一致mysqlbinlog /var/lib/mysql/binlog.0000xx | more
(不用指定参数)row
:基于行的记录格式(5.7之后的默认值)
binlog_row_image=[full|minimal|noblob]
mysqlbinlog -vv /var/lib/mysql/binlog.0000xx | more
mixed
:基于行和端的混合格式(推荐
)
PS:DDL操做(create、drop、alter)的时候都是基于段方式来记录log
若是一条一条记录,表有上亿数据,我就修改某列的状态值,那不得疯?
对binlog_row_image=[FULL|MINIMAL|NOBLOB]
的补充说明:
PS:查看方式:
show variables like 'binlog_row_image'
full
:完整
noblob
:就是在full记录的基础上对大文本列的优化
minimal
:简单记录,只记录修改的那一列
通常使用binlog_format=mixed
混合格式 or binlog_format=row
+ binlog_row_image=minimal
PS:若是对安全性要求特别高,推荐使用
binlog_format=row
+binlog_row_image=full
(不怕误操做)
这个和SQLServer的日志恢复模式有点相似,我贴下图大家能够对比参考:
上面虽说完了二进制日志的经常使用3种格式,但老版本默认都是不启用二进制日志的,咋办?
PS:若是是MariaDB能够去示例配置中查看:
ls /usr/share/mysql/ |grep .cnf
(CentOS)
验证下:
MySQL8以前:cat /etc/mysql/mysql.conf.d/mysqld.cnf
(UbuntuServer)
MySQL8:cat /etc/my.cnf |grep log
(CentOS)
Q:有些人可能疑惑了,为何用show variables like 'log_bin';
查询出来的结果和配置文件中不大同样啊?
PS:通常配置项中的参数均可以使用
show variables like 'xx'
来查询对应的值
A:那是由于5.7以后版本分红了两个参数:log_bin
和log_bin_basename
:
PS:配置文件的
log_bin=xxx
至关于命令中的log_bin
和log_bin_basename
mysql> show variables like 'log_bin%'; +---------------------------------+-----------------------------+ | Variable_name | Value | +---------------------------------+-----------------------------+ | log_bin | ON | | log_bin_basename | /var/lib/mysql/binlog | | log_bin_index | /var/lib/mysql/binlog.index | | log_bin_trust_function_creators | OFF | | log_bin_use_v1_row_events | OFF | +---------------------------------+-----------------------------+ 5 rows in set (0.00 sec)
MariaDB开启binlog图示:(CentOS)
MySQL5.7演示:(UbuntuServer)
配置文件中修改:(show variables like 'binlog_format';
:查看当前binlog基于什么格式)
# 服务器标识 server-id=1 # 单机MariaDB可不开启 # 开启binlog并设置路径 # 不指定路径则默认在数据目录下 log_bin=binlog # 这个表明以binlog开头的文件 # binlog采用ROW|MIXED格式 # binlog_format=MIXED # 5.7默认是ROW
先看下文件前缀(log_bin=binlog
)的概念,一张图就懂:
PS:若是log_bin只是指定一个名字,那么默认路径通常都是在数据文件的文件夹中
配置文件通常都会写,eg:
datadir=/var/lib/mysql
,或者经过show variables like 'datadir';
也能够查询到
虽然和SQLServer文件组不是一个概念,但有些类似 ==> log能够多个也能够动态调整
Q:虽然ROW记录能保证主从数据安全,但咱们排查问题的时候每每须要知道SQL,而用段的记录方式又不合适,咋办?
A:有个新参数能够解决:binlog_rows_query_log_events
,开启后就能够记录sql了
查看方式:show variables like 'binlog_row%';
mysql> show variables like 'binlog_row%'; +------------------------------+-------+ | Variable_name | Value | +------------------------------+-------+ | binlog_row_image | FULL | | binlog_rows_query_log_events | OFF | +------------------------------+-------+ 2 rows in set (0.01 sec)
显示binlog列表:show binary logs;
刷新一份新的binlog:flush logs;
(如今开始的二进制日志就记录在这个新文件中)
binlog如今是空的:(-vv
:把二进制格式的日志显示为能读懂的字符串)
mysqlbinlog --no-defaults -vv --base64-output=DECODE-ROWS /var/lib/mysql/binlog.000006
如今简单摸拟几个SQL操做,而后看看binlog:
查看下binlog日志:(线上开发通常都是FULL模式,主要是防止程序员修改SQL的时候不加条件等误操做)
FULL模式就是这样,该行数据所有记录(修改部分其实就绿色框的地方)
想要binlog中记录SQL就开启binlog_rows_query_log_events
:
PS:像这种操做,若是模式选混合模式,binlog中会记录SQL的
临时开启下binlog_rows_query_log_events
(若是你有须要能够配置文件设置一下)
PS:MySQL8可经过
set persist
命令将全局变量的修改持久化到配置文件中
效果以下:
expire_logs_days = 30
purge binary logs to 'binlog.000006';
purge binary logs before '2019-06-15 14:14:00';
已经23:23了,咱们快速演示下:
MySQL命令行中执行命令:
文件列表:
这个把运维篇讲完会继续说,运维篇结束后会有个高级篇(架构),这边就简单提下二进制格式对主从复制的影响
:
statement
格式(5.7前的默认)贴个课后拓展文章:http://www.javashuo.com/article/p-xqqwxjcp-bk.html
下级预估:备份与恢复、监控