TEMP_TABLE 의 값이 여러개라 가정했을때 --SESSION.1 에서 실행 SELECT TEMP1 FROM TEMP_TABLE WHERE ROWNUM=1 FOR UPDATE SKIP LOCKED; (커밋 혹은 롤백 하지 않음) --SESSION.2 에서 실행 SELECT TEMP1 FROM TEMP_TABLE WHERE ROWNUM=1 FOR UPDATE SKIP LOCKED;
게 실행하면
SESSION.1 에서는 값을 하나 출력하나
SESSION.2 에서는 어떤 값도 출력하지 않게 됩니다.
스킵락은 세션.1 에서 커밋 혹은 롤백 하지 않았을때 2에서는 1에서 락걸린 값을 제외한 나머지 값을 찾는걸로
알고 있는데 무슨 문제가 있는걸까요? 참고로 오라클은 11.0 이상 버전입니다.
아니면 위와 같은 상황에서 session1 에서 락이걸린것 제외하고 다른 값을 가져오는 방법은 무엇이 있을까요?
문의 드립니다. 좋은 하루 되세요~
아 넴 감사합니다.
간략하게 구현해야 하는걸 말씀드리자면요 ^^
temp_table 이라는 테이블에 temp_no, status 가 있을시에
temp_no status
------------------------
1 00
2 00
3 00
4 99
.
.
이런식으로 데이타가 만건이 있다고 쳤을때
select temp_no from temp_table
where status='00'
and rownum=1 으로 상태가 00인 로우중 하나의 값을 잡아서 99로 업데이트 치는 작업을 해야합니다,
그런데 여기저기서 위와 같은 작업을 해야해서. 동시성에 문제가 있을까 하여
select temp_no from temp_table
where status='00'
and rownum=1
for update;
를 하였눈데 한쪽세션에서 커밋을 안하면 다른쪽 세션에서 동일한 쿼리를 실행했을떼 락이 걸리더라구요
그래서 wait 3 등으로 락을 벗어나는 일을 해결했는데 궁극적으로는
하나의 세션에서 하나를 잡고 있다면 커밋 혹은 롤백 전에 다른 세션에서 다른걸 잡아서 처리할수 있도록
하려는 거여요 ㅎㅎ 구래서 skip locked 라는 옵션을 사용해보았으나 되질않아서요 ㅡㅡ
관심가져주셔서 감사합니다. 좋은 하루 되셔요
--테스트 --테이블 생성 CREATE TABLE TMP_20200130 ( COL1 VARCHAR2(10) , COL2 VARCHAR2(10) , COL3 VARCHAR2(10) ); --데이터 입력 INSERT INTO TMP_20200130 VALUES('A','B','C'); INSERT INTO TMP_20200130 VALUES('D','E','F'); --세션1에서 수행 DECLARE CURSOR CUR IS SELECT ROWID RID, A.* FROM TMP_20200130 A FOR UPDATE SKIP LOCKED; TYPE TMPTBL IS TABLE OF CUR%ROWTYPE; TMPCUR TMPTBL; BEGIN OPEN CUR; FETCH CUR BULK COLLECT INTO TMPCUR LIMIT 1; CLOSE CUR; UPDATE TMP_20200130 SET COL1 = '99' WHERE ROWID = TMPCUR(1).RID; --COMMIT; --COMMIT하지 않아본다. END; SELECT * FROM TMP_20200130 --결과 99 E F A B C --세션2에서 수행 DECLARE CURSOR CUR IS SELECT ROWID RID, A.* FROM TMP_20200130 A FOR UPDATE SKIP LOCKED; TYPE TMPTBL IS TABLE OF CUR%ROWTYPE; TMPCUR TMPTBL; BEGIN OPEN CUR; FETCH CUR BULK COLLECT INTO TMPCUR LIMIT 1; CLOSE CUR; UPDATE TMP_20200130 SET COL1 = '99' WHERE ROWID = TMPCUR(1).RID; --COMMIT; --COMMIT하지 않아본다. END; SELECT * FROM TMP_20200130 --결과 D E F 99 B C ----------------------------------------------- 잘 작동합니다. 처음에 제가 설명드린 PIPELINED 함수는 SELECT 만 처리하시려는 줄 알고 말씀드린 건데 목적이 UPDATE라면 위 내용을 프로시저로 만드시고 수행하셔야겠습니다.
어제 퇴근하면서 저도 원쿼리로 되지 않을까 했는데..
어차피 FOR UPDATE문 자체가 쿼리 결과에 대한 LOCK이기 때문에 안 될 것 같더라구요ㅎㅎ