一分钟了解,预写日志 WAL 的核心思路...

开发
要提升随机写性能,最容易想到的,就是利用高性能的顺序写日志,记录事务中的一些信息,来实现已提交事务的数据“要刷盘”,未提交事务的数据“不刷盘”,以及实现故障恢复。

上一篇《刷盘,还是不刷盘,是一个问题》中我们遇到了哪些问题?

(1) 已提交事务+未提交事务的ACID特性怎么保证?

画外音:上一篇中遇到的问题,主要是原子性与持久性。

(2) 数据库崩溃,怎么实施故障恢复?

(3) 每次都刷盘随机写,性能低,怎么提高数据库性能?

画外音:正常情况下,不需要每个事务提交,都进行刷盘。

要提升随机写性能,最容易想到的,就是利用高性能的顺序写日志,记录事务中的一些信息,来实现已提交事务的数据“要刷盘”,未提交事务的数据“不刷盘”,以及实现故障恢复。

这个顺序写的日志,记录什么内容呢?

事务中,对数据库的写操作。

如何来标识写操作的时序呢?

每条日志记录会有一个递增的日志序列号(log sequence number,LSN),唯一标识一条日志记录。

还有一种特殊的日志记录,叫检查点(checkpoint)。

检查点记录了某一个时刻,缓冲池(buffer pool)中所有数据页(page)的状态信息。

有了检查点和顺序写日志,我们就可以通过:

  • 重放(redo)已提交事务的操作;
  • 取消(undo)未提交事务的操作;
  • 顺序写替代随机写;

来解决,上面提到的三大难题。

这,就是我们今天要聊的核心技术,预写日志(write-ahead logging,WAL)。

预写日志不仅仅是一种日志,更像是一种模式,一种协议,它要求在进行数据写入操作时,必须先写入操作日志。

预写日志的分层结构是怎么样的?

如同数据的内存-磁盘两层结构一样,为了提升性能,预写日志也分为内存-磁盘两层结构:

  • 内存层:WAL buffer
  • 磁盘层:WAL log file

预写日志会记录哪些信息呢?

还是之前那个事务T1:

  • 开始事务
  • 读取记录A的值(假设A=1)
  • 修改记录A的值(假设修改为2)
  • 提交事务

预写日志首先会记录,T1事务开始:

LSN=0:<T1, BEGIN>

读取A的值是一个读操作,不需要进行记录。

修改记录A的值是一个写操作,需要进行记录,而且要记录修改前的值,与修改后的值,类似于:

LSN=1:<T1, A, 1, 2>

以方便未来进行redo与undo(如上图中的屎黄色1)。

接下来,事务会对缓冲池中的数据进行修改(如上图中的屎黄色2)。

到目前为止,预写日志都还是写在buffer中,并没有刷到磁盘上。

事务提交时,预写日志,以及缓冲池会发生什么?

首先,T1事务提交,也会记录到buffer中:

LSN=2:<T1, COMMIT>

但这样,还远远不够。

预写日志,必须全部从buffer里刷到磁盘上,也就是日志文件中,事务才能标记上“已提交”,并返回给应用程序。

没错,只要预写日志从buffer刷到磁盘,而不需要数据从buffer刷到磁盘,就能返回应用程序,事务提交成功。

至于数据什么时候从buffer刷回磁盘,这取决于缓冲池刷盘策略,例如:隔一段时间异步刷盘(如上图中的屎黄色便签)。

这,就是预写日志的核心思路。

总结与思考:

(1) 日志序列号(log sequence number,LSN),唯一标识一条日志记录,递增;

(2) 检查点(checkpoint),记录了某一个时刻,缓冲池(buffer pool)中所有数据页(page)的状态信息。

(3) 预写日志记录什么核心信息?

  • 事务开始
  • 事务结束(提交/回滚)
  • 事务的写操作,修改前/修改后的值

(4) 数据库何时能向应用程序返回“事务成功”?

预写日志刷盘成功之后。

(5) 上一篇《刷盘,还是不刷盘,是一个问题》结尾的问题:在数据库返回应用程序事务成功之前,要不要将数据刷回磁盘?

只要有预写日志机制,只需要预写日志刷盘,不需要数据刷盘。

新的场景出现了:如果数据库崩了,怎么利用检查点(checkpoint)以及预写日志,来进行刷盘和数据恢复呢?让你来设计,你会怎么做?

责任编辑:赵宁宁 来源: 架构师之路
相关推荐

2022-07-18 06:16:07

单点登录系统

2017-07-06 08:12:02

索引查询SQL

2020-07-09 07:37:06

数据库Redis工具

2020-07-17 07:44:25

云计算边缘计算IT

2018-03-27 09:28:33

缓存策略系统

2016-09-14 15:57:53

架构分布式系统负载均衡

2017-03-30 19:28:26

HBase分布式数据

2022-06-02 08:46:04

网卡网络服务器

2017-12-26 16:24:36

接口代码数据

2018-06-26 05:23:19

线程安全函数代码

2020-05-21 19:46:19

区块链数字货币比特币

2017-02-21 13:00:27

LoadAverage负载Load

2018-07-31 16:10:51

Redo Undo数据库数据

2011-02-21 17:48:35

vsFTPd

2015-10-10 14:11:00

互联网数据挖掘爬虫

2020-01-30 11:26:17

QinQVLAN协议

2018-01-14 23:19:25

静态动态互联网

2018-12-12 22:51:24

Java包装语言

2016-09-12 17:28:45

云存储应用软件存储设备

2019-12-24 09:10:43

Ipv6IP址协议
点赞
收藏

51CTO技术栈公众号