ORA-01555 快照太多 Old:rollback 名称为 "" 的段号太小

ORA-01555 Snapshot Too Old:rollback segment number with name "" too small

Oracle 存储过程在执行时突然抛出 ORA-01555。

select
a,b
from table1 S into a_var,b_var
where s.abc=systedate
and requiedate between add_months(sysdate,-2) and  sysdate
AND Currency= NVL(currency_CODe,USD)
group by S.actcount;

table1_invoice(1)=a_var;
table1_invoice(2)=b_var;

FORALL indx in 1..test.count SAVE EXCEPTIONS
insert into   table2   values
table1_invoice(indx);

当程序是 运行 并使用 table A 时,我在同一个 table.

上并行执行了索引重建

完成后,我在 table A 上执行了 gather stats。

这会产生错误 ORA-01555 吗?重建索引是否会消耗回滚段并删除未提交数据的旧快照?

我粘贴了伪代码。

我在同一个table上并行执行索引re-build。

这可能是您的原因。 ORA-1555 与能够为您提供一致的数据视图有关。例如,使用您的伪代码作为模板:

  • 您在上午 9 点打开光标
  • 您在上午 9 点开始从该游标获取数据,假设查询的总执行时间为 60 秒。
  • 假设您在该抓取的第 40 秒处。因为(你)读取数据不会阻止其他人更改它,你可能会遇到一些最近(比如 3 秒前)被其他人更改过的数据。
  • 我们无法为您提供该数据,因为我们必须向您显示上午 9 点(您的查询开始时)的数据。
  • 所以我们找到 3 秒前更改该数据的 t运行saction(s),并使用那些 t运行saction 写入的撤消信息来撤销更改。我们将继续这样做,直到数据现在看起来像上午 9 点时那样
  • 现在我们可以使用该(未完成)数据,因为它与您打开游标的时间一致。

那么 ORA-1555 适合什么地方呢?如果我们的查询 运行 一个小时怎么办?现在我们可能需要 undo-ing 其他 t运行 行动 运行 将近一个小时前。我们为(已完成的)t运行sactions 的撤消保留了这么多 space,因为我们需要在新的 t运行sactions 进来时释放它。我们抛出去掉旧的东西,因为那些 t运行sactions 已经提交。所以重新审视上面的处理,可能会发生以下情况:

  • 您在上午 9 点打开光标
  • 您在上午 9 点开始从该游标获取数据,假设查询的总执行时间为 60 秒。
  • 假设您在该抓取的第 40 秒处。因为(你)读取数据不会阻止其他人更改它,你可能会遇到一些最近(比如 3 秒前)被其他人更改过的数据。
  • 我们无法为您提供该数据,因为我们必须向您显示上午 9 点(您的查询开始时)的数据。
  • 因此我们找到 3 秒前更改该数据的 t运行saction(s) 并使用那些 t运行saction 写入的撤消信息来撤销更改。
  • 哦不!该撤消信息已被丢弃!!!

现在我们陷入困境,因为我们无法再向您提供上午 9 点时的数据,因为我们无法将一些更改的数据一直返回到上午 9 点。你要的数据snapshot时间太old.

因此出现“ORA-1555:快照太旧”

这就是为什么最常见的解决方案只是重试您的操作,因为现在您是在最近的时间开始查询。

因此您可以看到 - 在您查询时从其他会话对数据库进行的 activity 越多,遇到 ORA-1555 的风险就越大,因为撤消 space消耗得很快,因此我们可能会更快地扔掉旧东西。