У меня есть распределенное приложение Java, работающее на 5 серверах приложений. Все серверы используют одну и ту же базу данных Oracle 9i, запущенную на 6-м компьютере.
Приложение должно предварительно выбрать пакет из 100 идентификаторов из последовательности. Это относительно легко сделать в однопоточной, нераспределенной среде, вы можете просто выполнить следующие запросы:
select seq.nextval from dual;
alter sequence seq increment by 100;
select seq.nextval from dual;
Первый выбор извлекает первый идентификатор последовательности, который может использовать приложение, второй выбор возвращает последний, который можно использовать.
В многопоточной среде все становится интереснее. Вы не можете быть уверены, что перед вторым выбором другой поток не увеличит последовательность снова на 100. Эта проблема может быть решена путем синхронизации доступа на стороне Java - вы позволяете только одному потоку начать получать идентификаторы за один раз.
Ситуация становится действительно сложной, когда вы не можете синхронизировать, потому что части приложения не работают на одной и той же JVM, даже на одной физической машине. Я нашел некоторые ссылки на форумах, что у других тоже есть проблемы с решением этой проблемы, но ни один из ответов на самом деле не работает, не говоря уже о том, чтобы быть разумным.
Может ли сообщество предоставить решение этой проблемы?
Дополнительная информация:
- Я не могу поиграть с уровнями изоляции транзакций. Я использую JPA, и это изменение повлияет на все приложение, а не только на запросы предварительной выборки, и это для меня неприемлемо.
На PostgreSQL я мог бы сделать следующее:
выберите setval ('seq', nextval ('seq') + n - 1)
Решение от Мэтью работает, когда вы можете использовать фиксированное значение приращения (что вполне приемлемо в моем случае). Однако есть ли решение, когда вы не хотите фиксировать размер приращения, но хотите настроить его динамически?