♣ 题目 部分
在Oracle中,分布式事务ORA-01591错误如何解决?
♣ 答案部分
1、故障环境介绍
项目 |
数据库 |
DB类型 |
RAC |
DB版本 |
11.2.0.3 |
DB存储 |
ASM |
OS版本及kernel版本 |
AIX 64位 6.1.0.0 |
2、故障发生现象及报错信息
有同事发来错误,截图如下:
执行一个UPDATE语句的时候报ORA-01591的错误。
3、故障分析及解决过程
这个错误是由于分布式事务引起,而不是普通的锁引起的。若检查一般对象数据表锁定,则只需要检查V$LOCKED_OBJECT和V$TRANSACTION视图,就可以定位到具体的SQL语句和操作人等信息,但是检查之后的结果如下:
1SYS@oraLHR12> SELECT * FROM GV$LOCKED_OBJECT;
2no rows selected
3SYS@oraLHR12> SELECT * FROM GV$TRANSACTION;
4no rows selected
两个关键视图中,没有锁定的对象,也没有正在进行未提交的事务。那是不是没有锁定呢?或者锁已经释放了,重新尝试对数据表加锁,如下所示:
1SYS@oraLHR12> SELECT * FROM LHR.LHRBOKBAL FOR UPDATE;
2select * from LHR.LHRBOKBAL for update
3 *
4ERROR at line 1:
5ORA-01591: lock held by in-doubt distributed transaction 20.13.14721
6SYS@oraLHR12> SELECT COUNT(1) FROM LHR.LHRBOKBAL;
7 COUNT(1)
8----------
9 30998411
系统没有像一般阻塞那样等待,而是报错ORA-01591的错误,并且提示锁被一个分布式事务持有,不能实现加锁操作。那么ORA-01591错误究竟是什么错误呢?可以使用Oracle提供的oerr工具查看该错误编号,如下所示:
1root@ZFLHRRSP:/# oerr ora 1591
201591, 00000, "lock held by in-doubt distributed transaction %s"
3// *Cause: Trying to access resource that is locked by a dead two-phase commit
4// transaction that is in prepared state.
5// *Action: DBA should query the pending_trans$ and related tables, and attempt
6// to repair network connection(s) to coordinator and commit point.
7// If timely repair is not possible, DBA should contact DBA at commit
8// point if known or end user for correct outcome, or use heuristic
9// default if given to issue a heuristic commit or abort command to
10// finalize the local portion of the distributed transaction.
11
简单的说,01591错误的原因是该对象被一个处在“IN-DOUBT”状态的分布式事务锁定。分布式事务使用的是“two-phase commit”二阶段提交技术。解决该问题的方法就是查看内部表PENDING_TRANS$,确定分布式事务信息。这种状态的事务主要是由于在进行分布式事务时候,发生网络突发中断的情况,引起分布式事务无法正常结束,等待中断节点的事务响应。于是,各节点的事务所锁定的表就不会被释放掉。
此时,检查视图DBA_2PC_PENDING(或者基表PENDING_TRANS$),查看是否存在这种情况。
果然,当前存在一个阻塞分布式事务,处在prepared状态。当前问题,主要是源于在进入prepared阶段之后,发生了网络中断的现象,引起COMMIT的阶段不能等待到事务信息。所以,才会一直处在Prepared状态,数据表也就不会进行释放。
对于这个事务,只能通过连接网络或者强制提交回退事务来结束。可以使用COMMIT FORCE或者ROLLBACK FORCE来进行处理,在这里,进行回滚操作,如下所示:
1SYS@oraLHR12> ROLLBACK FORCE '20.13.14721';
2Rollback complete.
ROLLBACK FORCE的参数是DBA_2PC_PENDING中记录本地事务信息的编号即LOCAL_TRAN_ID。
此时,再次查看数据。
此时,该事务状态已经变化为forced rollback表示已经强制回退,此时再次尝试锁定表操作:
116:25:31 SQL> SELECT * FROM LHR.LHRBOKBAL FOR UPDATE;
2CURRENCY
3--------
4001
可以看出已经不报错了,可以正常执行。
& 说明:
有关该案例的更多内容可以参考我的BLOG:http://blog.itpub.net/26736162/viewspace-2122999/
本文选自《Oracle程序员面试笔试宝典》,作者:小麦苗
---------------优质麦课------------
详细内容可以添加麦老师微信或QQ私聊。
About Me:小麦苗
● 本文作者:小麦苗,只专注于数据库的技术,更注重技术的运用
● 作者博客地址:http://blog.itpub.net/26736162/abstract/1/
● 本系列题目来源于作者的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解
● 版权所有,欢迎分享本文,转载请保留出处
● QQ:646634621 QQ群:618766405
● 提供OCP、OCM和高可用部分最实用的技能培训
● 题目解答若有不当之处,还望各位朋友批评指正,共同进步
DBA宝典
长按下图识别二维码或微信扫描下图二维码来关注小麦苗的微信公众号:xiaomaimiaolhr,学习最实用的数据库技术。