https://www.datacyber.com
在MySQL中,有三个重要的日志文件,分别是undo log、redo log和binlog。这三个日志文件在MySQL中扮演着不同的角色。
在数据库事务的四大特性中,原子性是指事务中的所有操作要么全部成功,要么全部失败回滚。实现原子性的底层机制之一就是通过使用undo Log。
undo Log是Innodb引擎独有的日志,主要是为事务而准备的,采用循环写覆盖的方式提供回滚能力。它用于记录修改操作的反向操作。当MySQL执行一个事务时,它将对数据进行修改,同时也将反向操作(如果我们执行了insert操作,那么日志中就会新增一条相反的delete的sql)记录到undo Log中。如果MySQL在执行事务的过程中出现故障或者回滚操作,它可以通过 undo Log 中的信息进行恢复。
另外,undolog 还有一个作用,通过 ReadView + undo log 实现多行版本控制(MVCC):当读取的某一行被其他事务锁定时,它可以从undolog中分析出该行记录以前的数据是什么,从而提供该行版本信息,让用户实现非锁定一致性读取。
MySQL 的数据都是存在磁盘中的,当我们要更新一条记录的时候,得先要从磁盘读取该记录,然后在内存中修改这条记录。修改完这条记录不是直接写回到磁盘,而是缓存起来。为此,Innodb 存储引擎设计了一个缓冲池(Buffer Pool),来提高数据库的读写性能。
Buffer Pool 是提高了读写但是Buffer Pool 是基于内存的,而内存总不可靠,万一MySQL在执行事务的过程中遇到系统故障或者崩溃,还没来得及落盘的数据就会丢失。为了解决这个问题,引入了redo log, undo log也是innodb引擎独有的日志,主要是为事务而准备的,使用了 WAL 技术(Write-Ahead Logging),也就是预写日志。它的关键点就是先写日志,再写磁盘。
对应到Mysql中具体操作,就是每次更新操作,先写日志,然后更新内存数据,最后等系统压力小的时候再进行IO更新磁盘数据。避免了每一次更新都需要进行IO操作。redo log 是保证了事务持久性的关键。
当我们从数据库中获取到数据并对其进行修改操作之后,这个修改操作就会优先被存放到redo log buffer中,最终就会被写入到redo log file中。
后续,InnoDB 引擎会在适当的时候将redo log的写入磁盘,写入磁盘的时机是由MySQL系统参数设置决定的,我们可以键入下面这条SQL查看
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
innodb_flush_log_at_trx_commit有3种值:0、1、2,默认为1。
当设置为1的时候:事务每次提交都会将log buffer中的日志写入os buffer并调用fsync()刷到log file on disk中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能较差。
当设置为0的时候:事务提交时不会将log buffer中日志写入到os buffer,而是每秒写入os buffer并调用fsync()写入到log file on disk中。也就是说设置为0时是(大约)每秒刷新写入到磁盘中的,当系统崩溃,最多会丢失1秒钟的数据。 当设置为2的时候:每次提交都仅写入到os buffer,然后是每秒调用fsync()将os buffer中的日志写入到log file on disk。
redo log 和 undo log都属于 InnoDB 存储引擎的日志,并且主要是为事务而准备的,他们的区别在于 : redo log 记录了此次事务「完成后」的数据状态,记录的是更新之后的值;
undo log 记录了此次事务「开始前」的数据状态,记录的是更新之前的值; 事务提交之前发生了崩溃,重启后会通过 undo log 回滚事务,事务提交之后发生了崩溃,重启后会通过 redo log 恢复事务,如下图:
MySQL 在完成一条更新操作后,Server 层还会生成一条 binlog,等之后事务提交的时候,会将该事物执行过程中产生的所有binlog统一写入binlog文件。在正式运行环境,binlog非常重要,其关系到数据能否被找回的问题,binlog采用了追加写的方式,记录了所有数据库表结构变更和表数据修改的日志,不会记录查询类的操作,比如 SELECT 和 SHOW 操作。
redo log 和 binlog 有什么区别?
1、适用对象不同:
binlog 是 MySQL 的 Server 层实现的日志,所有存储引擎都可以使用; redo log 是 Innodb 存储引擎实现的日志; 2、文件格式不同:
bin log则是记录修改的动作,例如update table set name='zhangsan' whrere id=1 ,
redo log存储的物理日志,即修改的数据内容
3、写入方式不同:
binlog 采用追加写的方式,写满一个文件,就创建一个新的文件继续写,不会覆盖以前的日志,保存的是全量的日志。 redo log 是循环写,日志空间大小是固定,全部写满就从头开始,保存未被刷入磁盘的脏页日志。
4、用途不同:
binlog 用于备份恢复、主从复制;
redo log 用于停电等故障恢复。
查看mysql是否开启binlog同步功能
show variables like 'log_bin'
查询的结果显示为ON则表示MySQL开启了binlog。如果数据库的binlog处于关闭的状态,建议通过修改Mysql的配置文件:Windows下的Mysql配置文件是my.ini ,Linux下Mysql的配置文件是my.cnf。
[mysqld]
# 开启binlog
log-bin = mysql-bin
binlog_format = ROW
expire_logs_days = 30
添加相关配置后重启数据库即可
这三个日志不仅可以用于恢复数据库的状态,同时还可以增强数据库的性能和可靠性。对于MySQL的性能来说,redo log和undo log是至关重要的,他们通过控制事务的提交和回滚,保证了修改的正确性。binlog则更多的是用于备份和数据复制的场合,做到业务连续不中断。
而对于MySQL的可靠性来说,这三种日志都很重要,每种日志都发挥了不同的作用,从而最大程度的提高了MySQL的可靠性。