异步提交 是一种选项,它允许事务更快地完成,但代价是如果数据库崩溃,最近的事务可能会丢失。在许多应用程序中,这是一个可以接受的权衡。
如上一节所述,事务提交通常是 同步 的:服务器会等待事务的WAL记录被刷新到永久存储器中,然后再向客户端返回成功指示。因此,客户端可以保证,即使在服务器在之后立即崩溃的情况下,报告已提交的事务也会被保留。但是,对于短事务,此延迟是事务总时间的主要组成部分。选择异步提交模式意味着服务器在事务逻辑完成之后立即返回成功,即在事务生成的WAL记录实际上写入磁盘之前。这可以为小型事务提供显著的吞吐量提升。
异步提交引入了数据丢失的风险。在向客户端报告事务完成与事务真正提交(即保证在服务器崩溃时不会丢失)之间存在一个短暂的时间窗口。因此,如果客户端将采取依赖于事务将被记住的假设的外部操作,则不应使用异步提交。例如,银行当然不会对记录 ATM 现金提取的事务使用异步提交。但在许多情况下,例如事件日志记录,不需要这种强保证。
使用异步提交所承担的风险是数据丢失,而不是数据损坏。如果数据库崩溃,它将通过重播来恢复WAL到最后一个已刷新的记录为止。因此,数据库将恢复到一致的状态,但任何尚未写入磁盘的事务将不会反映在该状态中。因此,净效应是丢失最后几个事务。由于事务按提交顺序重播,因此不会引入不一致——例如,如果事务 B 进行了依赖于先前事务 A 的效果的更改,则不可能 A 的效果丢失而 B 的效果保留下来。
用户可以选择每个事务的提交模式,因此可以同时运行同步和异步提交事务。这允许在事务持久性的性能和确定性之间灵活地权衡。提交模式由用户可设置的参数 synchronous_commit 控制,它可以通过设置配置参数的任何方式来更改。任何一个事务使用的模式取决于事务提交开始时 synchronous_commit
的值。
某些实用程序命令,例如 DROP TABLE
,强制同步提交,而不管 synchronous_commit
设置如何。这是为了确保服务器文件系统与数据库的逻辑状态之间的一致性。支持两阶段提交的命令,例如 PREPARE TRANSACTION
,也始终是同步的。
如果数据库在异步提交与事务的WAL记录写入之间的时间窗口内崩溃,则该事务期间发生的更改 将 会丢失。时间窗口的持续时间有限,因为后台进程(““WAL 编写器”)每 wal_writer_delay 毫秒将未写入的WAL记录刷新到磁盘。时间窗口的实际最大持续时间是 wal_writer_delay
的三倍,因为 WAL 编写器在繁忙期间被设计为优先写入整个页面。
立即模式关闭相当于服务器崩溃,因此会导致任何未刷新的异步提交丢失。
异步提交提供的行为与设置 fsync = off 不同。fsync
是一个服务器范围的设置,它将改变所有事务的行为。它会禁用 PostgreSQL 中尝试同步写入数据库不同部分的所有逻辑,因此系统崩溃(即硬件或操作系统崩溃,而不是 PostgreSQL 本身的故障)会导致数据库状态的任意严重损坏。在许多情况下,异步提交提供了通过关闭 fsync
可以获得的大部分性能提升,但没有数据损坏的风险。
commit_delay 也听起来与异步提交非常相似,但它实际上是一种同步提交方法(事实上,在异步提交期间忽略 commit_delay
)。commit_delay
会在事务刷新WAL到磁盘之前造成延迟,希望一个由一个此类事务执行的刷新也可以服务于大约在同一时间提交的其他事务。可以将此设置视为一种增加事务可以加入一个即将参与单次刷新的组的时间窗口的方法,以便在多个事务之间分摊刷新的成本。
如果您在文档中看到任何不正确的内容、与您对特定功能的体验不符或需要进一步澄清,请使用 此表格 报告文档问题。