Mysql中的日志-undo/redo/binlog详解
在缓存一致性的方法中,有一种是用binlog同步消息,完成缓存的同步,提高了可靠性。这里详细学习一下数据库中的三种日志。
1. 日志的作用
1.1 事物的特性
在MySQL中,事务具有四大特性(ACID):
原子性(Atomicity):事务是一个不可分割的单元,要么都执行要么都不执行。
一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏
隔离性(Isolation):数据库允许多个并发事务同时对数据进行读写和修改,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
事务的原子性、一致性、持久性是通过数据的redo log(重做日志)和undo log(回滚日志)来完成的,而隔离性则是数据库另一个重要机制锁来实现的。
2. undo log回滚日志
2.1 作用
实现了事务中的原子性,主要用于事务回滚和 MVCC。
undo log生成的时机:
- 事务开始时分配
- 事务修改数据前记录旧值
- 事务提交后不会立即删除,可能被其他读事务引用
- 当没有事务需要访问旧版本数据时,由系统清理
2.2 原理
2.2.1 回滚场景
事务在执行过程中,提交事务之前,MySQL发生了崩溃,数据如何回滚到事务之前呢?
undo log是一种可以撤销回退的日志,在事务没有提交前,会记录更新前的数据到undo log中。
一条记录的每一次更新操作产生的undo log格式如上图,都有一个trx_id和roll_pointer,
- trx_id:知道该记录是哪个事务修改的
- roll_pointer:指向该记录的上一次更新数据,通过该指针形成链表,称为版本链。
id=1的新数据balance=2000000,是事务51更新的数据;历史数据是balance=1000000,是事务50更新的数据。
回滚原理:在发生回滚时,读取undo log中的数据,然后做相反的操作,例如delete一条记录,会将该数据记录到undo log中,回滚时,直接读取undo log中的数据即可。不同类型的操作,insert/update/delete有不同的undo log格式。
2.2.2 MVCC
MVCC是多版本并发控制,是通过read view和undo log实现的,undo log中存储着多个历史版本,事务中在第一个查询语句后,会创建一个read view,read view记录当前已经提交和未提交的所有事务,在事务内如果再次查询,依然用的是这个read view,所以事务内查询的数据都是一样的。在read view中可以知道当前事务可见的记录,顺着undo log版本链找到可见的行。
2.3 刷盘
undo log是存储在buffer pool内存中的,那如何持久化呢?
undo log在buffer pool中,对undo log的修改也会记录到redo log,redo log每秒进行刷盘,提交事务的时候也会刷盘,数据页和undo页都是通过这种机制持久化的。
3. buffer pool存储引擎缓存
在讲redo log前需要先说一下buffer pool
数据是存储在磁盘中的,磁盘的IO耗时高,需要缓存数据,减少磁盘的访问。
innodb存储引擎中有个缓冲池buffer pool,用来缓存页数据,提高读写性能。
读操作:直接从缓存中获取数据即可
写操作:修改缓存中数据,并将该页修改为脏页(缓存和磁盘数据不一致),后台线程会在合适的时机更新到磁盘中。
mysql启动时,会将buffer pool划分为多个页空间,其中包括数据页,索引页,undo页等。
4. redo log重做日志
实现了事务中的持久性,主要用于掉电等故障恢复;
如下图中存储引擎中有buffer pool缓存提高了读写效率,但是内存中的数据一旦断电,还没有刷盘的脏页数据就会丢失,为了防止这种情况,innodb引擎在更新内容中数据时,会将该页数据以redo log的形式保存下来,
redo log记录某个数据页做了什么操作,例如xxx表的yyy数据页zzz偏移量的地方做了aaa操作。
在事务提交时,即可将该redo log持久化到磁盘中,不需要等脏页数据持久化到磁盘中。
当系统崩溃重启后,虽然脏页数据没有持久化到磁盘,但是可以用redo log中的内容恢复数据。
其中undo log内容的修改也会记录到redo log并持久化到磁盘中。
区别 | undo log | redo log | binlog |
记录内容 | 记录更新之前的值 | 记录更新之后的值 | 所有的操作 |
产生时机 | 事务开始时 | 事务提交时 | 每条操作 |
作用 | 回滚、事务原子性 | 恢复,事务持久性 | 备份,主从复制 |
5. binlog归档日志
undo log与redo log都是innodb引擎层生成的。
是 Server 层生成的日志,主要用于数据备份和主从复制;
数据完成一条更新操作就会产生一条binlog,在事务提交时,会将事务产生的所有binlog统一写入到binlog文件中,binlog记录数据表结构变更和数据变更,不会记录查询操作。
binlog日志是追加写,写满一个文件就会产生一个新的文件,不会覆盖之前的日志,保存全量日志,redo log是循环写,日志空间大小固定,写满从头开始写,保存未被刷入磁盘的脏页数据。
5.1 数据备份场景
如果不小心将整个数据库的数据都删除了,可以用redo log恢复么?不能,因为redo log会擦除已经刷入磁盘的数据,只保留未被刷入磁盘的页数据,binlog记录了所有数据变更,需要用binlog恢复数据。
5.2 主从复制场景
步骤1.客户端提交事务后,先在server层写入binlog,然后将事务提交给引擎层,更新引擎层数据,返回给客户端事务提交成功。
步骤2.从库会有一个IO线程链接主库的log dump线程,接收主库的binlog日志,写入replay log中继日志中,返回主库复制成功。
步骤3.从库会创建一个回放binlog的线程,读取中继日志,回放binlog更新存储引擎中的数据,最终实现主从一致性。
参考自小林coding