我有一个在 5 个应用程序服务器上运行的分布式 Java 应用程序。这些服务器都使用在第 6 台机器上运行的相同 Oracle 9i 数据库。
应用程序需要从序列中预取一批 100 个 ID。在单线程、非分布式环境中做起来相对容易,您只需发出以下查询即可:
SELECT seq.nextval FROM dual;
ALTER SEQUENCE seq INCREMENT BY 100;
SELECT seq.nextval FROM dual;
第一个选择获取应用程序可以使用的第一个序列 ID,第二个选择返回最后一个可以使用的序列 ID。
在多线程环境中,事情变得更加有趣。您不能确定在第二次选择之前另一个线程不会再次将序列增加 100。这个问题可以通过在 Java 端同步访问来解决 - 您一次只让一个线程开始获取 ID。
当您无法同步时,情况会变得非常困难,因为应用程序的某些部分不在同一个 JVM 上运行,甚至不在同一台物理机器上运行。我在论坛上发现了一些引用,其他人也无法解决这个问题,但没有一个答案真正有效,更不用说合理了。
社区能否针对这个问题提供解决方案?
更多信息:
- 我真的不会玩事务隔离级别。我使用 JPA,更改会影响整个应用程序,而不仅仅是预取查询,这对我来说是 Not Acceptable 。
在 PostgreSQL 上,我可以执行以下操作:
SELECT setval('seq', NEXTVAL('seq') + n - 1)
Matthew 的解决方案在您可以使用固定增量值时有效(在我的情况下完全可以接受)。但是,当你不想固定增量的大小,而是想动态调整它时,有什么解决方案吗?
最佳答案
为什么不让序列一直递增 100?每个“nextval”给你 100 个序列号来处理
SQL> create sequence so_test start with 100 increment by 100 nocache;
Sequence created.
SQL> select so_test.nextval - 99 as first_seq, so_test.currval as last_seq from dual;
FIRST_SEQ LAST_SEQ
---------- ----------
1 100
SQL> /
FIRST_SEQ LAST_SEQ
---------- ----------
101 200
SQL> /
FIRST_SEQ LAST_SEQ
---------- ----------
201 300
SQL>
关于你的例子的注释..注意 DDL..它会产生隐式提交
DDL 生成的提交示例
SQL> select * from xx;
no rows selected
SQL> insert into xx values ('x');
1 row created.
SQL> alter sequence so_test increment by 100;
Sequence altered.
SQL> rollback;
Rollback complete.
SQL> select * from xx;
Y
-----
x
SQL>
关于java - 如何在分布式环境中预取 Oracle 序列 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43808/