Oracle:如何查找模式中上次更新(任何表)的时间戳?
有一个Oracle数据库模式(数据很小,但仍然有10-15个表左右)。它包含一种配置(路由表)。
有一个应用程序必须不时轮询此架构。不得使用通知。
如果架构中没有数据更新,应用程序应使用其当前的内存版本。
如果任何表有任何更新,应用程序应将所有表重新加载到内存中。
自给定关键点(时间或事务 ID)以来检查整个模式是否更新的最有效方法是什么?
我想象 Oracle 为每个模式保留一个事务 ID。那么应该有一种方法来查询这样的 ID 并保留它以便在下次轮询时进行比较。
我发现了这个问题,其中行级别上存在这样的伪列:
我认为在架构级别上存在类似的东西。
有人可以指出我正确的方向吗?
There is an Oracle database schema (very small in data, but still about 10-15 tables). It contains a sort of configuration (routing tables).
There is an application that have to poll this schema from time to time. Notifications are not to be used.
If no data in the schema were updated, the application should use its current in-memory version.
If any table had any update, the application should reload all the tables into memory.
What would be the most effective way to check the whole schema for update since a given key point (time or transaction id)?
I am imagined Oracle keeps an transaction id per schema. Then there should be a way to query such an ID and keep it to compare with at next poll.
I've found this question, where such an pseudo-column exists on a row level:
How to find out when an Oracle table was updated the last time
I would think something similar exists on a schema level.
Can someone please point me in the right direction?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不知道 Oracle 中有任何此类功能。请参阅下文。我能想到的最佳解决方案是在每个表上创建一个触发器来更新单行表或 上下文 与当前日期/时间。此类触发器可以位于表级别(而不是行级别),因此它们不会像大多数触发器那样带来那么多开销。
顺便说一句,Oracle 无法为每个模式保留一个事务 ID,因为一个事务可能会影响多个模式。或许可以使用 V$ 视图来跟踪事务回其影响的对象,但这并不容易,而且几乎肯定会比触发方案执行得更差。
事实证明,如果你有10g,你可以使用Oracle的闪回功能来获取这些信息。但是,您需要启用闪回(这会带来一些自身的开销),并且查询速度非常慢(可能是因为它并不是真正用于此用途):
为了避免“上次更新”表中的锁定问题,您可能希望将该更新放入使用自主事务的过程中,例如:
这将导致您的应用程序在某种程度上进行序列化:需要调用此过程的每个语句都需要等待前一个语句完成。 “上次更新”表也可能不同步,因为即使激活触发器的更新被回滚,其上的更新也将持续存在。最后,如果您的交易特别长,应用程序可能会在交易完成之前获取新的日期/时间,从而达不到目的。我越想这件事,就越觉得这是一个坏主意。
避免这些问题的更好解决方案是从触发器插入一行。这不会锁定表,因此不会有任何序列化,并且插入不需要异步进行,因此它们可以与实际数据一起回滚(并且在您的应用程序之前不可见)数据也可见)。应用程序将获得最大值,如果表已建立索引,这应该非常快(事实上,该表将是索引组织表的理想候选者)。唯一的缺点是您需要一个定期运行的作业来清除旧值,这样它就不会变得太大。
I'm not aware of any such functionality in Oracle.See below.The best solution I can come up with is to create a trigger on each of your tables that updates a one-row table or context with the current date/time. Such triggers could be at the table-level (as opposed to row-level), so they wouldn't carry as much overhead as most triggers.
Incidentally, Oracle can't keep a transaction ID per schema, as one transaction could affect multiple schemas. It might be possible to use V$ views to track a transaction back to the objects it affected, but it wouldn't be easy and it would almost certainly perform poorer than the trigger scheme.
It turns out, if you have 10g, you can use Oracle's flashback functionality to get this information. However, you'd need to enable flashback (which carries some overhead of it's own) and the query is ridiculously slow (presumably because it's not really intended for this use):
In order to avoid locking issues in the "last updated" table, you'd probably want to put that update into a procedure that uses an autonomous transaction, such as:
This will cause your application to serialize to some degree: each statement that needs to call this procedure will need to wait until the previous one finishes. The "last updated" table may also get out of sync, because the update on it will persist even if the update that activated the trigger is rolled back. Finally, if you have a particularly long transaction, the application could pick up the new date/time before the transaction is completed, defeating the purpose. The more I think about this, the more it seems like a bad idea.
The better solution to avoid these issues is just to insert a row from the triggers. This would not lock the table, so there wouldn't be any serialization and the inserts wouldn't need to be made asynchronously, so they could be rolled back along with the actual data (and wouldn't be visible to your application until the data is visible as well). The application would get the max, which should be very fast if the table is indexed (in fact, this table would be an ideal candidate for an index-organized table). The only downside is that you'd want a job that runs periodically to clean out old values, so it didn't grow too large.
dbms_stats.gather_table_stats 也可能有帮助:http://forums .oracle.com/forums/thread.jspa?threadID=607610
dbms_stats.gather_table_stats might also help: http://forums.oracle.com/forums/thread.jspa?threadID=607610