ORA-00051 timeout occurred while waiting for a resource λ?
ORA-00051μ Oracle λ°μ΄ν°λ² μ΄μ€μμ νΉμ 리μμ€λ₯Ό κΈ°λ€λ¦¬λ λμ μ€μ λ νμμμ μκ°μ΄ μ΄κ³Όλμμ λ λ°μνλ μλ¬μ λλ€. μ£Όλ‘ λΆμ° νΈλμμ (Distributed Transaction) νκ²½μμ μ격 λ°μ΄ν°λ² μ΄μ€μμ ν΅μ μ€ λ½(Lock) λλ 리μμ€λ₯Ό νλνμ§ λͺ»ν μ± λκΈ° μκ°μ΄ λμ΄κ° λ λ°μν©λλ€. λ¨μΌ μΈμ€ν΄μ€ ν경보λ€λ DB Linkλ₯Ό ν΅ν μ격 쿼리λ RAC(Real Application Clusters) νκ²½μμ λ λΉλ²νκ² λνλλ©°, νΈλμμ λ‘€λ°±μ΄λ μΈμ μ’ λ£λ‘ μ΄μ΄μ§ μ μμ΄ μ΄μ μ€ μ¦κ°μ μΈ μ‘°μΉκ° νμν©λλ€.
μ£Όμ λ°μ μμΈ
1. λΆμ° νΈλμμ μμμ λ½ λκΈ° νμμμ (DISTRIBUTED_LOCK_TIMEOUT)
Oracleμ DISTRIBUTED_LOCK_TIMEOUT νλΌλ―Έν°λ λΆμ° νΈλμμ
νκ²½μμ λ½μ κΈ°λ€λ¦¬λ μ΅λ μκ°μ μ΄(seconds) λ¨μλ‘ μ μν©λλ€. κΈ°λ³Έκ°μ 60μ΄μ΄λ©°, DB Linkλ₯Ό ν΅ν΄ μ격 ν
μ΄λΈμ DML(INSERT, UPDATE, DELETE)μ μνν λ μ격 μΈμ
μ΄ λ½μ 보μ ν μ± μλ΅νμ§ μμΌλ©΄ μ΄ νλΌλ―Έν°μ κ°μ μ΄κ³Όνμ¬ ORA-00051μ΄ λ°μν©λλ€. νΉν λ°°μΉ μμ
μ΄λ λμ©λ νΈλμμ
μ΄ μ격 DBμμ μ€λ μ€ν μ€μΌ λ μμ£Ό λͺ©κ²©λ©λλ€.
2. λ€νΈμν¬ λΆμμ λλ μ격 DB μλ΅ μ§μ°
DB Linkλ‘ μ°κ²°λ μ격 Oracle μΈμ€ν΄μ€κ° λ€νΈμν¬ λ¨μ , κ³ΌλΆν, λλ μ₯μ μνμΌ κ²½μ° λ‘컬 μΈμ μ 리μμ€ μλ΅μ κΈ°λ€λ¦¬λ€ νμμμλ©λλ€. TCP μμ€μμ ν¨ν· μμ€μ΄ λ°μνκ±°λ λ°©νλ²½ μΈμ λ§λ£(Firewall Session Timeout)λ‘ μΈν΄ μ°κ²°μ΄ λκ²Όμμλ Oracleμ΄ μ΄λ₯Ό μΈμ§νμ§ λͺ»νκ³ λκΈ°νλ κ²½μ°μλ λ³Έ μλ¬κ° νΈλ¦¬κ±°λ©λλ€. μ΄λ° μν©μ μΌκ° λ°°μΉ μλμ°λ μΈνλΌ μ μ§λ³΄μ μκ°λμ νΉν λ§μ΄ λ°μν©λλ€.
3. RAC νκ²½μμμ κΈλ‘λ² λ¦¬μμ€ κ²½ν© (GCS/GES μ§μ°)
Oracle RAC νκ²½μμλ GCS(Global Cache Service)μ GES(Global Enqueue Service)λ₯Ό ν΅ν΄ μΈμ€ν΄μ€ κ° λ¦¬μμ€λ₯Ό 곡μ ν©λλ€. νΉμ μΈμ€ν΄μ€κ° λΈλ‘ μ μ‘μ΄λ μΈν(Enqueue) νλμ κ³Όλν μκ°μ΄ μμλ κ²½μ° λ΄λΆ νμμμμ΄ λ°μνκ³ ORA-00051λ‘ μ΄μ΄μ§ μ μμ΅λλ€. μΈν°μ»€λ₯νΈ λ€νΈμν¬μ λ μ΄ν΄μκ° λκ±°λ νΉμ λ Έλμ κ³ΌλΆνκ° μ§μ€λ λ μ΄ λ¬Έμ κ° μ¬νλ©λλ€.
ν΄κ²° λ°©λ²
μμΈ 1: DISTRIBUTED_LOCK_TIMEOUT κ° μ‘°μ
νμ¬ μ€μ κ°μ νμΈνκ³ , μ
무 μ건μ λ§κ² κ°μ μ‘°μ ν©λλ€. λ¨, κ°μ 무μμ λ리면 λ½ κ²½ν©μ΄ κΈΈμ΄μ§ μ μμΌλ―λ‘ κ·Όλ³Έ μμΈ νμ
μ΄ μ°μ μ
λλ€.
-- νμ¬ DISTRIBUTED_LOCK_TIMEOUT νλΌλ―Έν° νμΈ
SELECT name, value, description
FROM v$parameter
WHERE name = 'distributed_lock_timeout';
-- λμ μΌλ‘ λ³κ²½ (ALTER SYSTEM)
-- κΈ°λ³Έκ° 60μ΄ β νμμ λ°λΌ μ‘°μ (μ: 120μ΄)
ALTER SYSTEM SET distributed_lock_timeout = 120 SCOPE = BOTH;
-- λ³κ²½ ν νμΈ
SHOW PARAMETER distributed_lock_timeout;
νμ¬ λΆμ° νΈλμμ
λκΈ° μΈμ
μ νμ
νμ¬ μμΈ μΈμ
μ μλ³ν©λλ€.
-- λΆμ° νΈλμμ
λκΈ° μΈμ
νμΈ
SELECT s.sid,
s.serial#,
s.username,
s.status,
s.wait_class,
s.event,
s.seconds_in_wait,
s.sql_id,
s.program,
s.machine
FROM v$session s
WHERE s.wait_class != 'Idle'
AND s.event LIKE '%distributed%'
ORDER BY s.seconds_in_wait DESC;
-- νμ¬ λΆμ° νΈλμμ
λͺ©λ‘ νμΈ
SELECT local_tran_id,
global_tran_id,
state,
mixed,
advice,
tran_comment,
fail_time,
force_time,
retry_time,
os_user,
os_oid,
db_user,
interface
FROM dba_2pc_pending;
In-doubt μνλ‘ λ¨κ²¨μ§ λΆμ° νΈλμμ
μ κ°μ λ‘ μ²λ¦¬ν©λλ€.
-- In-doubt νΈλμμ
κ°μ μ»€λ° (μ격 DBμ νμ ν μν)
COMMIT FORCE 'local_tran_id_κ°';
-- λλ κ°μ λ‘€λ°±
ROLLBACK FORCE 'local_tran_id_κ°';
-- μμ
COMMIT FORCE '1.23.456';
ROLLBACK FORCE '1.23.456';
μμΈ 2: λ€νΈμν¬ κ΄λ ¨ λ½ λκΈ° μΈμ κ°μ μ’ λ£
μλ΅νμ§ μλ μΈμ
μ μλ³νκ³ μ’
λ£ν©λλ€.
-- μ₯μκ° λκΈ° μ€μΈ μΈμ
μ‘°ν (300μ΄ μ΄μ)
SELECT s.sid,
s.serial#,
s.username,
s.status,
s.event,
s.seconds_in_wait,
s.blocking_session,
s.sql_id,
q.sql_text
FROM v$session s
LEFT JOIN v$sql q ON s.sql_id = q.sql_id
WHERE s.seconds_in_wait > 300
AND s.status = 'ACTIVE'
ORDER BY s.seconds_in_wait DESC;
-- λΈλ‘νΉ μΈμ
μ²΄μΈ νμ
SELECT blocker.sid AS blocker_sid,
blocker.serial# AS blocker_serial,
blocker.username AS blocker_user,
blocker.program AS blocker_program,
waiter.sid AS waiter_sid,
waiter.serial# AS waiter_serial,
waiter.username AS waiter_user,
waiter.event AS wait_event,
waiter.seconds_in_wait
FROM v$session blocker
JOIN v$session waiter ON waiter.blocking_session = blocker.sid
WHERE waiter.blocking_session IS NOT NULL;
-- λ¬Έμ μΈμ
κ°μ μ’
λ£
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;
-- μμ
ALTER SYSTEM KILL SESSION '145,2038' IMMEDIATE;
DB Link μ°κ²° μνλ₯Ό μ κ²ν©λλ€.
-- νμ¬ DB Link λͺ©λ‘ μ‘°ν
SELECT db_link, username, host, created
FROM dba_db_links
ORDER BY db_link;
-- νΉμ DB Link μ°κ²° ν
μ€νΈ (κ°λ¨ν μ격 쿼리)
SELECT 1 FROM dual@your_db_link_name;
-- νμ±νλ DB Link μΈμ
νμΈ
SELECT s.sid,
s.serial#,
s.username,
s.program,
s.status,
s.event,
s.seconds_in_wait
FROM v$session s
WHERE s.program LIKE '%dbnewid%'
OR s.event LIKE '%db link%'
OR s.username IN (
SELECT username FROM dba_db_links
);
μμΈ 3: RAC νκ²½ κΈλ‘λ² λ¦¬μμ€ κ²½ν© μ§λ¨
-- RAC μΈν°μ»€λ₯νΈ λκΈ° μ΄λ²€νΈ νμΈ
SELECT inst_id,
event,
total_waits,
total_timeouts,
time_waited,
average_wait,
max_wait
FROM gv$system_event
WHERE event IN (
'gc buffer busy acquire',
'gc buffer busy release',
'gc cr request',
'gc current request',
'global enqueue wait'
)
ORDER BY inst_id, time_waited DESC;
-- μΈμ€ν΄μ€ κ° λΈλ‘νΉ νν© μ‘°ν
SELECT g1.inst_id AS blocker_inst,
g1.sid AS blocker_sid,
g2.inst_id AS waiter_inst,
g2.sid AS waiter_sid,
g2.event AS wait_event,
g2.seconds_in_wait
FROM gv$session g1
JOIN gv$session g2
ON g2.blocking_instance = g1.inst_id
AND g2.blocking_session = g1.sid
WHERE g2.blocking_session IS NOT NULL
ORDER BY g2.seconds_in_wait DESC;
-- GES(Global Enqueue Service) λ½ νν©
SELECT inst_id,
type,
id1,
id2,
lmode,
request,
block
FROM gv$lock
WHERE block = 1
ORDER BY inst_id;
μλ°© λ°©λ²
1. SQLNET λ° DB Link Dead Connection κ°μ§ μ€μ κ°ν
λ€νΈμν¬ λ¨μ μ΄ λ°μν΄λ Oracleμ΄ μ΄λ₯Ό μ μνκ² κ°μ§νλλ‘ sqlnet.oraμ Dead Connection Detection(DCD) νλΌλ―Έν°λ₯Ό μ€μ ν©λλ€. μ΄ μ€μ μ λ°©μΉλ λΆμ° νΈλμμ
μΈμ
μ μλμΌλ‘ μ 리νμ¬ νμμμ μλ¬ λ°μμ μ€μ¬μ€λλ€.
-- sqlnet.ora μ€μ μμ (DB μλ² μΈ‘ $ORACLE_HOME/network/admin/sqlnet.ora)
-- SQLNET.EXPIRE_TIME = 10 (10λΆλ§λ€ μ°κ²° μμ‘΄ μ¬λΆ νμΈ)
-- Oracle νλΌλ―Έν° μμ€μμ λΆμ° νΈλμμ
μλ 볡ꡬ μ€μ
SELECT name, value
FROM v$parameter
WHERE name IN (
'distributed_lock_timeout',
'commit_point_strength',
'open_links',
'open_links_per_instance'
);
-- DB Link μ΅λ μ€ν μ μ μ μμ€ μ μ§ (κΈ°λ³Έκ° 4, μ΅λ 255)
ALTER SYSTEM SET open_links = 10 SCOPE = SPFILE;
ALTER SYSTEM SET open_links_per_instance = 10 SCOPE = SPFILE;
2. μ κΈ°μ μΈ In-doubt νΈλμμ λͺ¨λν°λ§ λ° μλ¦Ό μ²΄κ³ κ΅¬μΆ
DBA_2PC_PENDING λ·°λ₯Ό μ£ΌκΈ°μ μΌλ‘ μ‘°ννμ¬ μ²λ¦¬λμ§ λͺ»ν λΆμ° νΈλμμ
μ λΉ λ₯΄κ² κ°μ§νκ³ μ‘°μΉν©λλ€. μ΄μ νκ²½μμλ μλ 쿼리λ₯Ό Cronμ΄λ Oracle Scheduler JobμΌλ‘ λ±λ‘νμ¬ In-doubt νΈλμμ
λ°μ μ λ΄λΉμμκ² μλ¦Όμ΄ κ°λλ‘ μλννλ κ²μ κΆμ₯ν©λλ€.
-- In-doubt νΈλμμ
λͺ¨λν°λ§ 쿼리 (Scheduler Job λλ λͺ¨λν°λ§ ν΄μ λ±λ‘)
SELECT COUNT(*) AS indoubt_count,
MIN(fail_time) AS oldest_fail_time,
MAX(fail_time) AS latest_fail_time
FROM dba_2pc_pending
WHERE state IN ('prepared', 'collecting', 'committed', 'rolled back');
-- μμΈ λ΄μ μλ¦Όμ© μΏΌλ¦¬
SELECT local_tran_id,
global_tran_id,
state,
fail_time,
db_user,
os_user,
ROUND((SYSDATE - fail_time) * 24 * 60, 2) AS elapsed_minutes
FROM dba_2pc_pending
WHERE fail_time < SYSDATE - (1/24) -- 1μκ° μ΄μ μ§λ λ―Έμ²λ¦¬ νΈλμμ
ORDER BY fail_time;
-- Oracle Schedulerλ₯Ό μ΄μ©ν μλ μ κ² Job λ±λ‘ μμ
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'CHECK_INDOUBT_TRANS',
job_type => 'PLSQL_BLOCK',
job_action => '
DECLARE
v_cnt NUMBER;
BEGIN
SELECT COUNT(*) INTO v_cnt FROM dba_2pc_pending;
IF v_cnt > 0 THEN
-- μλ¦Ό λ‘μ§ (DBMS_ALERT λλ UTL_MAIL νμ©)
DBMS_OUTPUT.PUT_LINE(''In-doubt transactions found: '' || v_cnt);
END IF;
END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=MINUTELY;INTERVAL=30',
enabled => TRUE,
comments => 'Monitor in-doubt distributed transactions'
);
END;
/
κ΄λ ¨ μλ¬
-
ORA-00060:
deadlock detected while waiting for resourceβ λ μΈμ μ΄ μλ‘μ 리μμ€λ₯Ό κΈ°λ€λ¦¬λ©° λ°μνλ λ°λλ½μΌλ‘, ORA-00051κ³Ό λ¬λ¦¬ Oracleμ΄ μλμΌλ‘ ν μΈμ μ λ‘€λ°±νμ¬ ν΄μν©λλ€. -
ORA-02049:
timeout: distributed transaction waiting for lockβ λΆμ° νΈλμμ νκ²½μμDISTRIBUTED_LOCK_TIMEOUTμ΄κ³Ό μ λ°μνλ©°, ORA-00051κ³Ό ν¨κ» λνλλ κ²½μ°κ° λ§μ΅λλ€. -
ORA-01013:
user requested cancel of current operationβ νμμμ μ€μ μ μν΄ μΏΌλ¦¬κ° κ°μ μ·¨μλ λ λ°μνλ©°,STATEMENT_TIMEOUTλλ OCI ν΄λΌμ΄μΈνΈ νμμμκ³Ό μ°κ΄λ©λλ€. -
ORA-03113:
end-of-file on communication channelβ λ€νΈμν¬ λ¨μ λ‘ μ격 μ°κ²°μ΄ λκ²Όμ λ λνλλ©°, ORA-00051 λ°μ μ΄ν νμμΌλ‘ κΈ°λ‘λλ κ²½μ°κ° μμ΅λλ€. -
ORA-04021:
timeout occurred while waiting to lock objectβ DDL μμ μ€ μ€λΈμ νΈ λ½ νλ λκΈ° νμμμμΌλ‘, 리μμ€ λκΈ° νμμμμ΄λΌλ λ§₯λ½μμ ORA-00051κ³Ό μ μ¬ν μ±κ²©μ κ°μ§λλ€.












