개발 공부 기록하기/02. DB & SQL

내맘대로 정리하는 Real MySQL #4장) 트랜잭션과 잠금 - 트랜잭션 편

lannstark 2020. 8. 16. 11:37

<내맘대로 정리하는> 시리즈는, 책을 읽으며 몰랐던 내용을 위주로 정리한 내용 그대로 포스팅하는 시리즈입니다 ^^

원문의 문맥이 궁금하면 (좋은 책이니) 이 참에 하나 장만하는 것은 어떤가요??

트랜잭션이란

  • 작업의 완전성을 보장해주는 것
  • 논리적인 작업 모음을 모두 완벽하게 처리하거나 또는 처리하지 못할 경우 원 상태로 복구해서 작업의 일부만 적용되는 현상이 발생하지 않게 만들어주는 기능이다

MEMORY 스토리지 엔진 혹은 MyISAM 스토리지 엔진은 트랜잭션 기능이 없다.

트랜잭션 기능이 없다면 애플리케이션에서 일부의 쿼리만 실행된것에 대한 후처리를 정말 끔찍하게 해야하지만 트랜잭션을 활용하면 try - catch 로 깔끔하게 처리된다.

try {
    START TRANSACTION;
  INSERT INTO tab_a ...;
    INSERT INTO tab_b ...;
    COMMIT;
} catch (exception) {
    ROLLBACK;
}

트랜잭션 또한 DBMS의 커넥션과 동일하게 꼭 필요한 최소한의 코드에만 적용하는 것이 좋다. 프로그램의 코드가 DB connection을 가지고 있는 범위와 트랜잭션이 활성화돼 있는 프로그램의 범위를 최소화해야 한다는 것이다.

프로그램의 코드에서 라인 수는 한두 줄이라 하더라도 네트워크 작업이 있는 경우는 반드시 트랜잭션에서 배제해야 한다. 이런 실수로 인해 DBMS 서버가 높은 부하 상태로 빠지거나 위험한 상태에 빠지는 경우가 빈번히 나타나곤 한다.

트랜잭션 격리수준

동시에 여러 트랜잭션이 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지 결정하는 것

READ UNCOMMITED

이름 그대로 commit 되지 않은 레코드를 읽을 수 있게 하는 것이다.

때문에 어떤 트랜잭션에서 처리한 작업이 완료되지 않았는데 다른 트랜잭션에서 볼 수 있는 Dirty Read 현상이 나타난다.

정합성에 문제가 많은 격리수준이다.

READ COMMITED

commit 된 레코드만 읽을 수 있게 하는 것이다. 하지만 NON-REPEATABLEREAD 문제가 발생할 수 있다. 이 문제는 다음과 같다.

  1. A가 트랜잭션을 시작해 SELECT 구문을 사용한다 → 나온 결과가 1개
  2. B가 트랜잭션을 시작해 INSERT 구문을 사용한다
  3. B가 트랜잭션을 commit 한다
  4. A가 트랜잭션을 끝내기 전에 SELECT 구문을 한 번 더 사용한다 → 오잉 2개? 아까랑 바꼈다

이는 금전적인 처리와 연결되면 더 문제가 될 수 있다. 예를 들어, 다른 트랜잭션에서 입금과 출금 처리가 계속 진행되고 있을 때 다른 트랜잭션에서 오늘 입금된 금액의 총합을 조회한다고 가정해보자. 그런데 'REPEATABLE READ'가 보장되지 않기 때문에 총합을 계산하는 SELECT 쿼리는 실행될 때마다 다른 결과를 가져올 것이다.

REPEATABLE READ

InnoDB의 기본 방식으로 Undo 로그를 사용해 현 시점의 과거 데이터를 읽어올 수 있도록 한다 (3장 InnoDB MVCC 참고)

REPEATABLE READ 격리 수준에서는 MVCC를 보장하기 위해 실행중인 트랜잭션 가운데 가장 오래된 트랜잭션 번호보다 트랜잭션 번호가 앞선 undo 영역의 데이터는 삭제할 수가 없다. 더 정확하게는 특정 트랜잭션 번호의 구간 내에서 백업된 언두 데이터가 보존돼야 하는 것이다.

SERIALIZABLE

읽기 작업도 공유 잠금(읽기 잠금)을 획득해야 하며, 동시에 다른 트랜잭션은 동일한 레코드를 변경하지 못한다.

성능 비교

READ UNCOMMITED 격리 수준과 READ COMMITED 격리 수준은 성능이 크게 차이나지 않는다. (Table 크기에 따라 2~7% 정도 성능)

  • 하나의 트랜잭션을 열어 그 트낼잭션에서 모든 테이블의 데이터를 SELECT한 이후, 그대로 놔두면 InnoDB의 undo 영역이 계속 커진다 이 경우는 제외 ㅎ..