Oracle:如何查找架构中上次更新(任何表)的时间戳?

时间:2011-07-21 12:01:10

标签: sql oracle schema timestamp sql-update

有一个Oracle数据库架构(数据非常小,但仍然有大约10-15个表)。它包含一种配置(路由表)。

有一个应用程序必须不时轮询此架构。不得使用通知。

如果架构中没有数据更新,则应用程序应使用其当前的内存中版本。

如果任何表有任何更新,应用程序应该将所有表重新加载到内存中。

从给定的关键点(时间或事务ID)开始,检查整个架构的最有效方法是什么?

我想象Oracle会为每个架构保留一个事务ID。然后应该有一种方法来查询这样的ID并保持与下次轮询比较。

我发现了这个问题,在行级别上存在这样的伪列:

How to find out when an Oracle table was updated the last time

我认为在架构级别上存在类似的东西。

有人可以指出我正确的方向吗?

2 个答案:

答案 0 :(得分:12)

我不知道Oracle中有任何此类功能。见下文。

我能想出的最佳解决方案是在每个表上创建一个触发器,用于更新单行表或context以及当前日期/时间。这样的触发器可以在表级(而不是行级),因此它们不会像大多数触发器那样承载过多的开销。

顺便说一句,Oracle无法为每个架构保留事务ID,因为一个事务可能会影响多个架构。有可能使用V $视图来跟踪事件回到它受影响的对象,但这并不容易,而且几乎肯定会比触发方案更差。

事实证明,如果你有10g,你可以使用Oracle的闪回功能来获取这些信息。但是,你需要启用闪回(它带有一些自己的开销)并且查询速度非常慢(可能是因为它并不是真正用于此用途):

select max(commit_timestamp) 
from FLASHBACK_TRANSACTION_QUERY 
where table_owner = 'YOUR_SCHEMA' 
      and operation in ('INSERT','UPDATE','DELETE','MERGE') 

为了避免“最后更新”表中的锁定问题,您可能希望将该更新放入使用自治事务的过程中,例如:

create or replace procedure log_last_update as
pragma autonomous_transaction;
begin
   update last_update set update_date = greatest(sysdate,update_date);
   commit;
end log_last_update;

这将导致您的应用程序在某种程度上序列化:需要调用此过程的每个语句都需要等到上一个语句完成。 “上次更新”表也可能不同步,因为即使激活触发器的更新被回滚,其上的更新也将保持不变。最后,如果您有特别长的交易,应用程序可以在交易完成之前获取新的日期/时间,从而违背目的。我越是想到这一点,它看起来就越糟糕。


避免这些问题的更好解决方案就是从触发器中插入一行。这不会锁定表,因此不会有任何序列化,并且不需要异步进行插入,因此它们可以与实际数据一起回滚(并且在应用程序之前不会显示数据也是可见的)。应用程序将获得max,如果表被索引,则应该非常快(实际上,此表将是索引组织表的理想候选者)。唯一的缺点是你需要一个定期运行的工作来清理旧值,所以它不会变得太大。

答案 1 :(得分:3)

dbms_stats.gather_table_stats 也可能有所帮助:http://forums.oracle.com/forums/thread.jspa?threadID=607610

   4. Statistics is considered to be stale, when the change is over 10% of current rows. 
   (As of 11g, this value can be customized per objects. Cool feature)


    .
    . 
    .

exec dbms_stats.gather_table_stats(user, 'T_STAT');

select * from sys.dba_tab_modifications where table_name = 'T_STAT';
No row selected

select stale_stats from sys.dba_tab_statistics where table_name = 'T_STAT';
NO

insert into t_stat select rownum from all_objects where rownum <= 20;

select * from sys.dba_tab_modifications where table_name = 'T_STAT';
No rows selected <-- Oops
select stale_stats from sys.dba_tab_statistics where table_name = 'T_STAT';
NO  <-- Oops

exec dbms_stats.flush_database_monitoring_info;

select * from sys.dba_tab_modifications where table_name = 'T_STAT';
TABLE_OWNER TABLE_NAME  PARTITION_NAME  SUBPARTITION_NAME   INSERTS UPDATES DELETES TIMESTAMP   TRUNCATED   DROP_SEGMENTS
UKJA        T_STAT      20  0   0   2008-01-18 PM 11:30:19  NO  0

select stale_stats from sys.dba_tab_statistics where table_name = 'T_STAT';
YES