MySQL为什么需要日志
了解redis的朋友都知道redis的日志是为了实现数据的持久化,而mysql将数据存储在磁盘文件,没有持久化的问题,为什么还需要日志呢?
答案:
1.mysql的事务支持回滚操作,但数据库的状态为当前状态,需要记录事务开始前的数据库状态,以便进行回滚恢复
2.如果在执行事务时数据库故障,需要记录事务的执行状态,以便重启mysql时恢复之前的事务状态
3.用来支持主从复制,避免直接的数据库拷贝,而是通过从数据库重放日志来达到备份的目的,实质是将大部分工作转移到从数据库进行,避免对主数据库造成性能影响
MySQL有哪些日志?有什么作用?
一、undo log(回滚日志):是 Innodb 存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和 MVCC。
作用:
undo log
用于支持事务的回滚和多版本并发控制(MVCC)。在事务修改数据之前,undo log
记录了数据的旧版本,以便在事务回滚时可以恢复到之前的状态。
特性:
- 逻辑日志:记录的是逻辑操作,如插入、更新、删除等。
- 多版本控制:
undo log
支持 MVCC,通过保存数据的旧版本,提供一致性读(Consistent Read),实现快照读。
记录内容:
- 修改前的值或逻辑操作(如行删除、更新前的旧值等)。
二、redo log(重做日志):是 Innodb 存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障恢复;
作用:
redo log
主要用于保证事务的持久性和数据恢复。在事务提交时,redo log
记录了所有修改操作,这些日志可以在数据库崩溃后用来重做(恢复)事务,以保证已提交事务的持久性。
特性:
- 物理日志:记录的是页级别的物理修改操作。
- 循环写:
redo log
的大小固定,采用循环写的方式。 - 持久性保证:事务在提交时会先写入
redo log
并刷盘,确保即使数据库崩溃也能通过redo log
恢复已提交的事务。
记录内容:
- 页号、偏移量、修改前后的数据等。
三、binlog (归档日志):是 Server 层生成的日志,主要用于数据备份和主从复制;
作用:
bin log
主要用于复制和数据恢复。bin log
记录了所有的DML(Data Manipulation Language)和DDL(Data Definition Language)操作,这些操作日志可以用于主从复制(Master-Slave Replication)和基于时间点的恢复(PITR)。
特性:
- 逻辑日志:记录的是逻辑操作,如SQL语句。
- 复制机制:主库的
bin log
可以传输到从库,从库通过重放bin log
实现数据同步。 - 数据恢复:可以通过
bin log
重放操作来恢复数据库到某一时间点。
记录内容:
- SQL语句(INSERT、UPDATE、DELETE等)、事务的开始和结束标记、表结构变化等。
三种日志的区别和联系
- 用途:
redo log
:用于崩溃恢复,保证事务的持久性。undo log
:用于事务回滚和MVCC,提供一致性读。bin log
:用于主从复制和数据恢复。
- 内容:
redo log
:物理级别的页修改操作。undo log
:逻辑级别的操作和数据的旧版本。bin log
:逻辑级别的SQL操作。
- 写入时机:
redo log
:在事务提交时写入。undo log
:在数据修改前写入。bin log
:在事务提交时写入。
undo log(回滚日志)
为什么需要undo log?
mysql事务支持回滚,也就是在事务提交之前,可以恢复到事务开始前的数据库状态,相当于已经执行的事务操作没有发生过一样,这是怎么做到的?mysql数据库的状态一定是当前状态,它是如何恢复到事务开始前的状态的呢?
这就是undo log的作用了:记录对数据库的修改操作(增删改)或修改前的值,达到记录数据库历史状态的目的
听起来很复杂的样子,让我们一探究竟!
undo log记录哪些内容?
每当 InnoDB 引擎对一条记录进行操作(修改、删除、新增)时,要把回滚时需要的信息都记录到 undo log 里,比如:
- 在插入一条记录时,要把这条记录的主键值记下来,这样之后回滚时只需要把这个主键值对应的记录删掉就好了;
- 在删除一条记录时,要把这条记录中的内容都记下来,这样之后回滚时再把由这些内容组成的记录插入到表中就好了;
- 在更新一条记录时,要把被更新的列的旧值记下来,这样之后回滚时再把这些列更新为旧值就好了。
在发生回滚时,就读取 undo log 里的数据,然后做原先相反操作。比如当 delete 一条记录时,undo log 中会把记录中的内容都记下来,然后执行回滚操作的时候,就读取 undo log 里的数据,然后进行 insert 操作。
undo log 支持 MVCC,通过保存数据的旧版本,提供一致性读(Consistent Read),实现快照读
不了解MVCC的朋友可以先简单学习一下
undo log的特性(保存数据的旧版本)决定了它能够支持多版本并发控制,当一个事务需要读取数据时,根据隔离级别,可以控制它能读到哪个版本的数据(最新、事务开始前),而这些不同历史版本的数据来源就是undo log
Undo Log 在 MVCC 中的作用
MVCC(多版本并发控制)依赖于数据的多个版本来实现并发控制和一致性读。具体来说:
- 多版本数据存储:
- 当事务对数据进行修改时,InnoDB 不会立即覆盖原始数据,而是通过
undo log
保存一份修改前的旧数据副本。 - 这些旧数据副本实际上构成了数据的多个版本。每个版本都有一个对应的事务ID和版本号。
- 快照读(Snapshot Read):
- 事务在启动时会创建一个一致性视图(Consistent View),该视图定义了事务可以看到的所有数据版本。
- 一致性视图使用
undo log
中的旧数据版本来提供数据的快照读。例如,如果一个事务在其开始后有其他事务对数据进行了修改,该事务仍然可以通过读取undo log
中的旧版本数据,看到事务开始时的数据库状态。
- 读取旧版本数据:
- 当事务执行 SELECT 语句时,InnoDB 会根据当前事务的时间戳和一致性视图,决定读取数据的哪个版本。
- 如果最新版本的数据对当前事务不可见(因为它是由其他更晚启动的事务修改的),InnoDB 会沿着
undo log
查找并读取一个对当前事务可见的旧版本数据。
具体实现过程
- 事务开始:
- 事务A开始,创建一致性视图。此时,视图中记录了事务A能看到的其他已提交事务的快照。
- 数据修改:
- 事务B开始,对某行数据进行更新。在更新前,InnoDB 会将该行数据的旧版本记录到
undo log
中。
- 事务读取:
- 事务A在读取相同的数据行时,InnoDB 检查该行的最新版本发现它是由事务B修改的(事务B可能还没有提交,或在事务A启动后才提交)。
- 根据一致性视图,事务A不能看到事务B的修改,因此InnoDB会通过
undo log
找到修改前的旧版本数据,返回给事务A。
- 事务提交和回滚:
- 事务B提交后,其修改的最新版本数据成为持久化数据,而旧版本数据仍然保留在
undo log
中,直到没有事务需要这些旧版本数据为止。 - 如果事务B需要回滚,InnoDB会使用
undo log
中的旧版本数据将数据恢复到事务B开始前的状态。