事务特性:ACID
- Atomicity: 原子性,事务中的操作要么全部成功,要么全部失败
原理:
undo log属于逻辑日志,它记录的是sql执行相关的信息。
InnoDB实现回滚,靠的是undolog:当事务对数据库进行修改时,InnoDB会生成对应的undo log;
如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。
- Consistency: 一致性,事务执行前后数据库都处于正确的状态
- Isolation:隔离性,多个事务并发执行时,一个事务的执行不应影响其他事务的执行
(一个事务)写操作对(另一个事务)写操作的影响:锁机制保证隔离性
(一个事务)写操作对(另一个事务)读操作的影响:MVCC保证隔离性
- 脏读:当前事务(A)中可以读到其他事务(B)未提交的数据(脏数据)
- 不可重复读:在事务A中先后两次读取同一个数据,两次读取的结果不一样,这种现象称为不可重复读。
脏读与不可重复读的区别在于:前者读到的是其他事务未提交的数据,后者读到的是其他事务已提交的数据。
- 幻读:事务A先查询查出2条,事务B做了insert操作,此时事务A做update影响了3条。
不可重复读与幻读的区别可以通俗的理解为:前者是数据变了,后者是数据的行数变了。
- Durability: 持久性,事务处理完成后,对数据的修改就是永久的
redo log被引入来解决这个问题:当数据修改时,除了修改Buffer Pool中的数据,还会在redo log记录这次操作;
当事务提交时,会调用fsync接口对redo log进行刷盘。如果MySQL宕机,重启时可以读取redo log中的数据,对数据库进行恢复。
redo log采用的是WAL(Write-ahead logging,预写式日志),所有修改先写入日志,再更新到Buffer Pool,保证了数据不会因MySQL宕机而丢失,从而满足了持久性要求。
既然redo log也需要在事务提交时将日志写入磁盘,为什么它比直接将Buffer Pool中修改的数据写入磁盘(即刷脏)要快呢?主要有以下两方面的原因:
-
刷脏是随机IO,因为每次修改的数据位置随机,但写redo log是追加操作,属于顺序IO。
-
刷脏是以数据页(Page)为单位的,MySQL默认页大小是16KB,一个Page上一个小修改都要整页写入;而redo log中只包含真正需要写入的部分,无效IO大大减少。
redo log与binlog
我们知道,在MySQL中还存在binlog(二进制日志)也可以记录写操作并用于数据的恢复,但二者是有着根本的不同的:
(1)作用不同:redo log是用于crash recovery的,保证MySQL宕机也不会影响持久性;binlog是用于point-in-time recovery的,保证服务器可以基于时间点恢复数据,此外binlog还用于主从复制。
(2)层次不同:redo log是InnoDB存储引擎实现的,而binlog是MySQL的服务器层(可以参考文章前面对MySQL逻辑架构的介绍)实现的,同时支持InnoDB和其他存储引擎。
(3)内容不同:redo log是物理日志,内容基于磁盘的Page;binlog的内容是二进制的,根据binlog_format参数的不同,可能基于sql语句、基于数据本身或者二者的混合。
(4)写入时机不同:binlog在事务提交时写入;redo log的写入时机相对多元:
前面曾提到:当事务提交时会调用fsync对redo log进行刷盘;这是默认情况下的策略,修改innodb_flush_log_at_trx_commit参数可以改变该策略,但事务的持久性将无法保证。
除了事务提交时,还有其他刷盘时机:如master thread每秒刷盘一次redo log等,这样的好处是不一定要等到commit时刷盘,commit速度大大加快
redolog和undolog
Redo日志是数据库中的一种日志,用于记录数据库中发生的所有修改操作,比如插入、更新和删除操作。这些修改会首先写入到Redo日志中,然后才会被应用到数据库的数据文件中。
Redo日志的作用在于在数据库发生故障时,可以利用Redo日志中的信息来进行数据库的恢复和重放操作,确保数据库的一致性和持久性。
Undo日志则用于记录数据库中的撤销操作,比如事务回滚或者数据恢复操作。当数据库执行修改操作时,会先将修改前的数据记录到Undo日志中,以便在需要时可以撤销这些操作。
Undo日志的存在可以确保数据库的一致性和事务的原子性。
- 参考博客
https://www.cnblogs.com/kismetv/p/10331633.html