데이터베이스 연결 구조

  • 사용자는 WAS나 DB 접근 툴(sqldeveloper 등) 같은 클라이언트를 사용하여 데이터베이스 서버에 접근하여 연결을 요청하고 커넥션을 맺음
  • 이때, 데이터베이스 서버 내부에 세션이라는 것이 생성되어 해당 커넥션을 통한 모든 요청은 이 세션을 통해서 실행
  • 개발자가 클라이언트를 통해 SQL을 전달하면 현재 커넥션에 연결된 세션이 SQL을 실행
  • 세션은 트랜잭션을 시작하고 커밋/롤백을 통해 트랜잭션 종료
  • 사용자가 커넥션을 닫거나 DBA가 세션을 강제로 종료하면 세션은 종료됨
  • 커넥션 풀이 10개의 커넥션을 생성하면, 세션도 10개 생성

자동 커밋과 수동 커밋

  • set autocommit true : 자동 커밋 모드 설정
    • SQL 실행 이후 commit을 호출하지 않아도 자동으로 커밋됨
    • commit을 호출하지 않는다고 하여 트랜잭션이 실행되지 않는 것이 아니라, 자동으로 commit을 호출함으로써 SQL 실행마다 트랜잭션이 시작되고 종료되는 것
  • set autocommit false : 수동 커밋 모드 설정
    • 보통 자동 커밋 모드가 기본을 설정된 경우가 많아, 수동 커밋 모드로 설정하는 것을 트랜잭션을 시작한다고 표현할 수 있음
    • 수동 커밋 설정을 하면 반드시 commit 또는 rollback을 호출해야 함

DB 락

  • 한 세션의 트랜잭션이 실행되는 동안 다른 세션의 트랜잭션이 현재 실행 중인 트랜잭션의 데이터에 접근하지 못하도록 하는 것

    • 공유 락(Shared Lock) : 여러 트랜잭션이 동시에 같은 데이터를 SELECT 가능하지만, UPDATE는 불가
    • 배타 락(Exclusive Lock) : 한 트랜잭션만 접근 가능, 다른 트랜잭션은 SELECT, UPDATE 모두 불가
  • 세션 1이 트랜잭션을 시작하고 데이터를 수정하는 동안, 아직 커밋을 수행하지 않았는데 세션 2가 같은 데이터를 수정하게 되면 트랜잭션의 원자성이 깨지는 문제가 발생

  • 이를 방지하기 위해 '락'을 사용

1. 데이터 동시 접근

  • 세션 1, 2 모두 memberA의 금액을 변경하려는 상황
  • 동시에 같은 데이터에 접근함으로써 발생하는 문제를 방지하기 위해 '락' 사용

2. 세션1 트랜잭션 시작 및 SQL 실행

  • 세션1이 세션2보다 조금 더 빨리 요청했다고 가정하면 세션1이 memberA 로우의 락을 획득
  • 접근하려는 로우의 락을 갖고 있어야 해당 로우를 수정 가능
  • 세션1이 트랜잭션을 시작하여 해당 로우에 update sql 실행

3. 세션2 트랜잭션 시작

  • 세션2가 트랜잭션을 시작하여 memberA의 money를 변경하려 시도
  • 해당 로우의 락은 이미 세션1이 갖고 있으므로 락이 반환될 때 까지 대기
    • 락 대기 시간을 넘어가면 락 타임아웃 오류 발생

4. 세션1 락 반환

  • 세션1이 커밋을 수행함에 따라 트랜잭션이 종료되었으므로 락 반환

5. 세션2 락 획득

  • 세션1의 트랜잭션 종료로 인해 반환된 락을 세션2가 획득

6. 세션2 SQL 실행

  • 세션2는 락을 갖고 있으므로 memberA 로우에 접근하여 SQL 실행

7. 세션2 트랜잭션 종료

  • 세션2는 커밋을 수행하고 트랜잭션이 종료되었으므로 락을 반납

+ Recent posts