怎么处理ORACLE悬疑分布式事务问题
这篇文章主要讲解了“怎么处理ORACLE悬疑分布式事务问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么处理ORACLE悬疑分布式事务问题”吧!
当需要在多个Oracle数据库之间进行数据一致性操作时,就会用到分布式事务。
例如:
insertintoT_log@remote_db;--远程数据库插入insertintoT_local;--本地数据库插入commit;
分布在本地和远程两个db的事务同时操作,这就构成了一个分布式事务。
分布式事务采用Two-Phase Commit提交机制,保证分布在各个节点的子事务能够全部提交或全部回滚的原子性。在这种机制下,事务处理过程分为三个阶段:
PREPARE:发起分布式事务的节点通知各个关联节点准备提交或回滚。各关联节点此时会做三个事情:刷新redo信息到redo log中;将持有的锁转换为悬疑事务锁;取各节点中最大的SCN号进行同步
COMMIT:写入commited SCN,释放锁资源
FORGET:悬疑事务表和关联的数据库视图信息清理
由于分布式事务涉及到多个数据库之间进行操作,偶尔会遇到一些异常情况(例如系统或网络中断)导致上述三个阶段出现异常,这就在一个或多个节点上,产生不完整的“悬疑分布式事务”。
大多数情况下,出现这种问题,Oracle会由Reco进程进行自动修复,Oracle数据库会在dba_2pc_pending 和dba_2pc_neighbors等多个视图中记录分布式事务相关的信息,事实上reco进程也是基于这些信息去做自动修复的。
Reco进程会尝试连接到其他节点获取分布式事务信息,然后尝试修复失败的事务,并将对应的事务中的记录删除。
但有些情况下(例如节点无法正常访问或事务表中记录的数据不完整),Reco进程不能正常完成这个工作,就会抛出异常。对于分布式事务,对应的异常代码区间是ORA-02040 - ORA-02099,可通过alert日志查看到错误信息。
例如:
ORA-02054:transactionin-doubtThetransactionisneithercommittedorrolledbacklocally,andwehavelostcommunicationwiththeglobalcoordinator.
此时往往需要手工处理进行干预。
以下是三种常见的分布式事务问题场景:
dba_2pc视图中有数据,但分布式事务已经不存在
分布式事务存在,但dba_2pc视图中没有数据
事务和视图数据都有,但是执行commit force或rollback force时hang住
通过报错会有提示,例如:
ORA-01591:lockheldbyin-doubtdistributedtransaction10.20.360这个10.20.360就是我们需要检查分布式事务ID
场景一:dba_2pc视图中有数据,但分布式事务已经不存在
视图有数据,那么先检查数据的状态
select*fromdba_2pc_pendingwherelocal_tran_id='10.20.360';
主要看state字段。
如果事务已经是committed, rollback forced或者commit forced状态,表示事务已经完成了,但是在FORGET阶段处理时,数据库字典的信息没能及时清除。此时,我们调用oracle的清理丢失事务信息的语句就可以完成处理:
executeDBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('10.20.360');
如果事务是PREPARED状态,但是在事务表中又没有活动的事务:
SELECTKTUXEUSN,KTUXESLT,KTUXESQN,/*TransactionID*/KTUXESTAStatus,KTUXECFLFlagsFROMx$ktuxeWHEREktuxesta!='INACTIVE'ANDktuxeusn=10;--注意替换这里的回滚段号(xid=usn.slot.(sqn+1))----没有活动的事务
那此时需要手工清理丢失事务的信息
settransactionuserollbacksegmentSYSTEM;deletefromsys.pending_trans$wherelocal_tran_id=;deletefromsys.pending_sessions$wherelocal_tran_id=;deletefromsys.pending_sub_sessions$wherelocal_tran_id=;commit;
场景二:分布式事务存在,但dba_2pc视图中没有数据
遇到ORA-2054, ORA-1591等错误,检查dba_2pc视图没有记录,这种场景不常见,只在少数极端的情况下出现。
先确认现象,分别检查x$ktuxe和 dba_2pc_pending视图,查询语句与场景一相同
在这种情况下无论是执行commit force还是rollback force,都会直接抛出异常:
commitforce'10.20.360';ORA-02058:nopreparedtransactionfoundwithID10.20.360
这时我们需要将视图对应的基表数据补入,然后再执行rollback force。
altersystemdisabledistributedrecovery;insertintopending_trans$(LOCAL_TRAN_ID,GLOBAL_TRAN_FMT,GLOBAL_ORACLE_ID,STATE,STATUS,SESSION_VECTOR,RECO_VECTOR,TYPE#,FAIL_TIME,RECO_TIME)values('10.20.360',/*<==Replacethiswithyourlocaltranid*/306206,'xxxxxxxx.00000.0.0.0','prepared','P',hextoraw('00000001'),hextoraw('00000000'),0,sysdate,sysdate);insertintopending_sessions$values('10.20.360',1,hextoraw('00000000'),'C',0,1433927502,'',14);--1433927502为DBID,14为useridcommit;rollbackforce'10.20.360';EXECUTEDBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('10.20.360');--手工清理事务信息
场景三:事务和视图数据都有,但是执行commit force或rollback force时hang住
如果视图和事务表中都有数据,而且状态是PREPARED,先执行commit force或rollback force,通常就能解决问题,但有时候也会遇到执行force处理时hang住
尝试purge事务信息时,有提示报错:
BEGINDBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('10.20.360');END;*ERRORatline1:ORA-06510:PL/SQL:unhandleduser-definedexceptionORA-06512:at"SYS.DBMS_TRANSACTION",line94ORA-06512:atline1
此时需要进行场景一和场景二的结合起来的所有步骤:
1.先将视图对应的基表数据删除deletefromsys.pending_trans$wherelocal_tran_id='10.20.360';deletefromsys.pending_sessions$wherelocal_tran_id='10.20.360';deletefromsys.pending_sub_sessions$wherelocal_tran_id='10.20.360';commit;2.再插入pending_trans$和pending_sessions$数据,见场景二3.rollbackforce'10.20.360';4.Purgethetransaction:execdbms_transaction.purge_lost_db_entry('10.20.360');
感谢各位的阅读,以上就是“怎么处理ORACLE悬疑分布式事务问题”的内容了,经过本文的学习后,相信大家对怎么处理ORACLE悬疑分布式事务问题这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。