MySQL系列之日志简单总结【五】

MySQL里边有几种常见的log,分别为:

  • undo log
  • binlog
  • redo log

redolog 是独属于 innodb 的日志,binlog 则是属于 server 层的日志。

1. binlog

binlog 又称作归档日志,binlog记录了数据库表结构和表数据变更,比如update/delete/insert/truncate/create。它不会记录select(因为这没有对表没有进行变更)。binlog 是逻辑日志,记录的是某个表执行了哪些操作。binlog 是追加形式的写入日志,后面的日志不会把前面的覆盖。

主要有两个作用:复制和恢复数据

  • MySQL在公司使用的时候往往是主从结构,从服务器需要与主服务器的数据保持一致,就是通过binlog来实现的
  • 数据库的数据被干掉了,可以通过binlog来对数据进行恢复

查看方法:

  1. 登录:mysql -uroot -p
  2. 查看日志状态:show variables like ‘%log_bin%’;
    MySQL系列之日志简单总结【五】_第1张图片我这里是开启了的。日志文件就在/var/lib/mysql/binlog
  3. 进入日志目录:
    MySQL系列之日志简单总结【五】_第2张图片
    圈中的都是binlog日志文件
  4. 查看日志:mysqlbinlog binlog.xxxxx
    MySQL系列之日志简单总结【五】_第3张图片

2. redo log

redolog 又称作重做日志,用于记录事务操作的变化,记录的是数据修改之后的值,不管事务是否提交都会记录下来。它在数据库重启恢复的时候被使用,innodb 利用这个日志恢复到数据库宕机前的状态,以此来保证数据的完整性。redolog 是物理日志,记录的是某个表的数据做了哪些修改,redolog 是固定大小的,也就是说后面的日志会覆盖前面的日志。
假设有一条sql语句:

update user set name='张三' where id = 1;

MySQL执行这条SQL语句,是先把id=1的这条记录查出来,前面的文章里说过MySQL的基本存储单位是页,也就是先将id=1的这条记录所在的页都加载到内存中,然后将id=1这条记录进行修改

这就可能存在一个问题:如果在内存中把数据改了,还没来得及写入磁盘,此时的数据库挂了,这次更改就丢了

但是想想也不可能等写入磁盘后再进行请求,那样请求响应会很慢,服务器也受不了。

MySQL引入了redo log,内存中的数据写完之后,会写一份redo log,这份redo log记载着这次在某个页上做了什么修改。

其实写redo log的时候,也会有buffer,是先写到buffer,再刷到磁盘中。至于buffer什么时候刷到磁盘,有配置供我们配置。虽然写redo log也需要刷到磁盘,但它的好处是顺序IO,而且redo log记载的是物理变化(xxxx页做了xxx修改),文件的体积很小,恢复速度很快。

3. binlog 和 redo log的区别

binlog 和 redo log除了"恢复"是相似的,很多都不一样:

3.1 存储的内容

binlog记载的是update/delete/insert这样的SQL语句;而redo log记载的是物理修改的内容。

总结就是:redo log 记录的是数据的物理变化,binlog 记录的是数据的逻辑变化

3.2 功能

redo log的作用是为持久化而生的。写完内存,如果数据库挂了,可以通过redo log来恢复内存还没来得及刷到磁盘的数据,将redo log加载到内存里边,内存就能恢复挂掉之前的数据;

binlog的作用是复制和恢复而生的:①.主从服务器需要保持数据的一致性,通过binlog来同步数据;②.如果整个数据库的数据都被删除了,binlog存储着所有的数据变更情况,那么可以通过binlog来对数据进行恢复

=如果内存中的数据已经刷到了磁盘,那么redo log的数据就无效了。所以redo log不会存储所有历史数据的变更,文件的内容会被覆盖。

3.3 binlog和redo log 写入的细节

  • redo log是MySQL的InnoDB引擎所产生的。
  • binlog无论MySQL用什么引擎,都有

InnoDB是支持事务的,而事务的四大特性之一:持久性就是靠redo log来实现的(如果写入内存成功,但数据还没真正刷到磁盘,如果此时的数据库挂了,我们可以靠redo log来恢复内存的数据,这就实现了持久性)。

redo log是在事务开始的时候,就开始记录每次的变更信息,而binlog是在事务提交的时候才记录

MySQL需要保证redo log和binlog的数据是一致的,如果不一致,那就乱套了

  • 如果redo log写失败了,而binlog写成功了。那假设内存的数据还没来得及落磁盘,机器就挂掉了。那主从服务器的数据就不一致了。(从服务器通过binlog得到最新的数据,而主服务器由于redo log没有记载,没法恢复数据)
  • 如果redo log写成功了,而binlog写失败了。那从服务器就拿不到最新的数据了

MySQL通过两阶段提交来保证redo log和binlog的数据是一致的

  1. 阶段1:读取对应的数据到内存,更新数据,InnoDB redo log 写盘,InnoDB 事务进入 prepare 状态
  2. 阶段2:binlog 写盘,提交事务,InooDB 事务进入 commit 状态
  3. 每个事务binlog的末尾,会记录一个 XID event,标志着事务是否提交成功,也就是说,恢复过程中,binlog 最后一个 XID event 之后的内容都应该被 purge

4. undo log

undo log主要有两个作用:回滚和多版本控制(MVCC)

在数据修改的时候,不仅记录了redo log,还记录undo log,如果因为某些原因导致事务失败或回滚了,可以用undo log进行回滚

undo log主要存储的也是逻辑日志,比如我们要insert一条数据了,那undo log会记录的一条对应的delete日志。我们要update一条记录时,它会记录一条对应相反的update记录。

因为undo log存储着修改之前的数据,相当于一个前版本,MVCC实现的是读写不阻塞,读的时候只要返回前一个版本的数据就行了。

5. 慢查询日志

mysql 支持慢查询日志功能—— mysql 会将查询时间过长的 sql 相关信息写入日志。这个查询时间阀值由参数 long_query_time 指定, long_query_time 的默认值为 10,运行 10S 以上的查询 sql 会被记录到慢查询日志中。默认情况下,Mysql 数据库并不启动慢查询日志,需要我们手动来设置这个参数。慢查询日志支持将日志记录写入文件,也支持将日志记录写入数据库表。

show variables  like '%slow_query_log%';

MySQL系列之日志简单总结【五】_第4张图片
通过以下 sql 开启慢查询:

set global slow_query_log=1;

使用 sql 修改慢查询日志设置只对当前数据库生效,如果 MySQL 重启后则会失效。如果要永久生效,就必须修改配置文件 my.cnf。

通过以下 sql 查看修改慢查询的阈值:

show variables like 'long_query_time%';
set global long_query_time=4;

MySQL系列之日志简单总结【五】_第5张图片
然后设置后关闭当前会话窗口,再重新打开,查看:
MySQL系列之日志简单总结【五】_第6张图片

你可能感兴趣的:(java,mysql)