應用報錯 ORA-02049: timeout: distributed transaction waiting for lock,經確認由參數 DISTRIBUTED_LOCK_TIMEOUT(預設 60 秒)控制。本文通過雙資料庫實驗完整重現並分析根因。
CREATE TABLE TEST (A NUMBER, B DATE);
INSERT INTO TEST VALUES (2, TO_DATE('16-04-2015 16:38:26','DD-MM-YYYY HH24:MI:SS'));
INSERT INTO TEST VALUES (1, TO_DATE('24-03-2015 16:32:36','DD-MM-YYYY HH24:MI:SS'));
INSERT INTO TEST VALUES (2, TO_DATE('16-04-2015 16:35:19','DD-MM-YYYY HH24:MI:SS'));
INSERT INTO TEST VALUES (2, TO_DATE('16-04-2015 16:35:19','DD-MM-YYYY HH24:MI:SS'));
COMMIT;
DROP DATABASE LINK TO_B;
CREATE DATABASE LINK TO_B
CONNECT TO B_USER IDENTIFIED BY B_PASSWORD
USING '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=10.10.15.10)(PORT=1521))
(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)))';
UPDATE TEST SET B = SYSDATE WHERE A = 2;
-- 此時 Session 持有該行的 TX 鎖
SHOW PARAMETER DISTRIBUTED_LOCK_TIMEOUT;
-- 預設 60 秒
UPDATE TEST@TO_B SET B = SYSDATE WHERE A = 2;
-- 等待 60 秒後報錯:
-- ORA-02049: timeout: distributed transaction waiting for lock
-- ORA-02063: preceding line from TO_B
DISTRIBUTED_LOCK_TIMEOUT 內釋放鎖,否則本地協調者強制回滾並拋出 ORA-02049。COMMIT。ALTER SYSTEM SET DISTRIBUTED_LOCK_TIMEOUT=180 SCOPE=SPFILE; -- 需重啟實例
-- 僅作為緩兵之計,掩蓋不了效能問題
-- 檢視當前分散式交易等待情況
SELECT * FROM V$DISTRIBUTED_TRANSACTION;
-- 檢視等待鎖的 Session
SELECT s.SID, s.SERIAL#, s.USERNAME, s.MACHINE, l.TYPE, l.LMODE, l.REQUEST
FROM V$SESSION s, V$LOCK l
WHERE s.SID = l.SID AND l.REQUEST > 0 AND l.TYPE = 'TX';
核心結論:ORA-02049 本質是遠端鎖持有時間過長導致協調者超時。治本之道在於優化遠端 SQL 效能與縮短事務邊界,而非單純調大參數。