김영한님의 자바 ORM 표준 JPA 프로그래밍 책에서, 트랜잭션을 지원하는 쓰기 지연 부분이 이해가 안되어서 공부한 내용이다.
혹시 제목이 너무 당연하게 느껴진다면, 전혀 읽을 필요가 없는 포스팅임을 미리 밝힌다.
책 몇판 몇쇄인지에 따라 페이지가 다를 수 있겠지만, 내 책 기준 690P 트랜잭션을 지원하는 쓰기 지연과 애플리케이션 확장성 파트를 읽는데 이해가 잘 안되었다. 결론 부터 말하자면, 이해가 안된 이유는 나의 DBMS 시스템에 대한 이해 부족때문이었다.
우선, 다음과 같은 책의 설명을 보자.
트랜잭션을 지원하는 쓰기 지연과 애플리케이션 확장성
책의 내용을 간추렸습니다.
JPA 의 트랜잭션을 지원하는 쓰기 지연과 변경 감지 기능의 진짜 장점은 데이터베이스 테이블 로우에 락이 걸리는 시간을 최소화 한다는 점이다.
이 기능은 트랜잭션을 커밋해서 영속성 컨텍스트를 플러시하기 전까지는 데이터베이스에 데이터를 등록, 수정, 삭제하지 않는다. 따라서 커밋 직전까지 데이터 베이스 로우에 락을 걸지 않는다. 다음 로직을 보자.
update(memberA); // Update SQL A
비지니스로직A();
비지니스로직B();
commit();
JPA 를 사용하지 않고 SQL을 직접 다루면 update(memberA) 를 호출할 때 UPDATE SQL 을 실행하면서 데이터베이스 테이블 로우에 락을 건다. 이 락은 비지니스로직A(), 비지니스로직 B()를 모두 수행하고 commit() 을 호출할 때까지 유지 된다.
이에 비해 JPA는 커밋을 하는 순간에 플러시를 호출하여 그제서야 수정쿼리를 한번에 보낸다. 즉, commit() 을 호출할 때 UPDATE SQL을 실행하고 바로 데이터베이스 트랜잭션을 커밋하는 것이다. 쿼리를 보내고 바로 트랜잭션을 커밋하므로 결과적으로 데이터 베이스 락이 걸리는 시간을 최소화한다.
처음에는 술술 잘 만 읽혔다
JPA 를 활용하면 쓰기 지연 덕분에 락을 잡는 시간이 최소화 되는구나. 그런데, 데이터베이스 테이블 로우에 락을 건다는 부분이 잘 이해가 가지 않기 시작했다. UPDATE SQL을 실행하면 데이터베이스 테이블 로우에 락이 걸린다고?
UPDATE SQL 을 실행하면 데이터베이스 테이블 로우에 락이 걸린다.
즉, 한 트랜잭션이 어떠한 row 를 업데이트 하고 있고, 아직 커밋이 되지 않았다면 다른 트랜잭션에서는 해당 데이터를 수정할 수 없다. 사실 이는 데이터의 정합성과 일관성을 위한 DBMS 의 당연한 조치이다. 이러한 오해는 명시락과(for update, for share) 낙관락 외에도 DBMS 도 알아서 락을 거는 메커니즘에 대한 이해 부족에서 비롯되었다.
즉 다시말해, UPDATE SQL을 실행하면 DBMS 에서 해당 로우에 락을 건다는 것이다.
사실 책에서 'UPDATE SQL을 실행하면 데이터베이스 테이블 로우에 락을 건다' 라고만 나와 있어 헷갈렸던 것 같다. 주체가 나와있지 않기 때문이다. 나는 락을 비관락, 낙관락 정도로만 이해하고 있었기 때문에 당연히 주체가 어플리케이션, 개발자가 작성하는 쿼리라고 생각했던 것이다. 사실 이것도 비겁한 변명인게, 그렇게 락을 건다는 것이 결국 DBMS 에게 해당 로우에 락을 걸라고 명령하는 것이기 때문이다. ㅎ.ㅎ
어쨌든, 그렇게 걸린 lock 에 대한 다른 트랜잭션의 접근은 데이터베이스 격리 수준에 따라 다르게 처리 될 것이다.
'JPA' 카테고리의 다른 글
웹 애플리케이션과 영속성 관리 (0) | 2023.10.03 |
---|