GOOGLE ADS

среда, 13 апреля 2022 г.

Как предварительно получить идентификаторы последовательности Oracle в распределенной среде

У меня есть распределенное приложение 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 я мог бы сделать следующее:
    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>

Комментариев нет:

Отправить комментарий

Laravel Datatable addColumn returns ID of one record only

Я пытаюсь использовать Yajra Datatable для интеграции DataTable на свой веб-сайт. Я смог отобразить таблицу, но столкнулся с проблемой. В по...