分布式事务,简单来说,是指一个事务在本地和远程执行,本地需要等待确认远程的事务结束后,进行下一步本地的操作。如通过dblink update远程数据库的一行记录,如果在执行过程中网络异常,或者其他事件导致本地数据库无法得知远程数据库的执行情况,此时就会发生in doublt的报错。此时需要dba介入,且需要分多种情况进行处理。
分布式事务在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。(eygle在这篇文章中也测试过)
至此,所有的点都完成了准备工作,我们开始进入COMMIT PHASE阶段,此时除commit point site点外所有点的事务均为in doubt状态,直到COMMIT PHASE阶段结束。
如果数据库在此阶段出现问题,我们查询(假设远程数据库为commit point site,且本地数据库为Global Coordinator):
select local_tran_id,state from dba_2pc_pending;
LOCAL_TRAN_ID STATE
---------------------- ----------------
2.12.64845 collecting
select local_tran_id,state from dba_2pc_pending;
no rows selected
即表示本地数据库要求其他点做好commit或者rollback准备,现在正在“收集”其他点的数据库的返回信息,但是远程数据库未知状态(in doubt)。我们需要将本地的Global Coordinator的状态清除掉:
或者我们在查询的时候发现是如下的状态:
select local_tran_id,state from dba_2pc_pending;
LOCAL_TRAN_ID STATE
---------------------- ----------------
2.12.64845 prepared
select local_tran_id,state from dba_2pc_pending;
no rows selected
即表示本地Global Coordinator已经做好准备,已经将分布式锁放到各个事务的表上,但是远程数据库的状态再次未知(in doubt),我们需要手工的将本地的transaction rollback掉,并且清除分布式事务信息:
rollback force 'local_tran_id';
execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('local_tran_id');
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。
如果数据库在此阶段出现问题,我们查询
select local_tran_id,state from dba_2pc_pending;
LOCAL_TRAN_ID STATE
---------------------- ----------------
2.12.64845 prepared
select local_tran_id,state from dba_2pc_pending;
LOCAL_TRAN_ID STATE
---------------------- ----------------
1.92.66874 commited
即远程数据库可能已经commit,但是本地Global Coordinator未知远程数据库的状态,还是处于prepare的状态。我们需要在如下处理:
commit force 'local_tran_id';
execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('local_tran_id');
execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('local_tran_id');
或者我们在查询的时候发现是如下的状态:
select local_tran_id,state from dba_2pc_pending;
LOCAL_TRAN_ID STATE
---------------------- ----------------
2.12.64845 commited
select local_tran_id,state from dba_2pc_pending;
LOCAL_TRAN_ID STATE
---------------------- ----------------
1.92.66874 commited
即远程数据库和本地数据库均已经完成commit,但是分布式事务的信息尚未清除,我们需要在本地和远程运行:
execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('local_tran_id');
execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('local_tran_id');
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清除分布式事务信息。
此时如果出现问题,我们查询:
select local_tran_id,state from dba_2pc_pending;
LOCAL_TRAN_ID STATE
---------------------- ----------------
2.12.64845 commited
select local_tran_id,state from dba_2pc_pending;
no rows selected
即远程commit point site已经完成commit,通知Global Coordinator清除本地的分布式事务信息,但是Global Coordinator没有收到该信息。我们需要这样处理:
execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('local_tran_id');
综上,分布式事务的依次状态为:
phase local_state remote_state action
----------- ---------- ------------------ -------------------
prepare collecting / 本地DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY
prepared / 本地rollback force后PURGE_LOST_DB_ENTRY
commit prepared commited 本地commit force后本地和远程均PURGE
commited commited 本地和远程均PURGE_LOST_DB_ENTRY
forget commited / 本地PURGE_LOST_DB_ENTRY
另,当我们遇到使用rollback/commit force的时候,无法正常的清除分布式事务的信息,会报错ORA-02058: no prepared transaction found with ID X.XX.XXXXX时,我们需要通过手工方式来清除该信息。(注,以下方式修改数据字典,存在风险,使用前请备份好你的数据库)
情况1,在dba_2pc表中还有事务记录,但是实际已经不存在该事务了:
LOCAL_TRAN_ID STATE
---------------------- ----------------
1.92.66874 prepared
(注:'1.92.66874' 的结构为rbs#, slot#, wrap#,此事务在rollback segment #1)
我们再用如下语句找出使用rollback segment #1且状态是active的transaction:
SELECT KTUXEUSN, KTUXESLT, KTUXESQN, /* Transaction ID */
KTUXESTA Status,
KTUXECFL Flags
FROM x$ktuxe
WHERE ktuxesta!='INACTIVE'
AND ktuxeusn= 1; <== 这是rollback segment#,即rbs#
no rows selected
因此我们在rollback force的时候会报错:
我们需要如下处理:
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表中无法查到分布式事务信息,但是实际上却是存在该分布式事务的:
我们在alertlog中可以看到:
我们查询dba_2pc的表,发现没有分布式事务信息:
where local_tran_id='1.92.66874';
no rows selected
但是去查实际的rollback segment信息,却发现有prepared状态的分布式事务存在:
KTUXESTA Status,
KTUXECFL Flags
FROM x$ktuxe
WHERE ktuxesta!='INACTIVE'
AND ktuxeusn= 1;
KTUXEUSN KTUXESLT KTUXESQN STATUS FLAGS
---------- ---------- ---------- ---------------- ------------------------
1 92 66874 PREPARED SCO|COL|REV|DEAD
我们无法做commit force或者rollback force:
ORA-02058: no prepared transaction found with ID 1.92.66874
我们用如下的方式手工清理:
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', /* <== 此处为你的local tran id */
306206, /* */
'XXXXXXX.12345.1.2.3', /* 这些值不必更改, */
'prepared','P', /* 是静态参数,可以直接 */
hextoraw( '00000001' ), /* 在这个sql中使用 */
hextoraw( '00000000' ), /* */
0, sysdate, sysdate );
insert into pending_sessions$
values( '1.92.66874',/* <==此处为你的local tran id */
1, hextoraw('05004F003A1500000104'),
'C', 0, 30258592, '',
146
);
commit;
commit force '1.92.66874';
此时如果commit force还是出现报错,需要继续执行:
delete from pending_trans$ where local_tran_id='1.92.66874';
delete from pending_sessions$ where local_tran_id='1.92.66874';
commit;
alter system enable distributed recovery;
此时如果没有报错,则执行以下语句:
alter system enable distributed recovery;
and purge the dummy entry from the dictionary, using
connect / as sysdba
alter session set "_smu_debug_mode" = 4;
(注:如果使用auto的undo管理方式,需要执行此步骤,此步骤能避免在后续执行purge_lost_db_entry出现ORA-01453 的报错,详细信息可见Bug 2191458)
commit;
exec dbms_transaction.purge_lost_db_entry( '1.92.66874' )
相关推荐
在大规模的SOA(Service-Oriented Architecture,面向服务架构)系统中,分布式事务处理是一项至关重要的技术。这种架构通常涉及多个独立的服务协同工作,每个服务都可能有自己的数据存储,因此,确保这些服务之间的...
在分布式环境中,由于多个服务之间可能存在数据交互,因此需要一种机制来处理跨服务的数据一致性问题,这就是分布式事务的核心目标。本示例("java分布式事务demo")很可能是为了演示如何在Java应用程序中实现这一...
分布式事务处理是现代大型服务导向架构(SOA)系统中不可或缺的一部分,特别是在诸如支付宝这样的高并发、高可用性环境中。本讲义将深入探讨在Java环境下实现大规模SOA系统中的分布式事务处理的关键技术和挑战。 ...
在大规模的Service-Oriented Architecture (SOA)系统中,分布式事务处理是一个核心且复杂的议题。本文基于程立,一位知名的技术领导者,同时也是蚂蚁集团的CTO,分享的分布式事务解决方案进行深入探讨。 首先,我们...
分布式事务是指在分布式系统中,为了确保跨多个节点上的操作能够正确地完成或者全部回滚,所采取的一种事务处理机制。在这样的场景下,事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的...
6. **分布式事务的挑战与解决方案**:包括网络延迟、单点故障、数据一致性等问题,常见的解决方案有故障恢复机制、超时重试策略、幂等性设计等。 7. **NoSQL数据库的分布式事务**:NoSQL数据库通常不支持ACID(原子...
例如,用户资产由余额、积分、优惠券等多个部分组成,每个部分可能由不同的微服务来处理,这就导致了分布式事务的出现,因为要保证这些操作的原子性和一致性。 数据库的ACID原则保证了本地事务的可靠性,但在分布式...
### 分布式事务若依框架文档 #### 一、分布式事务基本概念 在理解分布式事务之前,我们...通过以上步骤,我们可以搭建起一个基于Seata的分布式事务处理环境,从而更好地理解和实践分布式事务的处理过程和技术细节。
在这样的背景下,分布式事务成为了处理跨服务数据一致性问题的关键技术。 **分布式事务**是指涉及两个或更多节点上的资源管理器的一组操作,这些操作要么全部完成,要么全部不完成。它确保了不同服务之间数据的一致...
这些协议在处理分布式事务时,能够保证系统在面临网络分区或节点故障时仍然能按照预定的方式处理事务。 在分布式事务的控制解决方案中,还可以采用消息队列保证事务的一致性。通过消息队列,可以实现服务间的解耦,...
首先,分布式事务是指跨越多个数据库或者存储系统的事务处理,其目标是确保这些操作要么全部成功,要么全部失败,保持数据的一致性。在大规模分布式系统中,由于网络延迟、服务故障等因素,实现这样的事务处理非常...
在大规模的SOA(Service-Oriented Architecture,面向服务架构)系统中,分布式事务处理是一项至关重要的技术。本文将深入探讨这一主题,基于程立的资料,主要关注分布式事务处理模型、XA规范以及两阶段提交和三阶段...
### 分布式事务详细介绍 #### 一、分布式事务概述 分布式事务是指在分布式系统中,为了保持事务的...随着技术的发展,分布式事务的处理方式也在不断进步和完善,为构建更加健壮、可靠的分布式系统提供了坚实的基础。
分布式事务是大型分布式系统中必不可少的一个技术环节,它旨在确保在多节点、多数据库环境下的数据一致性。在当今云计算和微服务架构盛行的时代,分布式事务的重要性愈发凸显。本资料包"分布式事务解决方案.zip"深入...
2PC(两阶段提交)是一种经典的分布式事务处理算法,它试图通过协调参与者的操作来实现全局的一致性。 **两阶段提交(2PC)的工作原理** 1. **准备阶段(投票阶段)**: 在这个阶段,事务协调者(通常是应用...
《LINQ to SQL 分布式事务处理》是针对.NET框架中使用LINQ to SQL进行数据库操作时,如何处理复杂业务场景下涉及多个数据源的事务一致性问题的专业书籍。LINQ (Language Integrated Query) 是.NET Framework引入的一...
若依框架作为一款广受欢迎的Java开发框架,提供了丰富的功能支持,包括分布式事务处理。本文将深入探讨若依框架在分布式事务配置以及项目启动方面的知识,帮助开发者更好地理解和应用。 1. **若依框架简介** 若依...
分布式事务是数据库事务处理的一种形式,它涉及在一个分布式计算环境中,跨多个数据库或计算节点...在实际开发过程中,可能还需要考虑性能优化、故障恢复、安全性保障等因素,确保分布式事务应用能够稳定、高效地运行。