16hextoraw( '00000001' ),
17hextoraw( '00000000' ),
180, sysdate, sysdate );
已创建 1 行。
SQL> insert into pending_sessions$
2values( '72.0.1608712',
31, hextoraw('05004F003A1500000104'),
4'C', 0, 30258592, '',
5146
6);
已创建 1 行。
SQL> commit;
提交完成。
SQL> alter system enable distributed recovery;
系统已更改。
此时,查询dba_2pc_pending发现已有该事务,并且状态是我们模拟出的prepared状态
SQL> select * from dba_2pc_pending;
LOCAL_TRAN_IDGLOBAL_TRAN_ID STATEMIX A TRAN_COMMENTFAIL_TIMEFORCE_TIME RETRY_TIME OS_USER
OS_TERMINAL HOSTDB_USER
COMMIT#
----------------
72.0.1608712XXXXXXX.12345.1.2.3 prepared no12-11月-0812-11月-08
此时我们结束这个事务
SQL> COMMIT FORCE '72.0.1608712';
提交完成。
再次查询dba_2pc_pending,发现事务是forced commit状态,该事务已经结束。
SQL> select * from dba_2pc_pending;
LOCAL_TRAN_IDGLOBAL_TRAN_ID STATEMIX A TRAN_COMMENTFAIL_TIMEFORCE_TIME RETRY_TIME OS_USER
OS_TERMINALHOSTDB_USER COMMIT#
----------------
72.0.1608712XXXXXXX.12345.1.2.3 forced commitno12-11月-08 12-11月-08 12-11月-08
通过x$kutxe 查询事务信息,发现事务释放了回滚段,事务已经结束。
SQL> SELECT KTUXEUSN, KTUXESLT, KTUXESQN, /* Transaction ID */
2KTUXESTA Status,
3KTUXECFL Flags
4FROM x$ktuxe
5WHERE ktuxesta!='INACTIVE'
6AND ktuxeusn= 72;
未选定行
此时,我们需要清除dba_2pc_pending中分布式事务的残余信息
SQL> alter session set "_smu_debug_mode"=4;―― 在session级别设置回滚段处于手工管理模式,如果不设置这个参数,在回滚段自动管理模式下,清除事务信息会报错
会话已更改。
SQL> execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('72.0.1608712');――用dbms包清除事务信息
PL/SQL 过程已成功完成。
SQL> select * from dba_2pc_pending;
未选定行
测试访问业务表
SQL> select count(*) from UNITELE.BI_MQSYNC_SOURCE_CONTROL_T1;
COUNT(*)
----------
367
问题解决。
其实,我在另外一个客户处也碰到过类似问题,当时也是报ORA-01591,但是在dba_2pc_pending中可以查到prepared状态的事务,此时只需要commit force结束这个事务,并清除事务信息就可以了。对于上面的案例,我怀疑开发商直接清除了分布式事务信息,但是事务并没有结束,导致锁资源得不到释放报ORA-01591。
总结:ORA-01591错误一般是由于分布式事务造成的,造成分布式事务失败的原因主要是库之间的网络突然中断,造成两个库中的事务信息不一致,所以会有残余的分布式事务信息。此时,要针对不同的事务状态做不同的 理。同时在遇到棘手的问题时,可以查询metalink,该案例参考metalink文档:NOTE:401302.1
[@more@]