====== Oracle Table Lock 처리방법 ====== * ORA-00054 (resource busy and acquire with NOWAIT specified) 에러는 commit/rollback을 처리를 안했거나, 특정작업을 하고 있었거나 그 이유는 매우 다양하다. * DB를 재시작할 수 없는 상태에서는 Lock이 걸린 세션을 kill 해주어야 한다. ===== Table Lock kill mini-HOWTO ===== - lock 걸린 테이블 검색 select a.sid , a.serial# from v$session a , v$lock b , dba_objects c where a.sid = b.sid and b.id1 = c.object_id and b.type = 'TM' and c.object_name='TABLE_NAME'; SID SERIAL# ------- ---------- 1004 10001 - Lock 걸린 세션을 kill 시킨다. alter system kill session '1004,10001'; ===== Lock발생 사용자와 sql, object 조회 ===== select distinct x.session_id, a.serial#,d.object_name,a.machine,a.terminal,a.program,b.address,b.piece, b.sql_text from v$locked_object x, v$session a, v$sqltext b, dba_objects d where x.session_id = a.sid and x.object_id = d.object_id and a.sql_address = b.address --and a.terminal = '' order by b.address,b.piece; ===== Lock 발생 사용자확인 ===== select distinct x.session_id, a.serial#,d.object_name,a.machine,a.terminal,a.program, a.logon_time --select 'alter system kill session ''' || a.sid || ',' || a.serial# || ''';' from gv$locked_object x, gv$session a, dba_objects d where x.session_id = a.sid and x.object_id = d.object_id order by logon_time; ===== 현재 접속자의 sql 분석 ===== select distinct a.sid,a.serial#,a.machine,a.terminal,a.program,b.address,b.piece, b.sql_text from v$session a, v$sqltext b where a.sql_address = b.address order by a.sid, a.serial#,b.address,b.piece; ===== 접속 사용자 세션 제거 ===== --alter system kill session 'session_id,serial#'; alter system kill session '1004,10001'; ===== Lock waiting 세션의 SQL & TABLE & ROWID 구하기 ===== - howto 1 select a.sid, a.serial#, p.spid, a.status, b.sql_text, c.object_type , c.owner||'.'||c.object_name object, sys.dbms_rowid.rowid_create(1, -- rowid type : 0(restricted), 1(extended) a.row_wait_obj#, -- object_number a.row_wait_file#, -- releative file number a.row_wait_block#, -- block number a.row_wait_row#) row_id -- file number from v$session a, v$process p, v$open_cursor b, dba_objects c where a.sql_address = b.address and a.paddr = p.addr and a.row_wait_obj# = c.object_id and a.lockwait is not null SID SERIAL# SPID STATUS SQL_TEXT OBJECT_TYPE OBJECT ROW_ID --- --- ------ ------- ----------------------------------------------- -------- --------- ------------------ 10 19 4056 ACTIVE update emp set sal = '2000' where empno = :b1 TABLE SCOTT.EMP AAAHW7AABAAAMUiAAB 16 255 2816 ACTIVE delete emp where empno = 7499 TABLE SCOTT.EMP AAAHW7AABAAAMUiAAB 17 5 1356 ACTIVE update emp set job = 'CLERK' where empno = 7698 TABLE SCOTT.EMP AAAHW7AABAAAMUiAAF select * from emp rowid = 'AAAHW7AABAAAMUiAAB' - howto 2 select /*+ ordered */ a.sid, a.serial#, p.spid, a.status, l.type, decode(l.lmode, 0, 'wait', 'hold') stat, decode(l.lmode, 0, 'none', 1, 'null', 2, 'row share', 3, 'row excl.', 4, 'share', 5, 's/row excl.', 6, 'exclusive', ltrim(to_char(l.lmode, '990'))) lmode, decode(l.request, 0, 'none', 1, 'null', 2, 'row share', 3, 'row excl.', 4, 'share', 5, 's/row excl.', 6, 'exclusive', ltrim(to_char(l.request, '990'))) request, l.id1, l.id2, a.module, a.machine, decode(a.sql_address, '00', a.prev_sql_addr, a.sql_address) as sql_address, decode(a.sql_hash_value, '0', a.prev_hash_value, a.sql_hash_value) as hash_value, b.sql_text, c.object_type, c.owner || '.' || c.object_name object, decode(a.lockwait, null, 'n/a', sys.dbms_rowid.rowid_create(1, a.row_wait_obj#, a.row_wait_file#, a.row_wait_block#, a.row_wait_row#)) row_id from v$lock l, v$session a, v$process p, v$open_cursor b, dba_objects c where ((a.sid = l.sid and l.request <> 0) or (a.sid = l.sid and l.request = 0 and l.lmode <> 4 and (l.id1, l.id2) in (select s.id1, s.id2 from v$lock s where s.request <> 0 and s.id1 = l.id1 and s.id2 = l.id2))) and decode(a.sql_address, '00', a.prev_sql_addr, a.sql_address) = b.address and a.sid = b.sid and a.paddr = p.addr and a.row_wait_obj# = c.object_id(+) order by l.id1, l.id2, l.request; ===== LOCK을 HOLDING 하고 있는 세션의 SQL이 보이지 않을 경우 ===== select * from v$open_cursor where sid = 12 -- HOLDING세션