你能锁定Oracle序列吗?

3
有没有可能锁定Oracle序列,以便任何试图在其上使用nextval的会话都会被阻塞,直到我完成脚本?
我将解释一下我的做法,以防有其他方法。 我正在准备一个模式,以使用流进行双向复制。 我想确保所有主键序列产生唯一值。 我通过将序列递增1直到最后一位为1,然后将增量更改为100来实现这一点。 在另一台服务器上,我做同样的事情,直到最后一位是2。 这样,服务器1始终生成主键XXXXX01,服务器2生成XXXXX02。
问题是这是一个24x7数据库,我无法在调整序列时停止所有活动。 如果我可以短时间获得独占锁,我可以可靠地完成它。

您可以将序列的当前值设为最大值。 - uncaught_exceptions
在这种情况下,正确的解决方案通常是使用GUID作为键,而不是递增索引,虽然GUID几乎肯定比您的键字段大,但提供了几乎完全安全来避免这个问题。 - MikeT
5个回答

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

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

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


问题不在于如何设置序列,而在于尝试将它们设置为实时数据库上的正确值。 - JOTN
@JOTN,啊,抱歉我误解了问题。 - Ronnis

2

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


谢谢。我想在一个安静的时间试着完成它,并希望在另一次会话到达之前设置好顺序。如果我没有全部完成,我可以再次运行脚本。 - JOTN

2
我个人认为使用像Ronnis建议的分离的不重叠序列的想法很好。
另一个考虑的选择是使用复合主键。
1.如果您可以向数据模型添加列,则添加一个标识符,该标识符根据进程在哪个服务器上运行而设置不同。
2.如果您无法添加列,则可以将列数据类型更改为VARCHAR2,并将其设置为复合;例如,在服务器1上,您将连接序列值的“1-”,例如,“1-103450”因此不会与在服务器2上生成的“2-103450”发生冲突。
无论哪种方式,这都不会遇到未来添加更多服务器时的任何问题。

1

如果您只是想暂时阻止会话从序列中获取值,那么您可以撤销对其的访问权限。当然,除非您的用户正在以序列所有者的身份登录。

REVOKE SELECT ON mysequence FROM username;

注意:它并不是一个锁,而是会收到 Oracle 错误(我想是无效标识符)。

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接