我有一个在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并且更改会影响整个应用程序,而不仅仅是预取查询,这对我来说是不可接受的.
>在Postgresql上我可以做到以下几点:
select setval(‘seq’,nextval(‘seq’)n – 1)
>当你可以使用固定的增量值(在我的情况下完全可以接受)时,马修的解决方案就可以了.但是,如果您不想修改增量的大小,但想要动态调整它,是否有解决方案?
解决方法
为什么不一直将序列增加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>