设为首页 收藏本站
查看: 570|回复: 0

[经验分享] ORA-01591:lock held by in-doubt distributed transacation 解析

[复制链接]

尚未签到

发表于 2015-11-8 08:22:37 | 显示全部楼层 |阅读模式
http://blog.iyunv.com/langcai1981/article/details/
  今天在查找一个普通表时,出现了上图所示ORA-01591的错误提示,在网上找了下问题点,
  ORA-01591 错误问题说明如下:
  

Error:  ORA 1591                                                              
Text:   lock held by in-doubt distributed transaction <num >                  
-------------------------------------------------------------------------------
Cause:  An attempt was made to access a resource locked by a dead two-phase   
commit transaction that is in prepared state.                        
Action: Match the transaction number in the message with the GLOBAL_TRAN_ID   
column of the DBA_2PC_PENDING table to determine the database link and
the state of the transaction.                                         
Attempt to repair network connections to the coordinator and commit   
point, if necessary.                                                  
If timely repair is not possible, contact the database administrator  
at the commit point, if known, to resolve the pending transaction.

以上说明是mos关于该错误的一个描述,当然,引起该错误的原因可能有很多很多,很多时候是由于网络原因造成的,但是单表查询所报的错误提示是由于分布式事务查询时引起,是由于程序员在将操作分布到两个数据库时,突然发生的异常信息。
如此分布式事务,其实可以这样理解,就是一个完整的事务,其中包含的多个操作分布在两个以上的数据库中,只有这些操作都全部完成了,该事务才算完成,不然该事务都将失败。
换句话说,如果该事务失败了,其中涉及到操作表A,那么当其他session访问到表A时将出现ORA-01591错误。
至于具体说为什么分布式事务会失败,那么就要具体分析了,可能是程序本身的问题或者网络问题等等,正如上面所说的很多时候是由于网络异常中断导致的,公司网络不稳定,在操作过程中丢包就有可能发生此错误。
ORA-01591:lock held by in-doubt distributed transacation 9.8.1.003433,此错误的local_tran_id=9.8.1.003433,系统判断是分布事务,那么我们就查询dba_2pc_pending视图来找查相关原因了
查询结果如下;


LOCAL_TRAN_ID          STATE            FAIL_TIME    OS_USER    DB_USER
---------------------- ---------------- ------------ ---------- ----------
9.8.1.003433           prepared         2012-06-06              MIS

根据分布事务的状态(state)不同,我们需要采取不同的方法进行处理,稍后进行一个简单的总结,这里我继续描述如何处理该问题。
总结网址为: http://www.killdb.com/2011/10/11/ora-01591-lock-held-by-in-doubt-distributed-transaction.html
通过如下两个小步骤进行处理:

rollback force '19.3.5343485';
execute dbms_transaction.purge_lost_db_entry('19.3.5343485');



关于分布式事务处理的简单总结&#43;&#43;&#43;&#43;&#43;&#43; 常规处理步骤 &#43;&#43;&#43;&#43;&#43;&#43;
1. Identify the id OF the TRANSACTION:
COLUMN global_tran_id format a25
COLUMN DATABASE format a22
COLUMN global_name format a22
SELECT * FROM global_name;
SELECT LOCAL_TRAN_ID, GLOBAL_TRAN_ID,to_char(FAIL_TIME,'dd-mon-yyyy HH24:MI:SS'),STATE, MIXED FROM DBA_2PC_PENDING;           
SELECT LOCAL_TRAN_ID, IN_OUT,INTERFACE, DATABASE FROM DBA_2PC_NEIGHBORS;
2. Purge the TRANSACTION:
EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('<transaction_id>');
COMMIT;
3. Confirm that the TRANSACTION has been purged:
SELECT LOCAL_TRAN_ID, GLOBAL_TRAN_ID,to_char(FAIL_TIME,'dd-mon-yyyy HH24:MI:SS'),STATE, MIXED FROM DBA_2PC_PENDING;
SELECT LOCAL_TRAN_ID, IN_OUT,INTERFACE, DATABASE FROM DBA_2PC_NEIGHBORS;
其中有如下五种state:
collecting
   -- execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');
prepared
   -- rollback force tran_id/commit force tran_id;
   EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');
committed
   -- execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');
forced commit
   -- execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');
forced ROLLBACK
   -- execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');

&#43;&#43;&#43;&#43;&#43;&#43; 如果遇到ORA-30019错误,可以采取如下方式:&#43;&#43;&#43;&#43;&#43;&#43;
ALTER SESSION SET &quot;_smu_debug_mode&quot; = 4;
EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.10.255');
====== 情况1 在dba_2pc_pending表中还有事务记录,但是实际已经不存在该事务了
SELECT LOCAL_TRAN_ID,
       GLOBAL_TRAN_ID,
       to_char(FAIL_TIME, 'dd-mon-yyyy HH24:MI:SS'),
       STATE,
       MIXED
FROM DBA_2PC_PENDING;
LOCAL_TRAN_ID         1.92.66874             prepared
1 为回滚段号
SELECT KTUXEUSN,
       KTUXESLT,
       KTUXESQN, /* Transaction ID */
       KTUXESTA STATUS,
       KTUXECFL Flags
