知识库

检查点与日志裁剪的交互

概述

检查点是将其页缓存中所有待处理的页面更新刷新到存储文件的过程。这对于确保恢复时需要重放的事务数量保持在合理范围内是必要的,主要目的是减少不当关闭后的恢复时间。无论检查点是否存在,数据库操作都保持安全,因为所有未确认其更改已持久化到存储的事务将在下一次数据库启动时重放。然而,这取决于这些事务包含的更改集的存在,这些信息保存在事务日志中。保持未应用事务列表过长(检查点间隔较大)将导致事务日志的累积,因为它们是恢复所必需的。检查点在事务日志中引入一个特殊的“检查点”条目,标记检查点发生的最后一个事务。这用于确定哪些事务日志不再需要,因为它们包含的所有事务都已安全地持久化到存储文件中。

删除恢复不再需要的事务日志的过程称为裁剪。从上述描述可以看出,裁剪依赖于检查点,因为检查点决定了哪些日志可以被裁剪,或者换句话说,何时可以进行裁剪,因为如果未发生检查点,可裁剪的事务日志文件集就不会发生变化。这种依赖性通过在发生检查点时触发裁剪(可能包含或不包含对其存在性的检查,如下所述)来表达。这种关系是不变的,适用于后续的所有讨论。

检查点(和裁剪)事件的触发

作为裁剪的驱动事件,检查点可以通过几种不同的方式触发。

最简单的方法称为“周期性”,默认情况下每15分钟检查是否有待刷新的更改(即尚未进行检查点的事务)。如果有,它会执行一个检查点,然后触发日志裁剪。请注意,未执行检查点意味着没有发生裁剪。这是默认行为,也是社区版中唯一可用的行为。

在企业版中,还有两种额外的检查点策略。最简单的一种称为“连续”,顾名思义,它会不断检查是否可以进行检查点(即自上次成功检查点以来是否有任何事务提交),如果有,则执行。裁剪在检查点完成后立即触发,就像在周期性策略中一样。

第三种也是最后一种检查点策略是“容量性”。它每10秒检查是否有日志可供裁剪,如果有,则触发检查点,然后裁剪日志。这种策略似乎颠倒了检查点和裁剪之间的控制关系,但实际上它只是改变了检查点何时必须发生的标准。它不再像前两种策略那样依赖于时间触发器,而是依赖于裁剪检查。裁剪仍然会在检查点发生之后进行,与另外两种策略相同。然而,由于检查取决于可裁剪事务日志文件的存在,因此此策略依赖于裁剪配置,如下一节所述。

要使用的策略由设置dbms.checkpoint控制,默认为“periodic”。

日志记录和指标

以下详细说明了检查点事件发生时预期出现在logs\debug.log中的消息

基于 dbms.checkpoint.interval.time 的检查点

2019-08-28 12:55:05.174+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Scheduled checkpoint for time threshold" @ txId: 49 checkpoint started...
2019-08-28 12:55:05.253+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Scheduled checkpoint for time threshold" @ txId: 49 checkpoint completed in 79ms

基于 dbms.checkpoint.interval.tx 的检查点

2019-08-28 13:08:51.603+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Scheduled checkpoint for tx count threshold" @ txId: 118 checkpoint started...
2019-08-28 13:08:51.669+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Scheduled checkpoint for tx count threshold" @ txId: 118 checkpoint completed in 66ms

当 dbms.checkpoint=continuous 时的检查点

2019-08-28 13:17:21.927+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Scheduled checkpoint for continuous threshold" @ txId: 171 checkpoint started...
2019-08-28 13:17:21.941+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Scheduled checkpoint for continuous threshold" @ txId: 171 checkpoint completed in 13ms

由于数据库关闭导致的检查点

2019-08-28 12:35:56.272+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Database shutdown" @ txId: 47 checkpoint started...
2019-08-28 12:35:56.306+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Database shutdown" @ txId: 47 checkpoint completed in 34ms

由于 Neo4j 3.5.6 中引入的call dbms.checkpoint();导致的检查点

2019-08-28 12:31:56.463+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Call to dbms.checkpoint() procedure" @ txId: 47 checkpoint started...
2019-08-28 12:31:56.490+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Call to dbms.checkpoint() procedure" @ txId: 47 checkpoint completed in 27ms

由于备份运行导致的检查点

2019-08-28 12:33:30.489+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Full backup" @ txId: 47 checkpoint started...
2019-08-28 12:33:30.509+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Checkpoint triggered by "Full backup" @ txId: 47 checkpoint completed in 20ms

检查点指标也可用,并在metrics/和以下文件中详细说明

neo4j.check_point.check_point_duration.csv
neo4j.check_point.total_time.csv
neo4j.check_point.events.csv

控制事务日志裁剪

事务日志裁剪配置主要涉及指定应保留的事务日志数量。保留超过恢复所需的绝对最小量的主要原因是集群部署和在线备份的要求。由于数据库更新通过事务日志在集群成员和备份客户端之间进行通信,因此保留超过必要最小量允许仅传输增量更改(以事务的形式)而不是整个存储文件,这可以显著节省时间和网络带宽。对于 HA 部署、备份和因果集群中的只读副本都是如此。然而,对于因果集群中的核心成员,重要的不是事务日志,而是 Raft 日志内容。这种情况将在单独的知识库文章中讨论。

裁剪操作后保留的事务日志量由设置dbms.tx_log.rotation.retention_policy控制,它可以采用多种值。它们的形式是<数值> <度量单位>

<度量单位>可以是“files”、“size”、“txs”、“entries”、“hours”或“days”。

  • “files”确定裁剪后保留的最小事务日志文件数量。这意味着一旦执行检查点,将删除一些日志文件以至少保留指定数量的文件——例如,“5 files”的值将至少保留5个事务日志文件。

  • “size”的行为类似,但它不是计数文件,而是计数总文件大小。例如,“500M size”将至少保留500M价值的文件。

  • “txs”“entries”是同义词。它们的行为类似于上述,但它们计数文件中存在的事务,无论文件数量或大小。“100 txs”将在每次操作后至少保留100个事务价值的日志不被裁剪。

  • “hours”“days”衡量时间而不是大小或事务计数,但其他方面行为类似。将值设置为“20 hours”将确保日志中至少存在20小时的事务。