Open ruthetum opened 1 year ago
격리 수준 관련해서 책도 설명이 잘 되어 있는데 같이 읽어보면 좋을 포스트 공유드려요.
DB별 기본 격리 수준
- MySQL: REPEATABLE READ
- Oracle: READ COMMITTED
- Postgre: READ COMMITTED
MySQL 이랑은 무관하지만, 트랜잭션 관련해서 재밌게 본 내용이 있어 공유합니닷 😋 뎁캠때 MSA 구성하면서 트랜잭션때매 애먹었는데 MSA 아키텍처 패턴들이랑 보상 트랜잭션 재밌었슴다
https://waspro.tistory.com/603 https://doqtqu.tistory.com/337
저도 예전에 보상 트랜잭션, 사가 패턴에 대해서 관심이 있어서 찾아봤던 적이 있는데 당시에 제가 아카이빙했던 아티클 공유드려요~
책 내용 관련해서 조금 더 자세하게 나와있는 좋은 글을 발견해서 공유합니다!
InnoDB lock & deadlock - https://www.letmecompile.com/mysql-innodb-lock-deadlock/ InnoDB 트랜잭션 격리 수준 - https://www.letmecompile.com/mysql-innodb-transaction-model/
ch5. 트랜잭션과 잠금 정리한 내용입니다.
공유차 올린 자료이고, 지수님이 정리해주신 자료가 조금 더 자세하고 내용이 깊은 것 같네요
https://github.com/ruthetum/study/blob/main/db/real-mysql/ch05-transaction-lock.md
저도 정리 링크 공유합니다~~ https://www.notion.so/5-4d740168db3146028c38670912d3d1dd
트랜잭션과 잠금
트랜잭션
여러 개의 작업을 하나로 묶은 실행 유닛을 의미하고, 작업의 완전성을 보장한다
논리적인 작업 셋이 모두 처리되거나, 모두 처리되지 않도록 원 상태로 복구하는 기능
트랙잭션 특성 (ACID)
MySQL에서의 트랜잭션
MyISAM 엔진은 트랜잭션을 지원하지 않아서 부분 업데이트(Partial Update) 발생
InnoDB 엔진은 트랜잭션이 적용되어서, 롤백됨
주의사항
트랜잭션은 최소한의 코드에만 적용하는 것이 좋다!
잠금
MySQL 엔진 잠금
: 모든 스토리지 엔진에 영향 미침스토리지 엔진 잠금
: 해당 스토리지 엔진에만 영향MySQL엔진 잠금
글로벌 락
MySQL 서버의 모든 테이블에 잠금을 건다
FLUSH TABLES WITH READ LOCK
명령으로 획득한 세션에서 글로벌 락을 획득하면, 다른 세션의 SELECT 를 제외한 거의 대부분의 DDL, DML 은 대기 상태가 된다
(반대로, 장시간 SELECT 쿼리가 실행되고 있으면
FLUSH TABLES WITH READ LOCK
은 해당 쿼리가 종료될 때까지 기다려야한다)InnoDB는 트랜잭션을 지원해서 일관된 데이터 상태를 위해 모든 데이터 변경 작업을 멈출 필요가 없다
그래서, MySQL 8.0 부터는
백업 락
이라는 더 가벼운 글로벌 락이 도입되었다.특정 세션에서 백업 락을 획득하면 모든 세션에서 테이블 스키마나 사용자의 인증 관련 정보를 변경할 수 없게 된다
일반적인 테이블의 데이터 변경은 허용된다
테이블 락
개별 테이블 단위로 설정되는 잠금
명시적:
LOCK TABLES table_name [READ | WRITE ]
로 획득하고,UNLOCK TABLES
로 해제특별한 상황 아니면 사용할 필요가 없다
묵시적으로는 MyISAM이나 Memory 테이블에 데이터 변경 쿼리를 실행하면 발생한다
쿼리가 실행되는 동안 자동으로 획득했다가 완료 후 해제된다
InnoDB 테이블은 레코드 기반 잠금을 제공해서 데이터 변경 쿼리로 인해 묵시적인 테이블락이 설정되지는 않는다 (테이블 락이 설정되지만 DDL에만 영향)
네임드 락
GET_LOCK()
함수를 이용해 임의의 문자열에 대해 잠금을 설정할 수 있다DB 1대를 5대의 웹서버가 접속하는 상황에서, 상호 동기화를 처리해야 할 때나, 많은 레코드에 대해서 복잡한 요건으로 변경을 하는 트랜잭션에 활용할 수 있다
MySQL 8.0 부터는 네임드 락의 중첩 사용도 가능
메타 데이터 락
데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 잠금
RENAME TABLE tab TO tab_b
같이 테이블 이름을 변경하는 경우 자동으로 획득된다 (원본, 변경될 이름 둘 다 잠금 설정)InnoDB 스토리지 엔진 잠금
레코드 기반의 잠금 기능을 제공하여 MyISAM보다 뛰어난 동시성 처리를 제공한다
Information Schema
조회로 트랜잭션과 잠금, 잠금 대기중인 트랜잭션 목록을 조회할 수 있고,Performance Schema
를 이용해 내부 잠금(세마포어) 모니터링도 할 수 있다 (8.0 부터는 Performance Schema 주로 이용)레코드 락
레코드 자체만을 잠그는데 인덱스의 레코드를 잠근다!
보조 인덱스를 이용한 변경 작업은 넥스트 키락(Next-key lock) 또는 갭락(Gap lock)을 사용하고, 프라이머리키 혹은 유니크 인덱스에 의한 변경 작업은 레코드 락을 건다
갭 락
레코드와 인접한 레코드 사이의 간격을 잠그는 것으로, 간격에 새로운 레코드가 생성(INSERT)되는 것을 제어한다
넥스트 키 락
레코드 락과 갭 락을 합쳐놓은 형태
범위를 지정한 쿼리를 실행하게되면 실제로는 위에서 각각 설명했던 record lock (찾아진 인덱스 레코드에 대해)과 gap lock (해당하는 인덱스 레코드 사이사이) 이 복합적으로 사용된다.
바이너리 로그에 기록되는 쿼리가 레플리카 서버에서 실행될 때, 소스 서버에서 만들어낸 결과와 동일한 결과를 만들어내도록 보장하는 것이 주 목적이다
자동 증가 락
자동 증가하는 숫자 값을 채번하기 위해 AUTO_INCREMENT라는 칼럼 속성을 제공하는데, 이를 위해 InnoDB에서는 자동 증가 락이라고 하는 테이블 수준의 잠금을 사용한다
자동 증가 락은 INSERT 와 REPLACE 같이 새로운 레코드를 생성하는 작업에만 걸리고, UPDATE 혹은 DELETE 에는 걸리지 않는다
innodb_autoinc_lock_mode
라는 시스템 변수를 이용해 작동 방식을 변경할 수 있다격리 수준
여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 말지를 결정하는 것
DIRTY READ: 트랜잭션에서 처리한 작업이 완료되지 않았는데 다른 트랜잭션에서 볼 수 있는 현상
NON-REPEATABLE READ: SELECT 시 항상 같은 결과를 가져오는 REPEATABLE READ 이 보장되지 않는다
PHANTOM READ: 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다 안 보였다 하는 현상
READ UNCOMITTED
변경 내용이 커밋과 롤백 여부에 상관없이 다른 트랜잭션에 보여진다
데이터 정합성에 문제가 많기 때문에 보통 사용되지 않는다
READ COMITTED
커밋이 된 데이터만 다른 트랜잭션에서 조회할 수 있다
오라클에서 기본으로 사용되는 격리 수준이며, 온라인 서비스에서 가장 많이 사용된다
변경 전 데이터가 언두 로그로 복사되고, 커밋 전 데이터를 조회하면 이 언두 로그 데이터가 반환된다
REPEATABLE READ
동일 트랜잭션 내에서는 동일한 결과를 보장한다
InnoDB의 기본 격리 수준으로, 바이너리 로그를 가진 MySQL은 최소 REPEATABLE READ 격리 수준 이상을 사용해야 한다
(InnoDB는 갭 락과 넥스트 키 락이 있어서, 검색하고자 하는 범위 내에 갭 락을 걸어서 특정 데이터가 추가, 삭제되어 발생하는 Phantom Read가 발생하지 않는다 -> 확인 필요)
REPEATABLE READ와의 차이는 언두 영역에 백업된 레코드의 여러 버전 중 몇 번째 이전 버전까지 찾아 들어가느냐에 있다
모든 트랜잭션은 고유 번호를 가지고, 언두 영역의 레코드도 변경을 발생시킨 트랜잭션의 번호가 포함되어 있다
해당 트랜잭션 안에서 실행되는 모든 SELECT 쿼리는 트랜잭션 번호가 자신의 번호보다 작은 번호에서 변경된 것만 보게 된다
SELECT FOR UPDATE
쿼리SERIALIZABLE
보통 SELECT는 아무런 레코드 잠금도 설정하지 않고 실행되지만 SERIALIZABLE 수준에서는 읽기 작업도 공유 잠금을 획득해야 하고, 다른 트랜잭션이 레코드를 변경하지 못한다
기타 참고자료
트랜잭션 문법
START TRANSACTION
트랜잭션 시작COMMIT
트랜잭션을 DB에 적용ROLLBACK
트랜잭션을 취소하고, START TRANSACTION 실행 전 상태로 롤백DDL은 트랜잭션의 롤백 대상이 아니다
DDL, DML, DCL
DDL(Data Definition Language)
: CREATE, ALTER, DROP, RENAME, TRUNCATEDML(Data Manipulation Language)
: SELECT, INSERT, UPDATE, DELETEDCL(Data Control Lanaguage)
: GRANT, REVOKETCL(Transaction Control Language)
: COMMIT, ROLLBACK, SAVEPOINT락 & 데드락
https://www.letmecompile.com/mysql-innodb-lock-deadlock/
Consistent Read
https://dev.mysql.com/doc/refman/8.0/en/innodb-consistent-read.html
https://www.letmecompile.com/mysql-innodb-transaction-model/