共计 3808 个字符,预计需要花费 10 分钟才能阅读完成。
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 |
更多 Oracle 相关信息见Oracle 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=12
本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-09/135020.htm