1、查询日志
在 MySQL 中也称为通用日志(general log),查询日志里面记录了数据库执行的所有命令,不管语句是否正确,都会被记录,原因如下:
- insert 查询为了避免数据冲突,如果此前插入过数据,当前插入的数据如果跟主键或唯一键的数据重复那肯定会报错;
- update 时也会查询因为更新的时候很可能会更新某一块数据;
- delete 查询,只删除符合条件的数据;
查询日志的开启有助于帮助我们分析哪些语句执行密集,执行密集的 select 语句对应的数据是否能够被缓存,同时也可以帮助我们分析问题,但是在并发操作非常多的场景下,查询信息会非常多,若都记录下来会导致 IO 非常大,影响了MySQL 性能,因此如果不是在调试环境下,是不建议开启查询日志功能的。
查询日志模式默认是关闭的,可以通过以下命令开启查询日志:
set global generallog=1 set global logoutput='table';
general_log=1 为开启查询日志,0 为关闭查询日志,这个设置命令即时生效,不用重启 MySQL 服务器。
2、慢日志
慢查询会导致 CPU、IOPS、内存消耗过高,当数据库遇到性能瓶颈时,大部分时间都是由于慢查询导致的。
开启慢查询日志,可以让 MySQL 记录下查询超过指定时间的语句,之后运维人员通过定位分析,能够很好的优化数据库性能。
默认情况下,慢查询日志是不开启的,只有手动开启了,慢查询才会被记录到慢查询日志中。使用如下命令记录当前数据库的慢查询语句:
set global slowquerylog='ON';
上面的这个命令只是对当前数据库有效,若 MySQL 数据库重启后就会失效。因此如果要永久生效,就要修改配置文件 my.cnf,设置 slowquerylog=1 并重启 MySQL 服务器。
3、重做日志(redo log)
为了最大程度的避免数据写入时,因为 IO 瓶颈造成的性能问题,MySQL 采用了这样一种缓存机制,先将数据写入内存中,再批量把内存中的数据统一刷回磁盘。为了避免将数据刷回磁盘过程中,因为掉电或系统故障带来的数据丢失问题,InnoDB 采用 redo log 来解决此问题。
4、回滚日志(undo log)
用于存储日志被修改前的值,从而保证如果修改出现异常,可以使用 undo log 日志来实现回滚操作。 undo log 和 redo log 记录物理日志不一样,它是逻辑日志,可以认为当 delete 一条记录时,undo log 中会记录一条对应的 insert 记录,反之亦然,当 update 一条记录时,它记录一条对应相反的 update 记录,当执行 rollback 时,就可以从 undo log 中的逻辑记录读取到相应的内容并进行回滚。undo log 默认存放在共享表空间中,在 ySQL 5.6 中,undo log 的存放位置还可以通过变量 innodbundodirectory 来自定义存放目录,默认值为“.”表示 datadir 目录。
5、错误日志
用来记录 MySQL 服务器运行过程中的错误信息,比如,无法加载 MySQL 数据库的数据文件,或权限不正确等都会被记录在此,还有复制环境下,从服务器进程的信息也会被记录进错误日志。默认情况下,错误日志是开启的,且无法被禁止。默认情况下,错误日志是存储在数据库的数据文件目录中,名称为 hostname.err,其中 hostname 为服务器主机名。在 MySQL 5.5.7 之前,数据库管理员可以删除很长时间之前的错误日志,以节省服务器上的硬盘空间, MySQL 5.5.7 之后,服务器将关闭此项功能,只能使用重命名原来的错误日志文件,手动冲洗日志创建一个新的,命令为:
mv hostname.err hostname.err.old mysqladmin flush-logs
6、二进制日志(bin log)
它是一个二进制文件,主要记录所有数据库表结构变更,比如,CREATE、ALTER TABLE 等,以及表数据修改,比如,INSERT、UPDATE、DELETE 的所有操作,bin log 中记录了对 MySQL 数据库执行更改的所有操作,并且记录了语句发生时间、执行时长、操作数据等其它额外信息,但是它不记录 SELECT、SHOW 等那些不修改数据的 SQL 语句。
binlog 的作用如下:
- 恢复(recovery):某些数据的恢复需要二进制日志。比如,在一个数据库全备文件恢复后,用户可以通过二进制日志进行 point-in-time 的恢复;
- 复制(replication):其原理与恢复类似,通过复制和执行二进制日志使一台远程的MySQL数据库(一般称为 slave 或者 standby)与一台 MySQL 数据库(一般称为 master 或者 primary)进行实时同步;
- 审计(audit):用户可以通过二进制日志中的信息来进行审计,判断是否有对数据库进行注入攻击。
除了上面几个作用外,binlog 对于事务存储引擎的崩溃恢复也有非常重要的作用,在开启 binlog 的情况下,为了保证 binlog 与 redo 的一致性,MySQL 将采用事务的两阶段提交协议。当 MySQL 系统发生崩溃时,事务在存储引擎内部的状态可能为 prepared(准备状态)和 commit(提交状态)两种,对于 prepared 状态的事务,是进行提交操作还是进行回滚操作,这时需要参考 binlog,如果事务在 binlog 中存在,那么将其提交;如果不在 binlog 中存在,那么将其回滚,这样就保证了数据在主库和从库之间的一致性。
binlog 默认是关闭状态,可以在 MySQL 配置文件(my.cnf)中通过配置参数 log-bin = [base-name] 开启记录 binlog 日志,如果不指定 base-name,则默认二进制日志文件名为主机名,并以自增的数字作为后缀,比如:mysql-bin.000001,所在目录为数据库所在目录(datadir)。
通过以下命令来查询 binlog 是否开启:
show variables like 'log_%';
binlog 格式分为: STATEMENT、ROW 和 MIXED 三种:
-
STATEMENT 格式的 binlog 记录的是数据库上执行的原生 SQL 语句。这种格式的优点是简单,简单地记录和执行这些语句,能够让主备保持同步,在主服务器上执行的 SQL 语句,在从服务器上执行同样的语句。另一个好处是二进制日志里的时间更加紧凑,所以相对而言,基于语句的复制模式不会使用太多带宽,同时也节约磁盘空间。并且通过 mysqlbinlog 工具容易读懂其中的内容。缺点就是同一条 SQL 在主库和从库上执行的时间可能稍微或很大不相同,因此在传输的二进制日志中,除了查询语句,还包括了一些元数据信息,如当前的时间戳。即便如此,还存在着一些无法被正确复制的 SQL。比如,使用 INSERT INTO TB1 VALUE(CUURENT_DATE()) 这一条使用函数的语句插入的数据复制到当前从服务器上来就会发生变化,存储过程和触发器在使用基于语句的复制模式时也可能存在问题;另外一个问题就是基于语句的复制必须是串行化的,比如:InnoDB 的 next-key 锁等,并不是所有的存储引擎都支持基于语句的复制;
-
ROW 格式是从 MySQL 5.1 开始支持基于行的复制,也就是基于数据的复制,基于行的更改。这种方式会将实际数据记录在二进制日志中,它有其自身的一些优点和缺点,最大的好处是可以正确地复制每一行数据,一些语句可以被更加有效地复制,另外就是几乎没有基于行的复制模式无法处理的场景,对于所有的 SQL 构造、触发器、存储过程等都能正确执行;它的缺点就是二进制日志可能会很大,而且不直观,所以,你不能使用 mysqlbinlog 来查看二进制日志,也无法通过看二进制日志判断当前执行到那一条 SQL 语句。现在对于 ROW 格式的二进制日志基本是标配了,主要是因为它的优势远远大于缺点,并且由于 ROW 格式记录行数据,所以可以基于这种模式做一些 DBA 工具,比如数据恢复,不同数据库之间数据同步等;
-
MIXED 也是 MySQL 默认使用的二进制日志记录方式,但 MIXED 格式默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。比如用到 UUID()、USER()、CURRENTUSER()、ROWCOUNT() 等无法确定的函数。
redo log 和 binlog 有什么区别?
redo log(重做日志)和 binlog(归档日志)都是 MySQL 的重要的日志,它们的区别如下:
- redo log 是物理日志,记录的是“在某个数据页上做了什么修改”。
- binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
- redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
- redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
刚开始 MySQL 里并没有 InnoDB 引擎,MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档。而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统,也就是 redo log 来实现 crash-safe 能力。
注:crash-safe 是指发生宕机等意外情况下,服务器重启后数据依然不会丢失的情况。