你能锁定Oracle序列吗?

时间:2011-04-08 23:36:59

标签: sql oracle sequence

是否可以锁定Oracle序列,以便尝试在其上使用nextval的任何会话都会阻塞,直到我完成脚本为止?

如果有不同的方式,我会解释我在做什么。我正在准备一个模式来使用流进行双向复制。我想确保所有主键序列产生唯一值。我通过将序列递增1直到最后一位数为1然后将增量更改为100来执行此操作。在另一台服务器上,我执行相同操作直到最后一位数为2.这样,服务器1始终生成主键XXXXX01和服务器2 XXXXX02。

问题是这是一个24x7数据库,我在调整序列时无法阻止所有活动。如果我能在短时间内获得专属锁,我可以可靠地完成。

5 个答案:

答案 0 :(得分:3)

最简单的解决方案(在我看来)是为服务器1使用奇数,为服务器2使用偶数。这也消除了序列化的需要。

create sequence server1_seq increment by 2 start with 1;
create sequence server2_seq increment by 2 start with 2;

这将产生一系列值,如:

Server 1  Server 2
--------  --------
   1          2
   3          4
   5          6 
   7          8
   9         10

通过使用更大的增量(以及每个服务器的不同起始值),可以进一步扩展此解决方案以处理两个以上的服务器。

话虽如此,如果您打算随着时间的推移添加更多服务器,请 NOT 使用此方法。您必须使所有数据库脱机并从头开始重建表。

答案 1 :(得分:3)

我个人喜欢使用Ronnis建议使用单独的非重叠序列的想法。

要考虑的另一个选择是复合主键。

  1. 如果您能够向数据模型添加列,则添加一个不同的标识符,具体取决于运行该进程的服务器。

  2. 如果无法添加列,则可以将列数据类型更改为VARCHAR2,并将其设置为复合;例如在服务器1上,您可以将“1-”连接到序列值,例如因此,“1-103450”不会与服务器2上生成的“2-103450”冲突。

  3. 无论哪种方式,这都不会在将来添加更多服务器时遇到任何问题。

答案 2 :(得分:1)

不,你无法锁定一个序列。您可以尝试以所需状态重新创建序列。它会在短时间内引起问题。

答案 3 :(得分:1)

如果您只想暂时停止会话从序列中获取值,您可以撤消对它的访问权限。当然,除非您的用户以序列的所有者身份登录。

REVOKE SELECT ON mysequence FROM username;

注意:它本身不是锁;而不是等待,他们会得到一个Oracle错误(我认为无效的标识符)。

答案 4 :(得分:0)

看来您实际上可以锁定一个序列。

SELECT SEQ_NAME.nextval FROM dual FOR UPDATE [NOWAIT];

在Oracle 11 XE上测试。还可以看看https://www.experts-exchange.com/questions/20181432/lock-wait-on-sequence.htmlhttps://geraldonit.com/oracle/database/oracle-database-locktypes/