找出删除和更新的行

Posted

技术标签:

【中文标题】找出删除和更新的行【英文标题】:Find Out What Rows Where Deleted And Updated 【发布时间】:2014-07-22 08:30:48 【问题描述】:

是否有可能以某种方式找出从表中删除的行的主键?

同样,是否可以找出表中更新行的主键?

让我们考虑一个简单的用例:

我有两个时间戳

开始 结束

给我这两个时间戳之间更新/删除的所有行的主键。

表格内没有任何信息表明它们已更新。

【问题讨论】:

主键的可能值是多少?如果这些是连续的,那么您可以编写查询以查找从头到尾丢失的主键,结果输出是被删除的行。 Postgres 不存储有关表活动的信息,最好的方法是自己创建一个触发器来更新表上的一行以进行更新,或者只是将信息写入另一个位置更新或删除。 【参考方案1】:

不,PostgreSQL 不提供类似的内置功能。

为此,它必须浪费空间和 I/O 来跟踪大多数人永远不需要的东西。

如果您的主键是连续且单调的,那么您只需对generate_series 进行左反连接即可找到漏洞。但是,如果您使用 serial(即序列)来生成密钥,这将不起作用,因为任何回滚都会产生间隙,即使实际上没有插入任何内容以便随后被删除。

您需要添加一个审核触发器,以将您要跟踪的操作记录到单独的审核表中。您不能追溯执行此操作;您无法审核过去的事情。这是迄今为止最简单的选择。

另一种常见的解决方案是在应用程序级别将行标记为“已删除”,而不是从表中实际删除它们。例如,您可以在表中设置deleted_atdeleted_by 字段。您甚至可以使用带有ON INSERT OR UPDATE OR DELETE DO INSTEAD 触发器的视图使此应用程序透明。

还有一个 pg_audit 扩展正在开发中以使这更容易,但它还没有准备好。


半相关旁注:在 PostgreSQL 9.5 中,我认为这对于 最近 删除的行实际上是可能的,在 VACUUM 使用 C 清理它们之前延期。 9.5 将能够记录提交的时间戳,而 9.4 及更低版本则不能(它们只记录事务 ID)。因此,您可以通过检查 xmax 来找出哪个事务 ID 删除了一行,并从那里确定它被删除的时间戳。您需要一个 C 扩展,因为您必须对表进行“脏读”。

【讨论】:

“如果你的主键是连续的且单调的,那么你可以在 generate_series 上做一个左反连接”对我有用。我的用例是确定源数据库表中删除了哪些行,以便我可以删除目标数据库表中的相应记录。对于我的用例,这两个表必须是不同的数据库,并且目标数据库表中的行都具有对源数据库表行 ID 的反向引用。在这个用例中,如果我每次都获得一些额外的 ID 并不重要,因为替代方法是将所有剩余的源 ID 放入内存。谢谢!!! :-)【参考方案2】:

使用Netezza,不仅可以提取主键,还可以提取所有已删除的数据。

首先运行一个命令来暴露被删除的记录set show_deleted_records=true;

然后查询数据库。

Select deletexid,*
 from table_name
 where deletexid>0

这个技巧对于恢复错误很有用。请注意,在reclaimgroom 之后不再保留已删除的记录。

【讨论】:

以上是关于找出删除和更新的行的主要内容,如果未能解决你的问题,请参考以下文章

如何设计数据库以轻松更新和删除形成二进制类型概念的行?

存储更新、插入或删除语句影响了意外数量的行

SQL的更新和删除

如何在 SQL Server 触发器中复制插入、更新、删除的行

使用Swift 3和CoreData删除表视图行

ADO.NET DBConcurrencyException - 尝试更新已删除的行