FROM x$ktuxe
WHERE ktuxesta != 'INACTIVE'
AND ktuxeusn = 1
返回为0
如果当状态为prepared,且事务表中也不存在相关信息,那么我们只能手工进行清理:
&#43;&#43;&#43;&#43;&#43;&#43; 使用如下方式进行手工处理:&#43;&#43;&#43;&#43;&#43;&#43;
SET TRANSACTION USE ROLLBACK segment SYSTEM;
DELETE FROM sys.pending_trans$ WHERE local_tran_id = '1.92.66874';
DELETE FROM sys.pending_sessions$ WHERE local_tran_id = '1.92.66874';
DELETE FROM sys.pending_sub_sessions$ WHERE local_tran_id = '1.92.66874';
commit;
====== 情况2  在dba_2pc_pending表中无法查到分布式事务信息,但是实际上却是存在该分布式事务的
SELECT LOCAL_TRAN_ID,
       GLOBAL_TRAN_ID,
       to_char(FAIL_TIME, 'dd-mon-yyyy HH24:MI:SS'),
       STATE,
       MIXED
FROM DBA_2PC_PENDING;
查询无记录
SELECT local_tran_id, state
FROM dba_2pc_pending
WHERE local_tran_id = ' 1.92.66874 ';  -- 为空
SELECT KTUXEUSN,
       KTUXESLT,
       KTUXESQN, /* Transaction ID */
       KTUXESTA STATUS,
       KTUXECFL Flags
FROM x$ktuxe
WHERE ktuxesta != 'INACTIVE'
AND ktuxeusn = 1;
查询有记录
====== 此种情况下,我们无法手工进行ROLLBACK或commit ======
&#43;&#43;&#43;&#43;&#43;&#43; 我们用如下的方式手工清理:&#43;&#43;&#43;&#43;&#43;&#43;
ALTER system disable distributed recovery ;
INSERT INTO pending_trans $
(LOCAL_TRAN_ID,
GLOBAL_TRAN_FMT,
GLOBAL_ORACLE_ID,
STATE,
STATUS,
SESSION_VECTOR,
RECO_VECTOR,
TYPE #,
FAIL_TIME,
RECO_TIME)
VALUES
(' 1.92.66874 ',
306206,
' XXXXXXX.12345.1.2.3 ',
' prepared ',
' P ',
hextoraw(' 00000001 '),
hextoraw(' 00000000 '),
0,
sysdate,
sysdate);
INSERT INTO pending_sessions $
VALUES
(' 1.92.66874 ',
1,
hextoraw(' 05004F003A1500000104 '),
' C ',
0,
30258592,
'',
146);
commit ;
commit   force ' 1.92.66874 ' ;
&#43;&#43;&#43;&#43;&#43;&#43; 此时如果commit force还是出现报错,需要继续执行:&#43;&#43;&#43;&#43;&#43;&#43;
1. DELETE FROM pending_trans $ WHERE local_tran_id = '1.92.66874' ;
2. DELETE FROM pending_sessions $ WHERE local_tran_id = '1.92.66874' ;
3. commit ;
4. ALTER system enable distributed recovery ;     
5. ALTER SESSION SET &quot; _smu_debug_mode &quot; = 4 ;
6. EXEC dbms_transaction.purge_lost_db_entry ( '1.92.66874' )
====== 另外我们还可以通过如下SQL来捕获到导致分布式事务失败的SQL:======
&#43;&#43;&#43;&#43;&#43;&#43; 获取local_tran_id &#43;&#43;&#43;&#43;&#43;&#43;
SELECT a.sql_text, s.osuser, s.username
FROM v$transaction t, v$session s, v$sqlarea a
WHERE s.taddr = t.addr
AND a.address = s.prev_sql_addr
AND t.xidusn = 1
AND t.xidslot = 25
AND t.xidsqn = 589367;
如果 v$session 和 v$sqlarea 已经无法查到,那么我们还可以关联一些 dba_hist_* 试图进行查询。

还有一个找到一个解决办法:  网址为:  http://space.itpub.net/10173379/viewspace-626171


1.找到TRAN_ID  Select 'Rollback force '''||LOCAL_TRAN_ID||'''' from sys.pending_trans$;

2.將其COMMIT或ROLLBACK:  
rollback force LOCAL_TRAN_ID;  
commit force LOCAL_TRAN_ID;  

3.如果执行失败,则强行从资料字典中删除该交易记录:
set transaction use rollback segment system;   
delete from dba_2pc_pending where local_tran_id = LOCAL_TRAN_ID;   
delete from pending_sessions$ where local_tran_id = LOCAL_TRAN_ID;   
delete from pending_sub_sessions$ where local_tran_id = LOCAL_TRAN_ID;   
commit;

4.执行失败,还一种情况可以尝试下重起一下Oracle服务,这种情况我遇到过一次,重新启动后该锁自动解除(因为对删除数据字典比较担心,所以胡乱试了一次重启数据库,前提是执行了commit force LOCAL_TRAN_ID;失败之后重新启动)

5.生成语句操作语句的程序
begin
  for r in (select local_tran_id  
              from dba_2pc_pending t  
             where t.state = 'collecting') loop  
    --dbms_output.put_line('commit force '''||r.local_tran_id||''';');  
    dbms_output.put_line('delete from dba_2pc_pending where local_tran_id = '''||r.local_tran_id||''';');  
    dbms_output.put_line('delete from pending_sessions$ where local_tran_id = '''||r.local_tran_id||''';');  
    dbms_output.put_line('delete from pending_sub_sessions$ where local_tran_id = '''||r.local_tran_id||''';');  
  end loop;  
  dbms_output.put_line('commit;');  
end;



  



版权声明:本文为博主原创文章,未经博主允许不得转载。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-136434-1-1.html 上篇帖子: impdp传输表空间错误小记 ORA-39083: Object type INDEX_STATISTICS failed to create with er 下篇帖子: ORA_ERROR大全
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表