不,您无法撤消、回滚或反转提交。
停止数据库!
(注意:如果您从文件系统中删除了数据目录,请不要停止数据库。以下建议适用于意外提交DELETE
或类似的,不是rm -rf /data/directory
设想)。
如果这个数据很重要的话立即停止您的数据库并且不要重新启动它。使用pg_ctl stop -m immediate
以便在关闭时不运行检查点。
事务一旦提交就无法回滚。您将需要从备份中恢复数据,或使用时间点恢复,必须已设置before事故发生了。
如果您没有设置任何 PITR / WAL 归档并且没有备份,那么您就有麻烦了。
紧急缓解措施
一旦数据库停止,您应该制作整个数据目录的文件系统级副本 - 包含以下内容的文件夹base
, pg_clog
等复制所有的到一个新的地点。不要对新位置中的副本执行任何操作,如果您没有备份,这是恢复数据的唯一希望。如果可以的话,在可移动存储上再制作一份副本,然后从计算机上拔下该存储。请记住,你需要绝对每个部分数据目录,包括pg_xlog
等等。没有一部分是不重要的。
具体如何制作副本取决于您运行的操作系统。数据目录的位置取决于您运行的操作系统以及 PostgreSQL 的安装方式。
一些数据可以保存下来的方法
如果您足够快地停止数据库,您可能有希望从表中恢复一些数据。那是因为 PostgreSQL 使用多版本并发控制(MVCC)管理对其存储的并发访问。有时会写新版本您更新到表的行的数量,保留旧行但标记为“已删除”。一段时间后自动真空出现并将行标记为可用空间,以便以后可以覆盖它们INSERT
or UPDATE
。因此,旧版本的UPDATE
d 行可能仍然存在,但无法访问。
此外,Pg 分两个阶段写入。第一个数据被写入预写日志(WAL)。只有当它被写入 WAL 并命中磁盘后,它才会被复制到“堆”(主表),可能会覆盖那里的旧数据。 WAL 内容被复制到主堆bgwriter
并通过定期检查站。默认情况下,检查点每 5 分钟发生一次。如果您设法在检查点发生之前停止数据库,并通过硬终止数据库、拔掉机器上的插头或使用pg_ctl
in immediate
模式下,您可能已经在检查点发生之前捕获了数据,因此您的旧数据更有可能仍在堆中。
现在您已经制作了数据目录的完整文件系统级副本,如果确实需要,您可以启动数据库备份;数据仍然会消失,但您已经尽了一切努力,给自己一些恢复数据的希望。如果可以选择,为了安全起见,我可能会关闭数据库。
Recovery
您现在可能需要聘请 PostgreSQL 内部专家协助您尝试数据恢复。准备好支付专业人士的时间,可能是相当长的时间。
我在 Pg 邮件列表上发布了有关此内容的信息,并且Егоров 链接到 depesz 在 pg_dirtyread 上的帖子,这看起来正是你想要的,尽管它没有恢复TOAST
编辑数据,因此其实用性有限。尝试一下,如果幸运的话可能会成功。
See: GitHub 上的 pg_dirtyread.
我删除了我在本节中编写的内容,因为它已被该工具废弃。
也可以看看PostgreSQL 行存储基础知识
预防
请参阅我的博客条目防止 PostgreSQL 数据库损坏.
在半相关的旁注中,如果您使用两阶段提交你可以ROLLBACK PREPARED
对于准备提交但未完全提交的事务。这大约是您最接近回滚已提交事务的方法,并且不适用于您的情况。