日志分为二类
逻辑日志:可以简单理解为记录的就是sql语句。
物理日志:因为
mysql
数据最终是保存在数据页中的,物理日志记录的就是数据页变更。
undo log 记录数据被修改前的样子
防止丢失数据,用于事务失败后的回滚
Innodb 存储引擎的最大特点就是支持事务,如果本次更新失败,那么该事务中的所有的操作都必须回滚到执行前的样子,也就是说当事务失败的时候,也不会对原始数据有影响
在mysql将要更新的数据加载到缓冲区Buffer pool 时,同时往 undo 日志文件中插入一条日志,也就是将 id=1 的这条记录的原来的值记录下来。
到这一步,我们的执行的 SQL 语句已经被加载到 Buffer Pool 中了,然后开始更新这条语句,更新的操作实际是在Buffer Pool中执行的,那问题来了,按照我们平时开发的一套理论缓冲池中的数据和数据库中的数据不一致时候,我们就认为缓存中的数据是脏数据,那此时 Buffer Pool 中的数据岂不是成了脏数据?没错,目前这条数据就是脏数据,Buffer Pool 中的记录是小强 数据库中的记录是旺财 ,这种情况 MySQL是怎么处理的呢,继续往下看
redo 记录的是数据修改之后的值,不管事务是否提交都会记录下来
redo 日志文件是 InnoDB 特有的,他是存储引擎级别的,不是 MySQL 级别的
服务器宕机,mysql重启时,利用redo log日志内容恢复缓冲区数据
一般情况下,redo log Buffer 数据写入磁盘的策略是立即刷入磁盘
刷磁盘可以通过 innodb_flush_log_at_trx_commit 参数来设置
一般情况下,redo log Buffer 数据写入磁盘的策略是立即刷入磁盘
如果 redo log Buffer 刷入磁盘后,数据库服务器宕机了,在下次重启的时候 MySQL 也会将 redo 日志文件内容恢复到 Buffer Pool 中,因为 redo log buffer 中的数据已经被写入到磁盘了,已经被持久化了
( Redis 的持久化机制类似,在 Redis 启动的时候会检查 rdb 或者是 aof 或者是两者都检查,根据持久化的文件来将数据恢复到内存中)
redo log持久化到磁盘前后区别
mysql服务器宕机,缓冲区的数据会怎么样?
截至目前,我们应该都熟悉了 MySQL 的执行器调用存储引擎是怎么将一条 SQL 加载到缓冲池和记录哪些日志的,流程如下:
innodb_flush_log_at_trx_commit
参数决定)到此为止,从执行器开始调用存储引擎接口做了哪些事情呢?
binlog
用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。
binlog
是通过追加的方式进行写入的,可以通过max_binlog_size
参数设置每个binlog
文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志。
在实际应用中,binlog
的主要使用场景有两个,分别是主从复制和数据恢复。
Master
端开启binlog
,然后将binlog
发送到各个Slave
端,Slave
端重放binlog
从而达到主从数据一致。mysqlbinlog
工具来恢复数据。bin log 的刷盘是有相关的策略的,通过sync_bin log
来修改
对于InnoDB
存储引擎而言,只有在事务提交时才会记录binlog
,此时记录还在内存中,那么biglog
是什么时候刷到磁盘中的呢?mysql
通过sync_binlog
参数控制biglog
的刷盘时机,取值范围是0-N
:
MySQL 5.7.7
之前版本的默认值)commit
的时候都要将binlog
写入磁盘;(MySQL 5.7.7
之后版本的默认值)binlog
写入磁盘。刷入 bin log 有以下几种模式
基于 SQL 语句的复制,每一条会修改数据的 SQL 语句会记录到 bin log 中
**【优点】:**不需要记录每一行的变化,减少了 bin log 日志量,节约了 IO , 从而提高了性能
【缺点】:在某些情况下会导致主从数据不一致,比如执行sysdate()、sleep()等
基于行的复制(row-based replication, RBR),不记录每条SQL语句的上下文信息,仅需记录哪条数据被修改了
【优点】:不会出现某些特定情况下的存储过程、或 function、或 trigger 的调用和触发无法被正确复制的问题
【缺点】:会产生大量的日志,尤其是 alter table 的时候会让日志暴涨
MIXED
基于 STATMENT 和 ROW 两种模式的混合复制
其实 MySQL 在提交事务的时候,
如果在数据被写入到bin log文件的时候,刚写完,数据库宕机了,数据会丢失吗?
玩来玩去数据还是在内存里,我们数据库的数据最后是要被持久化要磁盘里的,什么时候持久化?
其实 MySQL 会有一个后台线程,它会在某个时机将我们Buffer Pool中的脏数据刷到 MySQL 数据库中,这样就将内存和数据库的数据保持统一了
redo log是 InnoDB 存储引擎特有的日志文件,而bin log属于是 MySQL 级别的日志
redo log记录的东西是偏向于物理性质的,如:“对什么数据,做了什么修改”。
bin log是偏向于逻辑性质的,类似于:“对 students 表中的 id 为 1 的记录做了更新操作” 两者的主要特点总结如下:
性质 | redo Log | bin Log |
---|---|---|
文件大小 | redo log 的大小是固定的(配置中也可以设置,一般默认的就足够了) | bin log 可通过配置参数max_bin log_size设置每个bin log文件的大小(但是一般不建议修改)。 |
实现方式 | redo log是InnoDB引擎层实现的(也就是说是 Innodb 存储引起过独有的) | bin log是 MySQL 层实现的,所有引擎都可以使用 bin log日志 |
记录方式 | redo log 采用循环写的方式记录,当写到结尾时,会回到开头循环写日志。 | bin log 通过追加的方式记录,当文件大小大于给定值后,后续的日志会记录到新的文件上 |
使用场景 | redo log适用于崩溃恢复(crash-safe)(这一点其实非常类似与 Redis 的持久化特征) | bin log 适用于主从复制和数据恢复 |
从准备更新一条数据到事务的提交的流程描述