• 分佈式事務故障處理暨ORA-24756: transaction does not exist處理


    ORA-24756处理

    看到警告日誌一直報ORA-24756錯誤

    Errors in file /oracle/admin/NHMIX01/bdump/nhmix01_reco_4959.trc:
    ORA-24756: transaction does not exist
    但是去找trace文件的時候卻沒有

    想到了事務的問題,查dba_2pc_pending

    select local_tran_id,state from dba_2pc_pending;
    LOCAL_TRAN_ID STATE
    6.22.290635 commited

    通过该视图我去到远端的数据库查询该是视图

    select local_tran_id,state from dba_2pc_pending;
    no rows selected.

    我嘗試

    commit force '6.22.290635'  卻發現被hang住了,其实此时不需要commit force了,此时是分布式事务的第三个阶段即forget phase发生错误,需要做的是在本地清除分布式事务信息。

    exec DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('6.22.290635');

    再kill了那个commit force动作。再去查询dba_2pc_pending的时候就找不到这个事务了。

    分佈式事務总结

    分布式事务,简单来说,是指一个事务在本地和远程执行,本地需要等待确认远程的事务结束后,进行下一步本地的操作。如通过dblink update远程数据库的一行记录,如果在执行过程中网络异常,或者其他事件导致本地数据库无法得知远程数据库的执行情况,此时就会发生in doubt的报错。此时需要dba介入,且需要分多种情况进行处理。

    分布式事务在commit提交时候,会经历3个阶段:
    1.PREPARE PHASE:
       1.1 决定哪个数据库为commit point site。(注,参数文件中commit_point_strength值[默认值为1]高的那个数据库为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):

    Scenario 1 collecting:

    select local_tran_id,state from dba_2pc_pending;
    LOCAL_TRAN_ID STATE
    6.22.290635 collecting

    remote DB

    select local_tran_id,state from dba_2pc_pending;
    no rows selected.

    即表示本地数据库要求做好commit或者rollback准备,现在正在收集其他点的数据库返回信息,但是远程数据库状态未知(in doubt),我们需要手动的将本地的Global Coordinator信息清除掉:

    SQL> exec DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('6.22.290635');

    PL/SQL procedure successfully completed.

    Scenario2:prepared

    select local_tran_id,state from dba_2pc_pending;
    LOCAL_TRAN_ID STATE
    6.22.290635 prepared

    remote DB

    select local_tran_id,state from dba_2pc_pending;
    no rows selected.

    即表示本地Global Coordinator已做好准备,已将分布式锁放到各个事务表上,但远程数据库的状态再次未知(in doubt),我们需要手动的将本地的transaction rollback掉,并且清除分布式事务信息:

    rollback force '6.22.290635';

    exec DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('6.22.290635');

    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。

    Scenario 1 local prepared ,remote commited

    local:
    select local_tran_id,state from dba_2pc_pending;
    LOCAL_TRAN_ID STATE
    6.22.290635 prepared
    remote DB:
    select local_tran_id,state from dba_2pc_pending;
    LOCAL_TRAN_ID STATE
    1.92.66874 commited

    即表示远程数据库可能已经commit,但是本地数据库未知远程数据库的状态,还是处于prepared状态。我们需要如下处理:

    local:
    commit force '6.22.290635';

    exec DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('6.22.290635');

    remote DB:

    exec DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.92.66874');

    Scenario2  local commited,remote commited

    local:
    select local_tran_id,state from dba_2pc_pending;
    LOCAL_TRAN_ID STATE
    6.22.290635 commited
    remote DB:
    select local_tran_id,state from dba_2pc_pending;
    LOCAL_TRAN_ID STATE
    1.92.66874 commited

    即表示本地和远程数据库均完成commit,但未清除分布式事务信息,我们需要如下处理:

    local:

    exec DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('6.22.290635');

    remote DB:

    exec DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.92.66874');

    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清除分布式事务信息。

    local:

    select local_tran_id,state from dba_2pc_pending;
    LOCAL_TRAN_ID STATE
    6.22.290635 commited

    remote DB

    select local_tran_id,state from dba_2pc_pending;
    no rows selected.

    即表示远端已完成commit,通知Global Coordinator清除分布式事务信息,但是本地没有收到该信息,我们改如下处理:

    local

    exec DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('6.22.290635');

    总结分佈式事務的狀態依次如下:

    phase local_state remote_state action
    prepare collecting
    prepared
    /
    /
    本地DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY
    本地rollback force后PURGE_LOST_DB_ENTRY
    commit prepared
    commited
    commited
    commited
    本地commit force后本地和遠程均PURGE
    本地和遠程均PURGE_LOST_DB_ENTRY
    forget commited / 本地PURGE_LOST_DB_ENTRY

    本文转载自http://www.oracleblog.org/working-case/how-to-deal-with-distributed-transaction/的博客

    不必太糾結于當下,也不必太憂慮未來
  • 相关阅读:
    NSURLSession 网络请求
    NSData 数据
    NSStream文件流
    NSFileManager文件管理
    NSCache 缓存
    NSUserDefaults数据存储
    NSKeyedArchiver数据归档
    子线程定时器的创建
    NSEnumerator迭代器
    NSDate 时间
  • 原文地址:https://www.cnblogs.com/guilingyang/p/5821160.html
Copyright © 2020-2023  润新知