是否可以锁定Oracle序列,以便尝试在其上使用nextval的任何会话都会阻塞,直到我完成脚本为止?
如果有不同的方式,我会解释我在做什么。我正在准备一个模式来使用流进行双向复制。我想确保所有主键序列产生唯一值。我通过将序列递增1直到最后一位数为1然后将增量更改为100来执行此操作。在另一台服务器上,我执行相同操作直到最后一位数为2.这样,服务器1始终生成主键XXXXX01和服务器2 XXXXX02。
问题是这是一个24x7数据库,我在调整序列时无法阻止所有活动。如果我能在短时间内获得专属锁,我可以可靠地完成。
答案 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建议使用单独的非重叠序列的想法。
要考虑的另一个选择是复合主键。
如果您能够向数据模型添加列,则添加一个不同的标识符,具体取决于运行该进程的服务器。
如果无法添加列,则可以将列数据类型更改为VARCHAR2,并将其设置为复合;例如在服务器1上,您可以将“1-”连接到序列值,例如因此,“1-103450”不会与服务器2上生成的“2-103450”冲突。
无论哪种方式,这都不会在将来添加更多服务器时遇到任何问题。
答案 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.html和https://geraldonit.com/oracle/database/oracle-database-locktypes/。