【问题标题】:Why does ora_rowscn change without updating a table为什么ora_rowscn在不更新表的情况下发生变化
【发布时间】:2015-08-11 07:18:25
【问题描述】:

我与ora_rowscn 一起跟踪表中更改的行并处理更新的行。

上周我注意到,对于我使用rowdependencies 创建的一些(不是全部)表,ora_rowscn 发生更改,而表上没有任何事务。我的意思是,如果我选择max(ora_rowscn),我总是会得到更高的数字。

这是我如何创建表格的示例

  1. 创建表

    create table test ( test_id number, txt varchar2(5) ) rowdependencies;
    
  2. 往表中插入一些数据

    insert into test values(1,'a');
    insert into test values(2,'b');
    insert into test values(3,'c');
    
  3. 使用 ORA_ROWSCN 多次查询表

    select max(ora_rowscn),max(b.current_scn) from test a, v$database b
    

我每次查询都会得到一个更高的max(ora_rowscn)

在 MetaLink 上我发现了两个报告的错误(错误 14093863、错误 9814923),它们似乎是同一个问题,但设置为不是错误。

为什么会发生,有什么解决方案可以让它工作或修复它?

【问题讨论】:

  • 我没看到; max(b.current_scn) 当然在增加,但 max(ora_rowscn) 保持稳定。但后来你说不是每张桌子,这也很有趣。您正在运行哪个补丁级别?您是否真的在测试表中看到了这种行为?
  • 我们使用的是 11.2.0.3 和 11.2.0.4,但我不确定它是否也在 11.2.0.4 上。机器。我不能给你任何进一步的信息,你可以做些什么来重新调整它。我不知道表开始出现这种行为的原因是什么。我家里没有 DB EE,这是我工作中的一个例子。
  • 在您的工作机器上,您在此处使用的test 表是否显示了问题?或者,如果您完全按照您在此处所做的那样构建了test 表,它会是不显示问题的表之一吗?您确定您没有某些进程会触及其ora_rowscn 值增加的表中的行吗?即使这些进程实际上并未更改数据,也许它们正在运行 UPDATE 将一行中的值设置为其当前值?
  • @JustinCave 不是测试表,我有临时表,我每天一次从文件中导入数据(包含更多列),带有主键和一些简单的索引,但我不相信它可能是一个问题。 test table 只是一个简单的例子。是的,我确定在此表上没有进行更新、插入和其他DMLs 的进程。在我的帖子中,我发布了一些具有相同问题的金属链接错误,因此问题存在。我想一定是更复杂的内存(PGA/SGA?)问题,是什么让Oracle感到困惑。
  • 您的暂存表(我假设是您看到的地方)是外部表吗?还是由 SQL*Loader 或其他进程填充?

标签: database oracle oracle11g


【解决方案1】:

我们询问了我们的 Oracle 联系人并得到了以下答案。

“这不是错误,它的未记录功能。”

ORA_ROWSCN 是在清除块时生成的 交易。可能会发生两种块清除:快速 清理和延迟清理。

请注意,对于延迟清除,事务的确切 commit-scn 当由该事务修改的块时可能不可用 清理干净,因此我们可能会得到 commit-scn 的上限。 因此,对于那些快速清除的块,我们可以更新 ORA_ROWSCN 交易提交后;

但是,对于那些延迟清除的块,我们只更新 下次我们触摸块时对应的 ORA_ROWSCN (DML 或 选择)。可能是几个小时后。有可能我们是 在其他表中做一堆工作人员(因此 SCN 会增加) 而且我们没有在这个表 T 中做任何事务。但是当我们 查询表 T 的 ORA_ROWSCN 我们仍然可以得到最近的数字 对于 SCN,因为块刚刚被清除(但是 交易已在几个小时前提交)。这个 ORA_ROWSCN 是 最后一个事务的提交时间的上限。

看起来问题确实存在。如果我理解正确,这种情况没有简单的解决方案。

我希望它有助于了解其他用户的问题。

在这里我找到了一些关于块清除的更多不安全的信息

【讨论】:

    【解决方案2】:

    怎么样:

    select 
      max(a.test_id) KEEP (DENSE_RANK FIRST ORDER BY a.ora_rowscn desc),
      max(a.txt) KEEP (DENSE_RANK FIRST ORDER BY a.ora_rowscn desc),
      max(a.rowid) KEEP (DENSE_RANK FIRST ORDER BY a.ora_rowscn desc),
      max(a.ora_rowscn)
    from test a;
    

    这应该标识正在更改的行。

    【讨论】:

    • 抱歉,我应该如何处理您的查询?我的问题是,为什么 ora_rowscn 在没有任何变化的情况下递增
    • 这应该返回行的rowid,具有最大的ora_rowscn。因此,您可以看到特定行是否正在更改它的 scn 或是否所有行都受到影响。您也可以将 rowid 转换为文件号和块 ID 以使用更改数据库转储块。或者您可以查看 logminer 以查看涉及特定 rowid 的查询。
    • 所以这真的不是一个答案(但查询太长无法评论),它可以帮助您进一步调查
    • 谢谢,但这并不能帮助我解决我的问题。 :)
    • @hotfix 有一些随机的 SGA 损坏,这导致了一些奇怪的行为。但是数据库块的“一致”更改应该通过重做日志写入来进行。因此,通过使用 logminner,您可以证明/反驳后台数据库中是否发生了某些事情。数据库块的转储也可以显示块内的行顺序是否正在改变(例如)。此外,视图 v$bh 可能会为您提供一些信息。当您知道文件编号和块 ID 后,您可以在 Unix 上使用 dd 手动转储数据文件块,这样您就可以看到这是在磁盘上还是仅在缓冲区缓存中发生变化。
    猜你喜欢
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 2019-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-19
    • 2020-11-10
    相关资源
    最近更新 更多