我试图更好地理解检查点内部结构,特别是在 PostgreSQL 中。
我目前的理解是,崩溃恢复将始终从检查点启动时标记的最新 REDO 位置开始。REDO 位置之前的所有 WAL 记录中的数据保证在磁盘上(在数据文件中),并且不再需要那些 WAL 记录。
我很难理解以下内容:
1)REDO位置是如何准确确定的。当一个 Checkpoint 启动时,它是否字面意思是“REDO location is the current WAL record + 1”?
2)当我们确定REDO位置时,如何保证在此之前的所有WAL记录都不再需要了?
具体来说,下面的场景是如何处理的:
- 检查点 1 运行并将脏页 A 写出到磁盘。
- 脏页 A 然后插入了新行
- 检查点 1 完成
- 检查点 2 启动并确定 REDO 位置。
如果页面在检查点 1 刷新后可能变脏,检查点 2 如何确保所有以前的数据都写入磁盘,这是问题的要点。
本质上,是的。确切地说,不。那里有关于记录不适合日志文件的其余部分和其他极端情况的情况的四舍五入的代码。要获得准确的答案,您必须阅读源代码。见
CreateCheckPoint
src/backend/access/transam/xlog.c检查点开始(在计算 REDO 指针之后)通过调查缓冲区缓存中的所有页面,并标记当时脏的页面。在检查点成功结束之前,所有这些标记的页面都需要被写入和刷新。一旦初始的脏页被刷新,保护初始脏页的 WAL 就不再需要了,因为页面本身安全地在磁盘上并且可以自己说话。如果页面开始变脏,然后在整个检查点中多次重新变脏,那么后续的变脏操作将各自有自己的 WAL 记录,这些记录必然落在 REDO 指针之后。这些 WAL 记录将被保留,至少直到当前检查点之后的下一个检查点成功完成。