안녕하세요.
오라클은 데이터 일관성을 위해 트랜잭션과 로우락을 구현하는 것으로 알고 있습니다.
만약 1억row가 들어있는 테이블 전체를 update 하면 rowlock이 1억row 전부 걸릴 것 입니다.
조금 극단적인 예지만 테이블이 인덱스를 타면서 update를 수행해서 12,3,.....1억 순서로 update 수행이 된다고
가정하면, 약 70만row까지 update가 진행하였을때, 다른 세션에서 100만번째 행에 update, commit 수행이 가능할까요?
정리하면
=> 대량 row update 처리시, 해당 행 전부 rowlock을 걸고, 실제 update를 수행하는지
=> 아니면, rowlock을 걸고 update 수행을 하고를 행마다 계속하여 반복하는지
궁금합니다. 이거 테스트를 어떻게 해야 할지 감이 안와서 질문하네요 ㅠㅠ
전체 테이블 update한 직후 100만번째 행을 update를 하면 update는 가능합니다만..
(100만번째 행 update문 commit 전까지 전체테이블 update문은 lock)
전체 테이블 update 쿼리가 완료되는 시점는 최종적으로 전체 update문 결과로 인해
100만번째 행 update문은 무효화 될겁니다.
lock은 실제 데이터 변경 후에 걸리는 것 같아요.
모든 오라클 서버 lock 기준이 동일한지는 잘 모르겠네요.
테스트 한번 해보시죠^^
1. 테이블 생성 create table tmp_20161101 as select '1' id from dual connect by level < 1000000 2.부분 update 할 행 rowid 획득 select rowid rid from tmp_20161101 3.전체 update 실행 update tmp_20161101 set id = '2' 4.전체 update문 완료전 부분 update 실행 update tmp_20161101 set id = '4' where rowid = 'AABVLzAA7AAON/9ACn' commit; 5.전체 update 문 commit; 6.최종 결과 확인 select * from tmp_20161101 where rowid = 'AABVLzAA7AAON/9ACn' -- 저는 '2'가 나오네요.
100만건 update 하는 동안 100만건 lock을 걸어주시려면 select for update 하시면 됩니다.
이 경우 100만번째 행 udpate문은 100만건 update commit 전까지 lock 상태일 것이고
100만 건 update commit 직후 수행되게 되어 결과 값은 최종적으로 '4'가 되겠네요.