SQL> select * from dba_2pc_pending;
LOCAL_TRAN_ID GLOBAL_TRAN_ID STATE MIX A TRAN_COMMENTFAIL_TIME FORCE_TIME RETRY_TIME OS_USER
OS_TERMINAL HOST DB_USER
COMMIT#
----------------
72.0.1608712 XXXXXXX.12345.1.2.3 prepared no12-11月-08 12-11月-08
此时我们结束这个事务
SQL> COMMIT FORCE '72.0.1608712';
提交完成。
再次查询dba_2pc_pending,发现事务是forced commit状态,该事务已经结束。
SQL> select * from dba_2pc_pending;
LOCAL_TRAN_ID GLOBAL_TRAN_ID STATE MIX A TRAN_COMMENTFAIL_TIME FORCE_TIME RETRY_TIME OS_USER
OS_TERMINAL HOST DB_USER COMMIT#
----------------
72.0.1608712 XXXXXXX.12345.1.2.3 forced commit no12-11月-08 12-11月-08 12-11月-08
通过x$kutxe 查询事务信息,发现事务释放了回滚段,事务已经结束。
SQL> SELECT KTUXEUSN, KTUXESLT, KTUXESQN, /* Transaction ID */
2 KTUXESTA Status,
3 KTUXECFL Flags
4 FROM x$ktuxe
5 WHERE ktuxesta!='INACTIVE'
6 AND 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:
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12137615/viewspace-607703/ ,如需转载,请注明出处,否则将追究法律责任。