Возобновление транзакций базы данных Oracle после повторного подключения

#oracle #transactions #oracle-call-interface #occi

#Oracle #транзакции #oracle-call-интерфейс #occi

Вопрос:

Мне поручили стабилизировать часть устаревшего приложения. Это ~ 20-летнее приложение на C , которое теперь использует базу данных Oracle 12.2 для сохранения (даже для кода пользовательского интерфейса). Взаимодействие между ними осуществляется с помощью интерфейса вызовов Oracle (OCI).
В настоящее время я пытаюсь «исправить» транзакции базы данных после неблагодарного отключения (например, переход с одной точки доступа на другую внутри той же сети). После повторного подключения к базе данных я хочу, чтобы клиент возобновил транзакцию с последнего сеанса. Таким образом, изменения в этой транзакции не будут отменены.

Я считаю, что это было бы полезно, поскольку я не могу быть уверен, какой DML был выполнен, а какой нет при запуске новой транзакции. Таким образом, возобновление старого позволило бы увидеть, что уже было выполнено.

Может быть, я совсем не в себе, но я, очевидно, открыт для лучших предложений. Конечно, есть какая-то структура или шаблон, которые я, кажется, не могу найти, потому что я ищу неправильные ключевые слова.

С наилучшими пожеланиями
, Ян

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

1. как получается, что транзакция / сеанс отключается, а затем снова подключается? Что это за приложение?

2. Если вы завершаете сеанс, oracle выполняет откат текущей незафиксированной транзакции. Он исчез.

3. Да, что сказал @OldProgrammer: нет способа соединить незафиксированные транзакции между сеансами. Приложение должно было бы отслеживать свое собственное состояние транзакции независимо от базы данных.

4. Посмотрите на DBMS_XA, который позволяет приостанавливать и возобновлять транзакции между сеансами. Если у меня будет время, я опубликую свой хакерский код из PHP-теста, который я когда-то делал. Я не говорю, что это лучший способ; возможно, было бы лучше подумать о решении среднего уровня.

Ответ №1:

Как я упоминал в своем комментарии, DBMS_XA может быть одним из способов, но, возможно, лучше подумать об альтернативных архитектурах (или исправлении сети ?!) При условии, что вы знаете, когда соединение будет отключено.

Смотрите Мои старые заметки на слайде 79 из https://www.oracle.com/technetwork/topics/php/highperf-php-preso-405765.pdf

Начните со схемы:

 drop table mytable;
create table mytable (id number, salary number);
insert into mytable values (1, 100);
insert into mytable values (2, 300);
commit;
 

Затем попробуйте использовать эти три фрагмента в трех разных сеансах SQL * Plus:

Сессия №1

Обновите первую зарплату:

 var rc number
exec :rc := DBMS_XA.XA_START(DBMS_XA_XID(123), DBMS_XA.TMNOFLAGS);
update mytable set salary = salary * 1.1 where id = 1;
select * from mytable;
exec :rc := DBMS_XA.XA_END(DBMS_XA_XID(123), DBMS_XA.TMSUSPEND);

select * from mytable;
 

Запросы показывают, что никаких изменений не видно после приостановки транзакции:

         ID     SALARY
---------- ----------
         1        110
         2        300

        ID     SALARY
---------- ----------
         1        100
         2        300
 

Сессия # 2

Обновите вторую зарплату:

 var rc number
exec :rc := DBMS_XA.XA_START(DBMS_XA_XID(123), DBMS_XA.TMRESUME);
update mytable set salary = salary * 3 where id = 2;
select * from mytable;
exec :rc := DBMS_XA.XA_END(DBMS_XA_XID(123), DBMS_XA.TMSUSPEND);

select * from mytable;
 

Вывод показывает, что транзакцию можно возобновить, и теперь в ней обновлены обе зарплаты. После повторного приостановления транзакции никаких изменений не отображается:

         ID     SALARY
---------- ----------
         1        110
         2        900

        ID     SALARY
---------- ----------
         1        100
         2        300
 

Сессия #3

 var rc number
exec :rc := DBMS_XA.XA_COMMIT(DBMS_XA_XID(123), TRUE);

select * from mytable;
 

Транзакция зафиксирована. Вывод:

         ID     SALARY
---------- ----------
         1        110
         2        900