SQL> drop table t;
Table dropped.
SQL>
SQL>
SQL> create table t
2 ( processed_flag varchar2(1)
3 );
Table created.
SQL> create bitmap index t_idx on t(processed_flag);
Index created.
SQL> insert into t values ( 'N' );
1 row created.
SQL> declare
2 pragma autonomous_transaction;
3 begin
4 insert into t values ( 'N' );
5 commit;
6 end;
7 /
declare
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
ORA-06512: at line 4
-- 한 번에 한 세션만 사용 가능(10g)
SELECT * FROM QUEUE_TABLE WHERE DECODE(PROCESSED_FLAG, 'N', 'N') = 'N' FOR UPDATE;
SQL> drop table t purge;
Table dropped.
SQL> create table t
2 ( id number primary key,
3 processed_flag varchar2(1),
4 payload varchar2(20)
5 );
Table created.
SQL> create index
2 t_idx on
3 t( decode( processed_flag, 'N', 'N' ) );
Index created.
SQL> insert into t
2 select r,
3 case when mod(r,2) = 0 then 'N' else 'Y' end,
4 'payload ' || r
5 from (select level r
6 from dual
7 connect by level <= 5)
8 /
5 rows created.
SQL> select * from t;
ID P PAYLOAD
---------- - --------------------
1 Y payload 1
2 N payload 2
3 Y payload 3
4 N payload 4
5 Y payload 5
-- 해결책 타입1
SQL> create or replace
2 function get_first_unlocked_row
3 return t%rowtype
4 as
5 resource_busy exception;
6 pragma exception_init( resource_busy, -54 );
7 l_rec t%rowtype;
8 begin
9 for x in ( select rowid rid
10 from t
11 where decode(processed_flag,'N','N') = 'N')
12 loop
13 begin
14 select * into l_rec
15 from t
16 where rowid = x.rid and processed_flag='N'
17 for update nowait;
18 return l_rec;
19 exception
20 when resource_busy then null;
21 end;
22 end loop;
23 return null;
24 end;
25 /
Function created.
SQL> set serveroutput on
declare
l_rec t%rowtype;
begin
l_rec := get_first_unlocked_row;
dbms_output.put_line( 'I got row ' || l_rec.id || ', ' || l_rec.payload );
end;
/SQL> 2 3 4 5 6 7
I got row 2, payload 2
PL/SQL procedure successfully completed.
SQL> declare
2 pragma autonomous_transaction;
3 l_rec t%rowtype;
4 begin
5 l_rec := get_first_unlocked_row;
6 dbms_output.put_line( 'I got row ' || l_rec.id || ', ' || l_rec.payload );
7 commit;
8 end;
9 /
I got row 4, payload 4
PL/SQL procedure successfully completed.
-- 해결책 타입2 : SKIP LOCKED (11g)
SQL> declare
2 l_rec t%rowtype;
3 cursor c
4 is
5 select *
6 from t
7 where decode(processed_flag,'N','N') = 'N'
8 FOR UPDATE
9 SKIP LOCKED;
10 begin
11 open c;
12 fetch c into l_rec;
13 if ( c%found )
14 then
15 dbms_output.put_line( 'I got row ' || l_rec.id || ', ' || l_rec.payload );
16 end if;
17 close c;
18 end;
19 /
I got row 2, payload 2
PL/SQL procedure successfully completed.
SQL> declare
2 pragma autonomous_transaction;
3 l_rec t%rowtype;
4 cursor c
5 is
6 select *
7 from t
8 where decode(processed_flag,'N','N') = 'N'
9 FOR UPDATE
10 SKIP LOCKED;
11 begin
12 open c;
13 fetch c into l_rec;
14 if ( c%found )
15 then
16 dbms_output.put_line( 'I got row ' || l_rec.id || ', ' || l_rec.payload );
17 end if;
18 close c;
19 commit;
20 end;
21 /
I got row 4, payload 4
PL/SQL procedure successfully completed.
- 강좌 URL : http://www.gurubee.net/lecture/3990
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.