前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在Oracle中,分布式事务ORA-01591错误如何解决?

在Oracle中,分布式事务ORA-01591错误如何解决?

作者头像
小麦苗DBA宝典
发布2019-11-23 16:19:48
2K0
发布2019-11-23 16:19:48
举报

题目部分

在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语句和操作人等信息,但是检查之后的结果如下:

代码语言:javascript
复制
1SYS@oraLHR12> SELECT * FROM GV$LOCKED_OBJECT;
2no rows selected
3SYS@oraLHR12> SELECT * FROM GV$TRANSACTION;
4no rows selected

两个关键视图中,没有锁定的对象,也没有正在进行未提交的事务。那是不是没有锁定呢?或者锁已经释放了,重新尝试对数据表加锁,如下所示:

代码语言:javascript
复制
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工具查看该错误编号,如下所示:

代码语言:javascript
复制
 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来进行处理,在这里,进行回滚操作,如下所示:

代码语言:javascript
复制
1SYS@oraLHR12> ROLLBACK FORCE '20.13.14721';
2Rollback complete.

ROLLBACK FORCE的参数是DBA_2PC_PENDING中记录本地事务信息的编号即LOCAL_TRAN_ID。

此时,再次查看数据。

此时,该事务状态已经变化为forced rollback表示已经强制回退,此时再次尝试锁定表操作:

代码语言:javascript
复制
116:25:31 SQL> SELECT * FROM LHR.LHRBOKBAL FOR UPDATE;
2CURRENCY
3--------
4001

可以看出已经不报错了,可以正常执行。

& 说明:

有关该案例的更多内容可以参考我的BLOG:http://blog.itpub.net/26736162/viewspace-2122999/

本文选自《Oracle程序员面试笔试宝典》,作者:小麦苗

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DB宝 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档