Welcome 微信登录

首页 / 数据库 / MySQL / ORA-01591错误解决方法

摘要:
 
在访问某些表的特定行时报ORA-01591错误
 
select * from BF_INCOME_EXPENSES_T
 
where account_id = 36816153
 
and user_id = 39964213
 
and city_code = "185"
 ORA-01591: 锁定已被有问题的分配事务处理72.0.1608712挂起SQL> select count(*) from UNITELE.BI_MQSYNC_SOURCE_CONTROL_T1;ORA-01591: 锁定已被有问题的分配事务处理72.0.1608712挂起
 
由于该表是业务关键表,部分前台业务受到影响。
 
关键词:ORA-01591 DBA_2PC_PENDING 分布式事务1.故障分析
 
首先,在遇到ORA错误时,我们不可能知道每个ORA错误都是什么意思,所以通过Oracle的联机文档查错误的cause和action可以让我们初步了解该错误。
 
01591, 00000, "lock held by in-doubt distributed transaction %s"
 
// *Cause:Trying to access resource that is locked by a dead two-phase commit
 
//transaction that is in prepared state.
 
// *Action: DBA should query the pending_trans$ and related tables, and attempt
 
//to repair network connection(s) to coordinator and commit point.
 
//If timely repair is not possible, DBA should contact DBA at commit
 
//point if known or end user for correct outcome, or use heuristic
 
//default if given to issue a heuristic commit or abort command to
 
//finalize the local portion of the distributed transaction.
 
Oracle对ORA-01591错误的描述是"lock held by in-doubt distributed transaction %s,由分布式事务持有锁造成的。通过错误的cause可以看到’Trying to access resource that is locked by a dead two-phase commit transaction that is in prepared state’该错误是由访问一个处于prepared状态的二阶段事务所持有锁的资源造成的。
 
下面简单介绍一下分布式事务。
 
分布式事务,简单来说,是指一个事务在本地和远程执行,本地需要等待确认远程的事务结束后,进行下一步本地的操作。如通过dblink update远程数据库的一行记录,如果在执行过程中网络异常,或者其他事件导致本地数据库无法得知远程数据库的执行情况,此时就会发生in doublt的报错。此时需要dba介入,且需要分多种情况进行处理。
 
分布式事务的Two-Phase Commit机制,会经历3个阶段:
 
1.PREPARE PHASE:
 
1.1 决定哪个数据库为commit point site。(注,参数文件中commit_point_strength值高的那个数据库为commit point site)
 
1.2 全局协调者(Global Coordinator)要求所有的点(除commit point site外)做好commit或者rollback的准备。此时,对分布式事务的表加锁。
 
1.3 所有分布式事务的节点将它的scn告知全局协调者。
 
1.4 全局协调者取各个点的最大的scn作为分布式事务的scn。
 
至此,所有的点都完成了准备工作,我们开始进入COMMIT PHASE阶段,此时除commit point site点外所有点的事务均为in doubt状态,直到COMMIT PHASE阶段结束。
 
2.COMMIT PHASE:
2.1 Global Coordinator将最大scn传到commit point site,要求其commit。
2.2 commit point尝试commit或者rollback。分布式事务锁释放。
2.3 commit point通知Global Coordinator已经commit。
2.4 Global Coordinator通知分布式事务的所有点进行commit。
 
3.FORGET PHASE:
3.1 参与的点通知commit point site他们已经完成commit,commit point site就能忘记(forget)这个事务。
3.2 commit point site在远程数据库上清除分布式事务信息。
3.3 commit point site通知Global Coordinator可以清除本地的分布式事务信息。
3.4 Global Coordinator清除分布式事务信息。
 
有关分布式事务的详细信息请参阅oracle联机文档.
 
当前的分布式事务处于Two-Phase Commit机制中的prepared阶段,这个阶段事务已经在表上加锁了,现在我们要访问这些表,但事务没有结束,一直持有锁,导致访问资源失败报ORA-01591。(在这里需要指出:分布式事务所持有的锁之所以堵塞读操作,是因为oralce不知道该显示哪个版本的数据) 如果结束这个事务,那相应的锁也会释放,这样就能解决这个问题。我们知道要结束一个事务有两种办法:commit和rollback。现在我们尝试结束这个事务:
 
commit force "72.0.1608712";
 
ORA-02058: no prepared transaction found with ID 72.0.1608712
 
报错并没有发现prepared状态的事务,由于该事务是分布式事务,我们首先想到的是dba_2pc_pending这个试图
 
SQL> select * from dba_2pc_pending;
 
no rows selected
 
该试图并没有查到信息,所以我们无法用commit force结束这个分布式事务,那么现在我们查看是否存在该事务,通过实际报错,我们可以清晰的看到事务号为72.0.1608712,该事务在72号回滚段的0号事务槽上并且序列号是1608712,这时查询一个基表x$ktuxe,看看72号回滚段上是否有该事务。
 
SQL> SELECT KTUXEUSN, KTUXESLT, KTUXESQN, /* Transaction ID */
 
2 KTUXESTA Status,
 
3KTUXECFL Flags
 
4FROM x$ktuxe
 
5WHERE ktuxesta!="INACTIVE"
 
6 AND ktuxeusn= 72;
 
KTUXEUSNKTUXESLTKTUXESQN STATUSFLAGS
 
---------- ---------- ---------- ---------------- ------------------------
 
7201608712 PREPAREDSCO|COL|REV|DEAD
 
通过x$ktuxe这个基表,我们看到确实存在这个事务,而且是prepared状态。
 
此时,我们基本清楚了这个问题的原因:当一个分布式事务死掉时,由于该事务没有正常结束,导致事务持有的锁一直没有释放,所以在访问这个事务涉及的资源时,申请不到锁资源,所以报ORA-01591。由于是分布式事务,当在dba_2pc_pending中查询不到事务信息时,我们是无法通过commit或者rollback结束该事务。
 
所以,我们目前的任务是模拟出这个分布式事务。由于dba_2pc_pending试图是依赖于pending_trans$这个表,同时事务是与session关联在一起的,所以我们需要手工往pending_trans$和pending_sessions$两个表中插入数据。
 
2.故障处理
 
SQL> alter system disable distributed recovery;
 
系统已更改。
 
SQL> insert into pending_trans$ (
 
2LOCAL_TRAN_ID,
 
3GLOBAL_TRAN_FMT,
 
4GLOBAL_ORACLE_ID,
 
5STATE,
 
6 STATUS,
 
7SESSION_VECTOR,
 
8RECO_VECTOR,
 
9TYPE#,
 
10FAIL_TIME,
 
11RECO_TIME)
 
12values( "72.0.1608712",13306206,
 
14"XXXXXXX.12345.1.2.3",
 
15"prepared","P",
 
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@]更多Oracle相关信息见Oracle 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=12Oracle 10G控制文件损坏恢复删除undo表空间遭遇ORA-30013及ORA-01548错误解决方法相关资讯      ORA-01591  本文评论 查看全部评论 (0)
表情: 姓名: 字数

版权所有©石家庄振强科技有限公司2024 冀ICP备08103738号-5 网站地图