update set subquery 실행시점이 궁금합니다. 0 4 848

by 파카 [Oracle 기초] [2017.12.15 16:00:10]


UPDATE user_token ut
SET (
		ut.token,
		ut.last_login_dt
	) = (
		SELECT 
			CASE 
				WHEN last_login_dt < SYSDATE - 1 THEN token
				ELSE :new_token
			END token,
			CASE
			WHEN last_login_dt < SYSDATE - 1 THEN last_login_dt
			ELSE SYSDATE
			END last_login_dt
		FROM user_token
		WHERE
		AND user_id = :user_id
	)
WHERE user_id = :user_id

user_token 테이블에 user_id와 token은 각각 pk, uk이고,

대략 이런 쿼리가 있을때,

동일한 user_id로 같은 시점에 요청이 들어올 경우

로우락이 걸리고, token과 last_login_dt가 업데이트 될텐데요.

이후 대기중인 update 쿼리가 실행되면 token과 last_login_dt가 수정될까요?

서브쿼리의 실행시점이 락이 걸린이후에 실행되느냐,

아니면 락이 걸리기 전에 실행되어 캐싱되느냐 차이일것 같은데..

둘다 아닐수도 있겠지만, 어떻게 되는지 궁금합니다.

by 우리집아찌 [2017.12.15 16:08:28]

책은 봤는데 기억이.. ^^*

http://wiki.gurubee.net/pages/viewpage.action?pageId=29065308

​​​​​​​


by 마농 [2017.12.15 16:25:26]

문제가 많은 쿼리네요.
1. 동일 테이블을 두번 읽는 쿼리네요.
  - 한번만 읽으면 됩니다. 다시말하면 서브쿼리가 필요 없습니다.
2. 업데이트 하지 않아도 될 것을 업데이트 하면서 락을 거네요.
  - 조건을 case 가 아닌 where 절에서 줘야죠.
 

UPDATE user_token
   SET token = :new_token
     , last_login_dt = sysdate
 WHERE last_login_dt >= sysdate - 1
   AND user_id = :user_id
;

 


by 파카 [2017.12.15 17:18:59]

궁금한건 쿼리 최적화가 아니라 실행순서라서 궁금이 풀리진 않네요.^^;;

제시해주신 쿼리에서도 궁금한게 있는데요,

해당 쿼리가 동일한 user_id로 동시에 여러건 요청할 경우

로우락이 걸리고, 업데이트가 되고, 이후 대기중인 동일한 쿼리들이 실행 될텐데요,

첫 쿼리에서 last_login_dt가 업데이트 되었기 때문에 나머지 쿼리는 업데이트가 안되는게 맞나요?

락을 걸땐 where 조건 보고 체크하겠지만, 이후 업데이트할땐 where조건을 체크하는 궁금하네요.

꼭 이런 매커니즘이 아니더라도, 어떻게 되는지 궁금합니다.

처음 질문하게된 쿼리가 나오게 된게 저런 의문 때문이였거든요.


by 마농 [2017.12.15 17:35:01]

2번세션에서 락이 걸려 대기하다가
락이 풀리면 엡데이트가 재수행 됩니다.
대상 추출할 때는 읽기 일관성 모드로 읽고,
최종 업데이트 할 때는 현재 모드로 수행합니다.
즉, 대상 추출 시점과 갱신시점 사이에 뭔가가 발생했다면?
결과가 달라질 수 있습니다.

 

1. S1 : UPDATE SET b = 1 WHERE b = 0;  > 정상
2. S2 : UPDATE SET b = 2 WHERE b = 0;  > 대기(읽기 일관성 모드로 읽어 1건 나옴)
3. S1 : COMMIT;  > 정상
4. S2 : 0 ROW UPDATED  (현재 모드로 재 수행되어 0 건 나옴)
5. 최종 : b = 1

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입