5 つのアプリケーション サーバーで実行されている分散 Java アプリケーションがあります。サーバーはすべて、6 台目のマシンで実行されている同じ Oracle 9i データベースを使用しています。
アプリケーションは、シーケンスから 100 個の ID のバッチをプリフェッチする必要があります。シングルスレッドの非分散環境では、次のクエリを発行するだけで比較的簡単に実行できます。
SELECT seq.nextval FROM dual;
ALTER SEQUENCE seq INCREMENT BY 100;
SELECT seq.nextval FROM dual;
最初の select は、アプリケーションが使用できる最初のシーケンス ID をフェッチし、2 番目の select は、使用できる最後の ID を返します。
マルチスレッド環境では、物事がさらに面白くなります。2 番目の select の前に、別のスレッドがシーケンスを 100 ずつ増加させないことを確認することはできません。この問題は、Java 側でアクセスを同期することで解決できます。一度に 1 つのスレッドのみが ID のフェッチを開始できるようにします。
アプリケーションの一部が同じ JVM 上で実行されず、同じ物理マシン上でさえ実行されないために同期できない場合、状況は非常に困難になります。フォーラムで、他の人もこの問題を解決するのに問題があるといういくつかの参照を見つけましたが、合理的であることは言うまでもなく、実際に機能する答えはありません。
コミュニティはこの問題の解決策を提供できますか?
いくつかの詳細情報:
- トランザクションの分離レベルを実際に操作することはできません。私は JPA を使用していますが、変更はプリフェッチ クエリだけでなく、アプリケーション全体に影響を与えるため、私には受け入れられません。
PostgreSQL では、次のことができます。
SELECT setval('seq', NEXTVAL('seq') + n - 1)
マシューによる解決策は、固定の増分値を使用できる場合に機能します (私の場合は完全に受け入れられます)。ただし、インクリメントのサイズを固定したくないが、動的に調整したい場合の解決策はありますか?