MySQL里边有几种常见的log,分别为:
redolog 是独属于 innodb 的日志,binlog 则是属于 server 层的日志。
binlog 又称作归档日志,binlog记录了数据库表结构和表数据变更,比如update/delete/insert/truncate/create。它不会记录select(因为这没有对表没有进行变更)。binlog 是逻辑日志,记录的是某个表执行了哪些操作。binlog 是追加形式的写入日志,后面的日志不会把前面的覆盖。
主要有两个作用:复制和恢复数据
查看方法:
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修改),文件的体积很小,恢复速度很快。
binlog 和 redo log除了"恢复"是相似的,很多都不一样:
binlog记载的是update/delete/insert这样的SQL语句;而redo log记载的是物理修改的内容。
总结就是:redo log 记录的是数据的物理变化,binlog 记录的是数据的逻辑变化
redo log的作用是为持久化而生的。写完内存,如果数据库挂了,可以通过redo log来恢复内存还没来得及刷到磁盘的数据,将redo log加载到内存里边,内存就能恢复挂掉之前的数据;
binlog的作用是复制和恢复而生的:①.主从服务器需要保持数据的一致性,通过binlog来同步数据;②.如果整个数据库的数据都被删除了,binlog存储着所有的数据变更情况,那么可以通过binlog来对数据进行恢复
=如果内存中的数据已经刷到了磁盘,那么redo log的数据就无效了。所以redo log不会存储所有历史数据的变更,文件的内容会被覆盖。
InnoDB是支持事务的,而事务的四大特性之一:持久性就是靠redo log来实现的(如果写入内存成功,但数据还没真正刷到磁盘,如果此时的数据库挂了,我们可以靠redo log来恢复内存的数据,这就实现了持久性)。
redo log是在事务开始的时候,就开始记录每次的变更信息,而binlog是在事务提交的时候才记录。
MySQL需要保证redo log和binlog的数据是一致的,如果不一致,那就乱套了:
MySQL通过两阶段提交来保证redo log和binlog的数据是一致的:
undo log主要有两个作用:回滚和多版本控制(MVCC)
在数据修改的时候,不仅记录了redo log,还记录undo log,如果因为某些原因导致事务失败或回滚了,可以用undo log进行回滚
undo log主要存储的也是逻辑日志,比如我们要insert一条数据了,那undo log会记录的一条对应的delete日志。我们要update一条记录时,它会记录一条对应相反的update记录。
因为undo log存储着修改之前的数据,相当于一个前版本,MVCC实现的是读写不阻塞,读的时候只要返回前一个版本的数据就行了。
mysql 支持慢查询日志功能—— mysql 会将查询时间过长的 sql 相关信息写入日志。这个查询时间阀值由参数 long_query_time 指定, long_query_time 的默认值为 10,运行 10S 以上的查询 sql 会被记录到慢查询日志中。默认情况下,Mysql 数据库并不启动慢查询日志,需要我们手动来设置这个参数。慢查询日志支持将日志记录写入文件,也支持将日志记录写入数据库表。
show variables like '%slow_query_log%';
set global slow_query_log=1;
使用 sql 修改慢查询日志设置只对当前数据库生效,如果 MySQL 重启后则会失效。如果要永久生效,就必须修改配置文件 my.cnf。
通过以下 sql 查看修改慢查询的阈值:
show variables like 'long_query_time%';
set global long_query_time=4;