【问题标题】:How to find out when an Oracle table was updated the last time如何找出上次更新 Oracle 表的时间
【发布时间】:2010-09-20 21:02:10
【问题描述】:

我能否查明对 Oracle 数据库中的表执行最后一次 INSERT、UPDATE 或 DELETE 语句的时间?如果是,如何查明?

一点背景:Oracle 版本是 10g。我有一个定期运行的批处理应用程序,从单个 Oracle 表中读取数据并将其写入文件。如果自上次作业运行以来数据没有更改,我想跳过此操作。

该应用程序是用 C++ 编写的,并通过 OCI 与 Oracle 通信。它使用“普通”用户登录 Oracle,所以我不能使用任何特殊的管理工具。

编辑:好的,“特殊管理员的东西”并不是一个很好的描述。我的意思是:除了从表中选择和调用存储过程之外,我什么也做不了。如果想在 2010 年之前完成,那么更改数据库本身的任何内容(例如添加触发器)都不是一个选项。

【问题讨论】:

  • 是的...... 2010 年的评论是关于我接受它的 DBA 的缓慢性?
  • 嗯,有点。它们很慢,但正如我在之前的评论中所说,我理解它们。如果这个数据库有问题,它会变得非常丑陋,非常快。你可以在那里拿东西,但只有在被一群人分析到地狱之后。
  • 由于我还不能评论答案(我是新来的),我想评论一下,我发现 CDC 已从 Oracle 12c 中删除,以促使人们购买 GoldenGate。 docs.oracle.com/database/121/UPGRD/deprecated.htm#UPGRD60083

标签: oracle oracle-call-interface


【解决方案1】:

您需要在插入、更新、删除时添加一个触发器,将另一个表中的值设置为 sysdate。

当您运行应用程序时,它会读取该值并将其保存在某处,以便下次运行时它具有要比较的引用。

你会考虑“特殊的管理员东西”吗?

最好描述一下你实际在做什么,这样你就能得到更清晰的答案。

【讨论】:

    【解决方案2】:

    您能否对结果运行某种校验和并将其存储在本地?那么当您的应用程序查询数据库时,您可以比较它的校验和并确定是否应该导入它?

    看来您可以使用ORA_HASH 函数来完成此操作。

    更新:另一个好资源:10g’s ORA_HASH function to determine if two Oracle tables’ data are equal

    【讨论】:

    • 听起来很有趣。您能否举一个为表创建哈希的示例?
    【解决方案3】:

    批处理写入文件需要多长时间?最简单的方法可能是让它继续运行,然后将文件与上一次运行的文件副本进行比较,看看它们是否相同。

    【讨论】:

    • 这就是问题所在:我不只是写数据,还需要以复杂的方式处理它。这需要几个小时,而这是我试图避免的。
    【解决方案4】:

    向您的 DBA 询问有关审计的问题。他可以使用以下简单命令开始审计:

    AUDIT INSERT ON user.table
    

    然后您可以查询表 USER_AUDIT_OBJECT 以确定自上次导出以来您的表中是否有插入。

    google for Oracle 审计了解更多信息...

    【讨论】:

    • 谢谢。我想这就是它应该完成的方式。可悲的是,“询问 DBA”往往相当复杂。他们对改变东西真的很偏执。我很理解他们。如果这个数据库有什么问题,事情往往会变得丑陋。
    【解决方案5】:

    由于您使用的是 10g,因此您可能会使用 ORA_ROWSCN 伪列。这为您提供了导致行更改的最后一个 SCN(系统更改号)的上限。由于这是一个递增序列,因此您可以存储您见过的最大 ORA_ROWSCN,然后仅查找 SCN 大于该值的数据。

    默认情况下,ORA_ROWSCN 实际上是在块级别维护的,因此对块中任何行的更改都会更改块中所有行的ORA_ROWSCN。如果我们谈论的是“正常”数据访问模式,那么如果目的是尽量减少多次处理的行数而不做任何更改,这可能就足够了。您可以使用 ROWDEPENDENCIES 重建表,这将导致在行级别跟踪 ORA_ROWSCN,从而为您提供更精细的信息,但需要一次性重建表。

    另一种选择是配置更改数据捕获 (CDC) 之类的东西,并使您的 OCI 应用程序成为表更改的订阅者,但这也需要一次性配置 CDC。

    【讨论】:

    • 哇,这真的很酷。我错过了那个伪列。但我不会使用 CDC ......对于他的目的来说太复杂了。我会使用 DCN(数据库更改通知)。
    • 什么是一行被删除?我怎样才能知道?
    【解决方案6】:

    Oracle 可以监视表的变化,当发生变化时,可以在 PL/SQL 或 OCI 中执行回调函数。回调获取一个对象,该对象是已更改的表的集合,并且具有已更改的 rowid 的集合,以及操作的类型、Ins、upd、del。

    所以你甚至不去餐桌,你就坐等被叫。只有有更改要写,你才会去。

    它叫做Database Change Notification。正如贾斯汀所说,它比 CDC 简单得多,但两者都需要一些花哨的管理内容。好的部分是这些都不需要更改应用程序。

    需要注意的是,CDC 适用于大容量表,而 DCN 则不然。

    【讨论】:

    • FWIW,我最近发现 12c 的 PDB 不支持 CQN(即 CDN)。希望它会在未来。
    【解决方案7】:

    我真的迟到了,但我是这样做的:

    SELECT SCN_TO_TIMESTAMP(MAX(ora_rowscn)) from myTable;
    

    对于我的目的来说已经足够接近了。

    【讨论】:

    • 只要上次更新您的表不是太久之前就可以工作。否则你会得到一个错误,所以最安全的做法是先做:left join sys.smon_scn_time tiemposmax on myTable.ora_rowscn
    【解决方案8】:

    请使用以下语句

    select * from all_objects ao where ao.OBJECT_TYPE = 'TABLE'  and ao.OWNER = 'YOUR_SCHEMA_NAME'
    

    【讨论】:

    • 你把问题转向了不同的方向
    【解决方案9】:
    SELECT * FROM all_tab_modifications;
    

    【讨论】:

    • 这将要求您首先收集表上的统计信息,因为它仅显示上次收集统计信息后的更改。
    • 这看起来是个好主意,但实际上它有很多注意事项:并非所有 DML 都能保证得到反映,它不是即时的,可能需要运行 dbms_stats.flush_database_monitoring_info 以使其保持最新,在统计数据收集后,该视图中没有条目,并且它已经记录了提交之前的更改
    【解决方案10】:

    如果有人仍在寻找答案,他们可以使用 Oracle 10g 附带的Oracle Database Change Notification 功能。它需要CHANGE NOTIFICATION 系统权限。您可以注册侦听器何时触发返回给应用程序的通知。

    【讨论】:

      【解决方案11】:

      如果在服务器上启用了审核,只需使用

      SELECT *
      FROM ALL_TAB_MODIFICATIONS
      WHERE TABLE_NAME IN ()
      

      【讨论】:

        猜你喜欢
        • 2011-10-10
        • 1970-01-01
        • 2014-01-03
        • 2014-07-01
        • 2019-10-26
        • 2010-09-23
        • 1970-01-01
        • 2013-03-31
        相关资源
        最近更新 更多