我可以回滚我已经提交的交易吗?(数据丢失)

SSS*_*SSS 48 database postgresql data-recovery

我提交了一个错误的UPDATE声明并丢失了一些数据.

在我已经承诺之后,现在可以回滚吗?

有帮助吗?

ROLLBACK
Run Code Online (Sandbox Code Playgroud)

NOTICE: there is no transaction in progress.

Cra*_*ger 93

不,您无法撤消,回滚或撤消提交.

停止数据库!

(注意:如果您从文件系统中删除了数据目录,请不要停止数据库.以下建议适用于意外提交DELETE或类似,而不是rm -rf /data/directory方案).

如果此数据很重要,请立即停止数据库,不要重新启动它.使用pg_ctl stop -m immediate以便在关闭时不运行检查点.

提交后,您无法回滚事务.您需要从备份中恢复数据,或使用必须在事故发生设置的时间点恢复.

如果您没有设置任何PITR/WAL归档并且没有备份,那么您真的遇到了麻烦.

紧急缓解

一旦你的数据库已经停止,你应该让整个数据目录的文件系统级别-包含文件夹base,pg_clog等复制这一切到一个新的位置.不要对新位置的副本执行任何操作,如果您没有备份,则唯一希望恢复数据.如果可以,请在某些可移动存储上制作另一个副本,然后从计算机上拔下该存储.请记住,您绝对需要数据目录的每个部分,包括pg_xlog等等.没有任何部分是不重要的.

具体如何制作副本取决于您正在运行的操作系统.数据目录取决于您正在运行的操作系统以及如何安装PostgreSQL.

一些数据可以幸存下来的方式

如果你足够快地停止你的数据库,你可能希望从表中恢复一些数据.这是因为PostgreSQL使用多版本并发控制(MVCC)来管理对其存储的并发访问.有时它会将您更新的行的新版本写入表中,保留旧版本但标记为"已删除".一段时间后autovaccum出现并将行标记为可用空间,因此它们可以被后来INSERT或者覆盖UPDATE.因此,UPDATEd行的旧版本可能仍然存在,存在但不可访问.

此外,Pg分两个阶段写作.第一个数据被写入预写日志(WAL).只有一旦它被写入WAL并命中磁盘,它就会被复制到"堆"(主表),可能会覆盖那里的旧数据.WAL内容bgwriter由定期检查点复制到主堆.默认情况下,检查点每5分钟发生一次.如果你设法在检查点发生之前停止数据库并通过硬杀死它,拔掉机器上的插头或使用pg_ctlin immediate模式来停止数据库,你可能已经在检查点发生之前捕获了数据,所以你的旧数据是更有可能仍然在堆中.

现在您已经为数据目录制作了完整的文件系统级副本,如果您确实需要,可以启动数据库备份; 数据仍然会消失,但你已经做了尽可能给自己一些希望恢复它的希望.鉴于选择我可能会保持数据库关闭只是为了安全.

复苏

您现在可能需要聘请PostgreSQL内部的专家来帮助您进行数据恢复尝试.准备支付专业人员的时间,可能是相当多的时间.

我在Pg邮件列表上发布了这个帖子,并且ВикторЕгоров链接到了 ps_dirtyread上的depesz帖子,看起来就像你想要的那样,虽然它没有恢复TOASTed数据所以它的实用性有限.尝试一下,如果你很幸运,它可能会起作用.

请参阅:GitHub上的pg_dirtyread.

我已经删除了我在本节中所写的内容,因为它已被该工具淘汰.

另请参阅PostgreSQL行存储基础知识

预防

请参阅我的博客文章防止PostgreSQL数据库损坏.


在半相关的附注中,如果您使用两阶段提交,则可以ROLLBACK PREPARED进行准备提交但未完全提交的转换.这是关于你回滚已经提交的交易的最接近的,并不适用于你的情况.