The package DBMS_XA can transfer an uncommitted transaction from one session to another. The second session can view the uncommitted data and can commit, rollback, or pass the transaction on again. The below example is based on this oracle-base article, and while it works for me, I have never used this feature in production before and there may be complications I'm not aware of.
First, create a table used by the example:
--DROP TABLE tab1;
CREATE TABLE tab1 (
id NUMBER
);
Session 1
Change the transaction timeout from 60 seconds to a larger value:
DECLARE
l_return PLS_INTEGER;
BEGIN
l_return := SYS.DBMS_XA.xa_settimeout(500);
END;
/
Start a transaction, passing in a magic number to name the transaction (999):
DECLARE
l_xid DBMS_XA_XID := DBMS_XA_XID(999);
l_return PLS_INTEGER;
BEGIN
l_return := SYS.DBMS_XA.xa_start(xid => l_xid,
flag => DBMS_XA.TMNOFLAGS);
END;
/
Do the real work here, without committing:
INSERT INTO tab1 (id) VALUES (1);
End the transaction so another session can attach to it later:
DECLARE
l_xid DBMS_XA_XID := DBMS_XA_XID(999);
l_return PLS_INTEGER;
BEGIN
l_return := SYS.DBMS_XA.xa_end(xid => l_xid,
flag => DBMS_XA.TMSUSPEND);
END;
/
The data has disappeared from our session - this table does not include the row we just inserted. Another session will need to attach to the global transaction and either commit it or roll it back.
select * from tab1;
Session 2
Initially, this session cannot see the data:
select * from tab1;
Attach to the global transaction, using the same magic number (999):
DECLARE
l_xid DBMS_XA_XID := DBMS_XA_XID(999);
l_return PLS_INTEGER;
BEGIN
l_return := SYS.DBMS_XA.xa_start(xid => l_xid,
flag => DBMS_XA.TMRESUME);
END;
/
Now only this session can see the new row:
select * from tab1;
The second session can commit, rollback, or pass the transaction to yet another session. To pass the transaction, call DBMS_XA.XA_END again and have another session then call DBMS_XA.XA_START.