【问题标题】:Safety of Oracle Package VariablesOracle 包变量的安全性
【发布时间】:2012-03-31 11:53:02
【问题描述】:

如果我在Oracle(8)中有一个包变量,并且在从多个触发器调用的函数中对其进行了修改(递增),是否有可能一次调用该函数多次?

具体来说,我们在业务事务中有序列号,因此我们有一个函数可以返回特定会话的序列中的下一个数字,然后有一个函数创建一个增量表示序列号的包变量。基本上,函数类似于:

function get_seq_num return number is
  ret number;
begin
  if g_seq_num is not null then
    ret := g_seq_num;
    g_seq_num := g_seq_num + 1;
  else
    g_seq_num := 1;
  end if;
  return ret;
end get_seq_num;

似乎有 2 个触发器试图为给定事务记录相同的 seq_num,但我无法完全弄清楚原因(除非它们同时运行,我认为它们不会同时运行)。

**NOTE1:为了记录,这是我继承的遗留代码,可能无法更改它,无论它的做法有多糟糕......

** 注意2:因为我认为该函数不可能同时执行多次,所以我正在研究是否可以在其他任何地方更新record_seq_num....

【问题讨论】:

  • 如果g_seq_num 的当前值为NULL,您的函数似乎将返回NULL。不确定这是否是期望的行为——或者它可能永远不会发生,如果包变量被初始化为非 NULL 值——但这似乎很奇怪。

标签: oracle variables package


【解决方案1】:

我认为你的问题的答案是肯定的。

每个数据库会话都有自己的包变量副本。它们不在会话之间共享。您所描述的不是创建序列的安全方法。如果您有一个会话多次命中该函数,则其包变量的副本将增加,但另一个会话不会。所以会话 A 可能会返回 1、2、3 ...,然后会话 B 会返回 1。

此外,当会话关闭或包重新编译时,您的包变量将被丢弃。

这是关于“Global variable across different sessions”的向 Tom 提问

您应该使用 Oracle sequence

【讨论】:

  • 也许我不清楚...整个目标是让它们在会话中独立。每个 Session 都有自己的 TXN_ID(按顺序设置),但是每个事务都有许多步骤(这是我们使用此序列号的地方)。例如,会话 A 获得 Txn_id 12345(来自序列)和该事务日志中的某些事件作为 Seq_num 1,2,3,4...。然后会话 B 获得 TXN_ID 12346,但也记录 seq_num 1,2,3... . 问题是 TXN x 似乎与 SEQ y 有一些重复。我会查看 Ask Tom 参考资料。
  • 啊,那不一样。您是否可以从不同的会话中调用具有相同 TXN_ID 的包,或者这一切都来自同一个事务?
  • 发现问题(干杯)正是正在发生的事情,只是没有意识到。第二个函数是使用“SELECT max(Seq_Num) from where tXN_ID = x”来计算出我们在哪里并从那里添加东西。由于那时还没有提交,它假设我们从头开始并尝试插入我们已经拥有的值....
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-11
  • 2013-09-23
相关资源
最近更新 更多