Sitemap

MySQL Transaction and Lock

5 min readNov 25, 2024

--

2024.11.25

트랜잭션

하나의 논리적인 작업 셋에 하나 또는 그 이상의 쿼리 여부와 상관없이 논리적인 작업 셋이 100% 적용되거나 아무것도 적용되지 않아야함을 보장

트랜잭션의 범위를 최소화 추천

  • 메일 전송이나 FTP 파일 전송 또는 네트워크를 통해 원격 서버와 통신하는 작업은 DBMS의 트랜잭션 내에서 제거 추천
// BEFORE
1. 처리 시작
-> DB connection 생성
-> 트랜잭션 시작
2. 사용자의 로그인 여부 확인
3. 사사용자의 글쓰기 내용의 오류 여부 확인
4. 첨부로 업로드된 파일 확인 및 저장
5. 사용자의 입력 내용을 DBMS에 저장
6. 첨부 파일 정보를 DBMS에 저장
7. 저장된 내용 또는 기타 정보를 DBMS에서 조회
8. 게시물 등록에 대한 알림 메일 발송
9. 알림 메일 발송 이력을 DBMS에 저장
<- 트랜잭션 종료(COMMIT)
<- DB connection 반납
10. 처리 완료

// AFTER
1. 처리 시작
2. 사용자의 로그인 여부 확인
3. 사사용자의 글쓰기 내용의 오류 여부 확인
4. 첨부로 업로드된 파일 확인 및 저장
-> DB connection 생성
-> 트랜잭션 시작
5. 사용자의 입력 내용을 DBMS에 저장
6. 첨부 파일 정보를 DBMS에 저장
<- 트랜잭션 종료(COMMIT)
7. 저장된 내용 또는 기타 정보를 DBMS에서 조회
8. 게시물 등록에 대한 알림 메일 발송
-> 트랜잭션 시작
9. 알림 메일 발송 이력을 DBMS에 저장
<- 트랜잭션 종료(COMMIT)
<- DB connection 반납
10. 처리 완료

잠금

스토리지 엔진 레벨 & MySQL 엔진 레벨

글로벌 락

Flush TABLES WITH READ LOCK
  • 작업 대상 테이블이나 데이터베이스가 다르더라도 동일하게 영향
  • MySQL 8.0부터 Xtrabackup이나 Enterprise Backup 같은 백업 락 도입

백업 락

  • 일반적인 테이블 변경 허용
  • 정상적으로 복제는 실행되지만 백업의 실패를 막기 위해 DDL 명령이 실행되면 복제를 일시 중지하는 역할

테이블 락

LOCK TABLES table_name [ READ | WRITE ]
  • 개별 테이블 단위
  • 명시적으로 획득한 잠금은 UNLOCK TABLES로 해제 가능
  • 묵시적인 테이블 락은 쿼리가 실행되는 동안 자동으로 획득됐다가 쿼리가 완료된 후 자동 해제

네임드 락

GET_LOCK()
  • 임의의 문자열에 대해 잠금 설정
  • 여러 클라이언트가 상호 동기화를 처리해야할 때 사용
  • 복잡한 요건으로 레코드를 변경하는 트랜잭션에 유용

메타데이터 락

  • 데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금

InnoDB 스토리지 엔진 잠금

  • 레코드 기반의 잠금 방식
  • information_schema DB에 존재하는 INNODB_TRX, INNODB_LOCKS, INNODB_LOCK_WAITS라는 테이블 조인해서 현재 어떤 트랜잭션이 어떤 잠금을 대기하고 있고 해당 잠금을 어느 트랜잭션이 가지고 있는 지 확인 가능
  • 레코드 자체가 아니라 인덱스의 레코드를 잠근다

GAP Lock

  • 레코드와 레코드 사이의 간격을 잠궈서 그 사이의 간격에 새로운 레코드 생성 제어

Next Key Lock

  • 레코드 락 + 갭 락
  • REPEATABLE READ 격리 수준
  • 바이너리 로그 포맷을 ROW 형태로 바꿔서 넥스트 키락이나 갭락을 줄이는 것이 좋음

자동 증가 락

  • 자동 증가하는 숫자 값을 추출하기 위해 AUTO_INCREMENT라는 칼럼 속성 제공
  • InnoDB 내부적으로 테이블 수준의 잠금 사용
  • 트랜잭션과 관계없이 INSERT나 REPLAE 문장에서 AUTO_INCREMENT 값을 가져오는 순간만 락이 걸렸다가 즉시 해제

MySQL의 격리 수준

Press enter or click to view image in full size

READ UNCOMMITED

  • Dirty read = 어떤 트랜잭션에서 처리한 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼수 있는 현상
  • 더티 리드 허용
  • 정합성에 문제가 많은 격리 수준

READ COMMITED

  • 온라인 서비스에서 가장 많이 선택되는 격리 수준
  • 어떤 트랜잭션에서 데이터를 변경했더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회 가능

REPEATABLE READ

  • InnoDB 스토리지 엔진에서 기본으로 사용되는 격리 수준
  • 트랜잭션이 시작되기 전에 커밋된 데이터만 조회
  • 트랜잭션이 ROLLBACK될 가능성에 대비해 변경되기 전 레코드를 언두 공간에 백업해두고 실제 레코드 값을 변경 => MVCC
  • MVCC를 이용해 COMMIT 전 데이터 보여줌
  • MVCC를 보장하기 위해 실행 중인 트랜잭션 가운데 가장 오래된 트랜잭션 번호보다 트랜잭션 번호가 앞선 언두 영역의 데이터는 삭제 불가
  • InnoDB 스토리지 엔진에서는 갭 락넥스트 키 락 덕분에 PHANTOM READ발생 안함

SERIALIZABLE

  • 가장 단순하고 엄격한 격리 수준
  • 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근 불가
  • PHANTOM READ발생 안함

PHANTOM READ

  • 하나의 트랜잭션에서 두번의 동일한 조회를 하였을 때, 다른 트랜잭션의 INSERT로 인해 없던 데이터가 조회되는 현상
Press enter or click to view image in full size
https://parkmuhyeun.github.io/woowacourse/2023-11-28-Repeatable-Read/

--

--