Можно ли увидеть изменения в другой сессии до COMMIT в ней?
Я реализовал PL/SQL скрипт. В продуктивной среде скрипт запустит DBA.
Есть ли способ, увидеть изменения, которые произвёл скрипт, до того, как будет выполнен COMMIT?
Знаю, что изменения будут активны в той сессии, в которой выполнялся скрипт. Но может есть способ в другой сессии, или более того, с другим пользователем, увидеть эти изменения?
Свободный перевод вопроса See changes of a different SQL Oracle session before COMMIT? от участника @Felipe Vidal Otero
Ответы (1 шт):
Пакет DBMS_XA может передавать незафиксированную транзакцию из одной сессии в другой. Другая сессия может просматривать незафиксированные данные, может фиксировать, откатывать или снова передать их в другую транзакцию. Приведенный ниже пример основан на этой статье ORACLE-BASE и выглядит, что работает, но никогда не проверял в продуктивной среде, поэтому - на свой страх и риск.
Сессия 1
Тестовая таблица и изменение тайм-аута на ветвление транзакций (по умочанию 60 сек.):
create table t1 (id number);
var ret number
exec :ret := dbms_xa.xa_settimeout(600);
Начните транзакцию с магическим числом транзакции (9999) и вставте первую запись:
exec :ret := sys.dbms_xa.xa_start (xid=>dbms_xa_xid (9999), flag=>dbms_xa.tmnoflags);
insert into t1 (id) values (1);
Завершим транзакцию, чтобы к ней можно было подключить другую сессию. Запись, которая была только что вставлена, будет больше не доступна в это сессии:
exec :ret := sys.dbms_xa.xa_end (xid=>dbms_xa_xid (9999), flag=>dbms_xa.tmsuspend);
select * from t1;
no rows selected
Сессия 2
Изначально, эта сессия не может видеть данные:
select * from t1;
no rows selected
Подключиться к глобальной транзакции, используя то же самое магическое число (9999). Затем, только эта сессия может видеть новую запись. В залючение, эта сессия должна зафиксировать, откатить, или опять - отсоединится от транзакции:
var ret number
exec :ret := dbms_xa.xa_start (xid=>dbms_xa_xid (9999), flag=>dbms_xa.tmresume);
select * from t1
/
ID
----------
1
begin
:ret := dbms_xa.xa_end (xid=>dbms_xa_xid (9999), flag=>dbms_xa.tmsuccess);
if :ret = dbms_xa.xa_ok then
:ret := dbms_xa.xa_commit (xid=>dbms_xa_xid (9999), onePhase=>true);
end if;
end;
/
Свободный перевод ответа от участника @Jon Heller