1. Identify the id OF the TRANSACTION:
COLUMN global_tran_id format a25
COLUMN DATABASE format a22
COLUMN global_name format a22
SELECT * FROM global_name;
SELECT LOCAL_TRAN_ID, GLOBAL_TRAN_ID,to_char(FAIL_TIME,'dd-mon-yyyy HH24:MI:SS'),STATE, MIXED FROM DBA_2PC_PENDING;
SELECT LOCAL_TRAN_ID, IN_OUT,INTERFACE, DATABASE FROM DBA_2PC_NEIGHBORS;
2. Purge the TRANSACTION:
EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('');
COMMIT;
3. Confirm that the TRANSACTION has been purged:
SELECT LOCAL_TRAN_ID, GLOBAL_TRAN_ID,to_char(FAIL_TIME,'dd-mon-yyyy HH24:MI:SS'),STATE, MIXED FROM DBA_2PC_PENDING;
SELECT LOCAL_TRAN_ID, IN_OUT,INTERFACE, DATABASE FROM DBA_2PC_NEIGHBORS;
其中有如下五种state:
collecting
-- execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');
prepared
-- rollback force tran_id/commit force tran_id;
EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');
committed
-- execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');
forced commit
-- execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');
forced ROLLBACK
-- execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');
++++++ 如果遇到ORA-30019错误,可以采取如下方式:++++++
ALTER SESSION SET "_smu_debug_mode" = 4;
EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');
====== 情况1 在dba_2pc_pending表中还有事务记录,但是实际已经不存在该事务了
SELECT LOCAL_TRAN_ID,
GLOBAL_TRAN_ID,
to_char(FAIL_TIME, 'dd-mon-yyyy HH24:MI:SS'),
STATE,
MIXED
FROM DBA_2PC_PENDING;
LOCAL_TRAN_ID 1.92.66874 prepared
1 为回滚段号
SELECT KTUXEUSN,
KTUXESLT,
KTUXESQN, /* Transaction ID */
KTUXESTA STATUS,
KTUXECFL Flags
FROM x$ktuxe
WHERE ktuxesta != 'INACTIVE'
AND ktuxeusn = 1
返回为0
如果当状态为prepared,且事务表中也不存在相关信息,那么我们只能手工进行清理:
++++++ 使用如下方式进行手工处理:++++++
SET TRANSACTION USE ROLLBACK segment SYSTEM;
DELETE FROM sys.pending_trans$ WHERE local_tran_id = '1.92.66874';
DELETE FROM sys.pending_sessions$ WHERE local_tran_id = '1.92.66874';
DELETE FROM sys.pending_sub_sessions$ WHERE local_tran_id = '1.92.66874';
commit;
====== 情况2 在dba_2pc_pending表中无法查到分布式事务信息,但是实际上却是存在该分布式事务的
SELECT LOCAL_TRAN_ID,
GLOBAL_TRAN_ID,
to_char(FAIL_TIME, 'dd-mon-yyyy HH24:MI:SS'),
STATE,
MIXED
FROM DBA_2PC_PENDING;
查询无记录
SELECT local_tran_id, state
FROM dba_2pc_pending
WHERE local_tran_id = ' 1.92.66874 '; -- 为空
SELECT KTUXEUSN,
KTUXESLT,
KTUXESQN, /* Transaction ID */
KTUXESTA STATUS,
KTUXECFL Flags
FROM x$ktuxe
WHERE ktuxesta != 'INACTIVE'
AND ktuxeusn = 1;
查询有记录
====== 此种情况下,我们无法手工进行ROLLBACK或commit ======
++++++ 我们用如下的方式手工清理:++++++
ALTER system disable distributed recovery ;
INSERT INTO pending_trans $
(LOCAL_TRAN_ID,
GLOBAL_TRAN_FMT,
GLOBAL_ORACLE_ID,
STATE,
STATUS,
SESSION_VECTOR,
RECO_VECTOR,
TYPE #,
FAIL_TIME,
RECO_TIME)
VALUES
(' 1.92.66874 ',
306206,
' XXXXXXX.12345.1.2.3 ',
' prepared ',
' P ',
hextoraw(' 00000001 '),
hextoraw(' 00000000 '),
0,
sysdate,
sysdate);
INSERT INTO pending_sessions $
VALUES
(' 1.92.66874 ',
1,
hextoraw(' 05004F003A1500000104 '),
' C ',
0,
30258592,
'',
146);
commit ;
commit force ' 1.92.66874 ' ;
++++++ 此时如果commit force还是出现报错,需要继续执行:++++++
1. DELETE FROM pending_trans $ WHERE local_tran_id = '1.92.66874' ;
2. DELETE FROM pending_sessions $ WHERE local_tran_id = '1.92.66874' ;
3. commit ;
4. ALTER system enable distributed recovery ;
5. ALTER SESSION SET " _smu_debug_mode " = 4 ;
6. EXEC dbms_transaction.purge_lost_db_entry ( '1.92.66874' )
====== 另外我们还可以通过如下SQL来捕获到导致分布式事务失败的SQL:======
++++++ 获取local_tran_id ++++++
SELECT a.sql_text, s.osuser, s.username
FROM v$transaction t, v$session s, v$sqlarea a
WHERE s.taddr = t.addr
AND a.address = s.prev_sql_addr
AND t.xidusn = 1
AND t.xidslot = 25
AND t.xidsqn = 589367;
如果 v$session 和 v$sqlarea 已经无法查到,那么我们还可以关联一些 dba_hist_* 试图进行查询。