分布式事务,简单来说,是指一个事务在本地和远程执行,本地需要等待确认远程的事务结束后,进行下一步本地的操作。如通过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' )
相关推荐
TJDTP是一个非常优秀的框架,优势在于提高了应用的成功率,自动进行分布式事务处理,事务处理速度快,提高了数据的一致性,把对事务的处理由不可控变为可控,需要人工处理的故障可一键完成,简单快捷,实现事务处理...
MOONWATER是一个非常优秀的框架,优势在于提高了应用的成功率,自动进行分布式事务处理,事务处理速度快,提高了数据的一致性,把对事务的处理由不可控变成可控,需要人工处理的故障可一键完成,简单快捷,实现事务...
这是处理分布式事务(尤其是进行错误恢复/清除)的首选方法。 Sage最好保证传奇中的所有事务都已成功完成,或者要补偿所有事务确实在运行以修改部分执行。 就像Ecto.Multi但是跨业务逻辑和第三方API。 -@jayjun ...
分布式事务的一般结构是什么 答:分布式事务的一般结构为: Begin Transaction原语:开始一个事务(2分) T1[] T2[] : 子事务或操作序列 : Tn[] Commit原语:事务成功完成的结束(2分) Rollback或Abort原语:事务...
1.4. 设数据项x,y存放在S1场地,u,v存放在S2场地,有分布式事务T1和T2,T1在S1场地的操作为R1(x)W1(x)R1(y)W1(y),T2在S1场地的操作为R2(x)R2(y)W2(y);T1在S2场地上的操作作为R1(u)R1(v)W1(u),T2在S2场地上的操作作为...
分布式数据库的分布式事务处理技术 分布式数据库选型与实战 服务vivo数亿用户的数据库服务平台实践 广告实时数仓建设实践 海量异构数据,在线业务存储架构演进与实践 基于图数据库的应用元数据平台实践 基于MySQL的...
-- 清理每个分布式事务都需要commit; 数据泵 1. 相关参数 PARALLEL参数考虑 可以设置成物理CPU(不是逻辑CPU)数的两倍数目,然后调整 对于Data Pump Export,PARALLEL参数必须要小于等于dump files数 ...
1.4. 设数据项x,y存放在S1场地,u,v存放在S2场地,有分布式事务T1和T2,T1在S1场地的操作为R1(x)W1(x)R1(y)W1(y),T2在S1场地的操作为R2(x)R2(y)W2(y);T1在S2场地上的操作作为R1(u)R1(v)W1(u),T2在S2场地上的操作作为...
大数据分布式有序计算(例如行情数据处理-定时任务调度等).zip 分布式强有序实时计算 -- 第一版(一个master节点 多个slave节点,轻量级storm golang版本) 应用场景:大数据(行情数据)处理/定时任务调度等 功能: ...
我们仅仅是想写个程序把几台甚至更多的机器一起用起来计算,把更多的cpu和内存利用上,来解决我们数量大和计算复杂的问题,当然这个过程中要考虑到分布式的协同和故障处理。如果仅仅是为了实现这个简单的初衷,为...
当一级处理单元速度,直接配置一下并发数,即可线性扩展性能健壮强:当Worker失效或机器出现故障时, 自动分配新的Worker替换失效Worker数据准确性:可以采用Ack机制,保证数据不丢失。 如果对精度有更多一步要求,...
支持分布式事务(弱xa)。 支持XA分布式事务(1.6.5)。 支持全局序列号,解决分布式下的主键生成问题。 分片规则丰富,插件化开发,易于扩展。 强大的web,命令行监控。 支持前端作为MySQL通用代理,后端JDBC方式...
分布式数据库系统的优缺点 分布式数据库系统的优点 分布式数据库系统是在冀中是数据库系统的基础上发展来...分布式数 据库系统中要注意解决分布式数据库的设计、查询处理和优化、事务管理及 并发控制和目录管理等问题。
分布式数据库系统中要注意解决分布式数据库的设计、查询处理和优化、事务管理及并发控制和目录管理等问题。 在一个分布式系统中,一组独立的计算机展现给用户的是一个统一的整体,就好像是一个系统似的。系统拥有...
我们不支持分布式事务处理协调器(DTC)或负责在多个云资源之间协调事务的两阶段提交协议。 我们需要一种协调多个本地交易的机制。 什么是传奇模式? Saga是一种用于处理“长期交易”(LLT)的设计模式,由Garcia-...
它具有分布式架构,可以优雅地向外扩展,并在像单个 ACID 数据库一样运行的同时处理故障。 FoundationDB 在商品硬件上提供惊人的性能,让您能够以低成本支持非常重的负载。 FoundationDB 已在生产环境中运行多年,...
主从复制 (Master-Slave Replication):一个主服务器处理写操作,一个或多个从服务器处理读操作。 集群解决方案:如MySQL Group Replication, MySQL NDB Cluster等。 自动故障转移:当主服务器宕机时,自动将一个从...
对于一个好的分布式系统来讲,设计时应当考虑到异构性、开放性、安全性、可扩展性、故障处理、并发性以及透明性等问题。基于SOAP的Web Service可以实现异构环境的互操作性,保证了跨平台的通信。利用WSE(Web ...