基本概念
Local Coordinator:在分佈事務中,必須參考其它節點上的數據才能完成本身這部分操做的站點。
Global Coordinator:分佈事務的發起者,負責協調這個分佈事務。
Commit Point Site:在分佈事務中,首先執行COMMIT或ROLLBACK操做的站點。通常狀況下,應該把存儲關鍵數據的站點做爲Commit Point Site。由於Commit Point Site和其它站點不同,歷來不會進入prepared狀態,因此不會存在IN-DOUBT事務。
能夠設置初始化參數COMMIT_POINT_STRENGTH,在分佈式事務中,會根據這 個值的大小來肯定Commit Point Site,分佈事物的狀態信息也存在該數據庫中。通常將關鍵的數據庫做爲commit point site ,commit_point_strength值較高的數據庫爲commit point site,在分佈事物中最早提交
分佈式提交的3個階段
分佈事物的兩階段提交分三個過程:
1. 準備階段(PREPARE PHASE)
·本地數據庫Global Coordinator向其它數據庫發出COMMIT通知
·比較全部數據庫的SCN號,將最高的SCN號做爲分佈事物的全局SCN號
·全部數據庫寫在線日誌
·對分佈事物修改的表加分佈鎖,防止被讀寫
·各數據庫向Global Coordinator發出已經準備好的通知
全部參與分佈事物的數據庫必須通過上述準備,才能進入下一階段。
2. 提交階段(COMMIT PHASE)
·本地數據庫Global Coordinator通知commit point site首先提交。commit point site提交後,釋放其佔有的資源,通知Global Coordinator完成提交
·本地數據庫Global Coordinator通知其它數據庫提交
·提交節點在日誌中追加一條信息,表示分佈事物已經完成提交,並通知Global Coordinator。此時全部數據庫的數據保持了一致性。
3. 註銷階段(FORGET PHASE)
·本地數據庫Global Coordinator通知commit point site全部數據庫已經完成提交
·commit point site清除分佈事物的記錄和狀態信息,並通知Global Coordinator
·Global Coordinator清除本地分佈事物的記錄和狀態信息
此時分佈事物的兩階段提交所有完成。
若是兩階段提交完成以前,數據庫或網絡出現異常,應用就會報錯,分佈事物處於IN_DOUBT狀態。一旦數據庫或網絡恢復正常,系統(RECO PROCESS)會自動處理IN_DOUBT狀態的分佈事物。有些狀況須要管理員手工處理IN_DOUBT狀態的分佈事物:
·IN_DOUBT狀態的分佈事物,將關鍵表鎖住,形成應用不能正常工做
兩個重要的視圖
DBA_2PC_PENDING:列出全部的懸而未決的事務﹐此視圖在末填入懸而未決的事務以前是空的﹐解決這後也被清空。
列名
|
說明
|
LOCAL_TRAN_ID
|
本地事務標識﹐格式爲integer.integer.ingeger。
當一個鏈接的local_tran_id和global_tran_id相同時﹐那麼該節點是該事務的全局協調器。
|
GLOBAL_TRAN_ID
|
全局事務標識,格式爲﹕global_db_name.db_hex_id.local_tran_id,其中db_hex_id是用來標識數據庫八字符的十六進制數﹐公共事各id在分佈式事務的每一個節點都是相同的。
|
STATE
|
下圖表進行說明
|
MIXED
|
「YES」意味着一部分事務已經在一個節點上提交﹐而在另外一個節點上被回滾。
|
TRAN_COMMENT
|
事務的註釋﹐或者若是使用了事務命名﹐當事各被提交時﹐事務的名字就會出如今此處
|
Host
|
主機名
|
Commit#
|
已提交的事務的全局提交數
|
DBA_2PC_PENDING的STATE列的說明
列值
|
說明
|
Connecting
|
一般狀況下﹐只有全局協調器和本地協調器才使用這個條目﹐節點在可以決定它是否可以準備好以前﹐要收集來自於其它數據庫服務的信息。
|
Prepared
|
節點已準好﹐可能或者也可能沒有將已準備好的消息通知本地協調器﹐但此時﹐該節點尚未接收到提交的請求﹐仍保持着准許備好的狀態﹐控制着提交事務所必需的任何本地資源。
|
Commited
|
節點(任何類型)已經提交了事務﹐但該事務所包含的其它節點可能並無提交﹐也就是該事務在一個個或多個其它節點上仍然是懸而未決 。
|
Forced commit
|
DBA進行判斷後﹐能夠強行提交未決的事務﹐若是一個事務由DBA在本地節點進行手動提交時﹐產生此項目
|
Forced abor(rollback)
|
DBA進行判斷後﹐能夠強行回滾未決的事務﹐若是一個事務由DBA在本地節點進行手動回滾時﹐產生此項目
|
DBA_2PC_NEIGHBORS:列出全部得到的(從遠程客戶)和送出的(給遠程服務器)懸而未決的事務﹐也表示該本地節點是否是事務的提交點站點。
LOCAL_TRAN_ID
|
同上
|
IN_OUT
|
得到事務爲IN﹐送出事務爲OUT
|
Database
|
對得到事務來講指本地節點信息的客戶數據庫的名稱﹔對送出的事務來講指用於訪問遠程服務器上信息的數據庫連接的名稱
|
DBuser_owner
|
對得到事務來講指遠程數據庫連接用於鏈接的本地帳戶﹔對於送出事務來講指該數據庫連接的擁有者。
|
INTERFACE
|
‘C’表明提交信息﹐’N’表示已準備好狀態的一條消息或是一條請求只讀提交的請求。
當’IN_OUT’爲OUT時﹐’C’表示該鏈接的遠程的站點是提交點站點,而且知道是提交仍是中斷。’N’表示本地節點正在通知遠程節點﹐說它已準備好。
當’IN_OUT’爲IN時﹐‘C’表示本地節點或送出的遠程的一個數據庫是提交點站點﹐’N’表示本地節點正在通知遠程節點﹐說它已準備好。
|
處理懸掛事務的通常步驟
一、 檢查alert文件,發現相似下面error:
ORA-1591 "lock held by in-doubt distributed transaction %s"
ORA-2062 "distributed recovery received dbid x, expected y"
ORA-2068 "following severe error from %s%s"
二、 確認網絡是否正常、dblink是否valid、v$dblink和gv$dblink中查詢當前是否在使用分佈式事務。
三、 查詢視圖dba_2pc_pending,查詢懸掛事務信息:
SELECT LOCAL_TRAN_ID, GLOBAL_TRAN_ID, STATE, MIXED, HOST, COMMIT#
FROM DBA_2PC_PENDING
WHERE LOCAL_TRAN_ID = '??.';
若是沒有記錄,說明RECO進程已經自動處理了該事務。
四、 在全部節點上查詢視圖dba_2pc_neighbors
五、 獲得全部節點的COMMIT_POINT_STRENGTH值,值最大的爲commit point site,即最先提交的點,若是懸掛事務發生在commit point site,則它的state決定了整個分佈式事務的狀態。懸掛事務是否應該commit force或者是rollback force,由此節點決定。
六、 檢查dba_2pc_pending的state列,若是是commited,意味着本地數據庫提交已經成功。其餘節點須要根據本地事務號和最大的commit#進行強制提交。用法以下:
SVRMGR> COMMIT FORCE 'your local transactionID on this node', 'highest SCN from already committed site';
SVRMGR> COMMIT FORCE '1.13.5197', '88123887';
七、 若是commit point site的state爲commited外的其餘狀態,則代表commit point site 沒有提交成功,分佈式事務須要強制回滾。這裏再也不須要全部節點的最大commit#。用法以下:
SVRMGR> ROLLBACK FORCE 'your local transactionID on this node';
SVRMGR> ROLLBACK FORCE '1.13.5197';
八、 清除dba_2pc_pending和dba_2pc_neighbers的相關記錄。通常分佈式事務自動恢復後,視圖內容會自動清除,若是是手工提交的事務,則須要用dbms_transaction包手工清除,清除規則以下表所示:
肯定什麼時候能使用DBMS_TRANSACTION
State列
|
全局事務狀態
|
本地事務狀態
|
一般的動做
|
可選擇的動做
|
Collecting
|
Rollback
|
Rollback
|
無
|
Purge_lost_db_entry(只有當自動回覆不能解決事務時)
|
Committed
|
Committed
|
Committed
|
無
|
Purge_lost_db_entry(只有當自動回覆不能解決事務時)
|
Prepared
|
Unknown
|
Prepared
|
無
|
強行提交或回滾
|
Forced
Commit
|
Unknown
|
Committed
|
無
|
Purge_lost_db_entry(只有當自動回覆不能解決事務時)
|
Forced rollback
|
Unknown
|
Rollback
|
無
|
Purge_lost_db_entry(只有當自動回覆不能解決事務時)
|
Forced commit
|
Mixed
|
Committed
|
手動刪除不一致性﹐而後使用purge_mixed
|
|
Forced rollback
|
Mixed
|
Rollback
|
手動刪除不一致性﹐而後使用purge_mixed
|
|
測試記錄
¡ 設置db1的commit_point_strength爲1,db2的commit_point_strength爲2,db2爲commit point site。
¡ db一、db2上執行100次insert循環,每次循環用分佈式事務插入db1和db2中的測試表。中間reboot db2服務器。此時db1對測試表的查詢出現如下錯誤:
SQL> select count(1) from temp.my_table;
select count(1) from temp.my_table
*
ERROR at line 1:
ORA-01591: lock held by in-doubt distributed transaction 7.30.7415
[oracle@db2 bdump]$ tail -f alert_ntespay.log
Tue Mar 4 14:14:28 2008
DISTRIB TRAN 1234.4F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
is local tran 7.30.7415 (hex=07.1e.1cf7)
insert pending prepared tran, scn=934346533 (hex=0.37b0ff25)
db1中分佈式事務相關的2個視圖內容以下:
select a.* from dba_2pc_pending a where LOCAL_TRAN_ID='7.30.7415';
LOCAL_TRAN_ID GLOBAL_TRAN_ID STATE MIXED ADVICE TRAN_COMMENT FAIL_TIME FORCE_TIME RETRY_TIME OS_USER OS_TERMINAL HOST DB_USER COMMIT#
1 7.30.7415 4660.4F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 prepared no 2008-3-4 14:14:28 2008-3-4 14:22:56 zhenxingzhai ZHAIZHENXING NETEASE\ZHAIZHENXING 934346533
其中,
state有如下幾種狀態:
Collecting, prepared, committed, forced commit, or forced rollback
mixed表示是否部分提交,部分回滾
advice:
C
for commit,
R
for rollback, else
NULL
select a.* from dba_2pc_neighbors a where LOCAL_TRAN_ID='7.30.7415';
LOCAL_TRAN_ID IN_OUT DATABASE DBUSER_OWNER INTERFACE DBID SESS# BRANCH
1 7.30.7415 in NULLjavaxa.oracle.com TEMP N javaxa_orcl 1 01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
此視圖說明了數據源1的輸入鏈接信息。由於數據源2不是經過dblink鏈接的,以此沒有出現它的記錄。
¡ db2重啓後查詢my_tab:
SQL> select count(1) from my_tab;
COUNT(1)
----------
75
¡ 由於db2中dba_2pc_pending和dba_2pc_neighbers中沒有記錄,而且db2爲commit point site,沒有記錄意味着沒有進行任何操做,因此db1應該和db2同樣,進行強制rollback。
SQL> conn / as sysdba
Connected.
SQL> rollback force '7.30.7415';
Rollback complete.
SQL> select count(12) from temp.my_table;
COUNT(12)
----------
75
db1的alert日誌中顯示了可疑事務的回滾過程:
Tue Mar 4 15:14:31 2008
DISTRIB TRAN 1234.4F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
is local tran 7.30.7415 (hex=07.1e.1cf7)
change pending prepared tran, scn=934346533 (hex=0.37b0ff25)
to pending forced rollback tran, scn=934346533 (hex=0.37b0ff25)
¡ 回滾後,兩個視圖中的狀態更改成以下:
select a.* from dba_2pc_pending a where LOCAL_TRAN_ID='9.33.5992';
LOCAL_TRAN_ID GLOBAL_TRAN_ID STATE MIXED ADVICE TRAN_COMMENT FAIL_TIME FORCE_TIME RETRY_TIME OS_USER OS_TERMINAL HOST DB_USER COMMIT#
1 7.30.7415 4660.4F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 forced rollback no 2008-3-4 14:14:28 2008-3-4 15:14:31 2008-3-4 15:20:07 zhenxingzhai ZHAIZHENXING NETEASE\ZHAIZHENXING 934346533
select a.* from dba_2pc_neighbors a where LOCAL_TRAN_ID='9.33.5992';
LOCAL_TRAN_ID IN_OUT DATABASE DBUSER_OWNER INTERFACE DBID SESS# BRANCH
1 7.30.7415 in NULLjavaxa.oracle.com TEMP N javaxa_orcl 1 01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
¡ 去除dba_2pc_pending和dba_2pc_ neighbors中的記錄:
(1) Disable分佈式恢復
SQL> ALTER SYSTEM DISABLE DISTRIBUTED RECOVERY;
System altered.
(2)Puege(清空)in-doubt transaction entry:
SQL> exec DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('7.30.7415');
PL/SQL procedure successfully completed.
(3)commit;
(4)而後enable 分佈式恢復:
SQL> ALTER SYSTEM ENABLE DISTRIBUTED RECOVERY;
分佈式事務相關資料
Note:1012842.102
Note:100664.1
Note:274321.1
Note:126069.1
[url]http://www.itk.ilstu.edu/docs/Oracle/server.101/b10739/ds_txns.htm#i1007721[/url]
本文出自 「帥小夥的博客」 博客,請務必保留此出處http://zhaizhenxing.blog.51cto.com/643480/134750java