트랜잭션, MySQL 엔진의 잠금, InnoDB 스토리지 엔진의 잠금, MySQL의 격리 수준을 알아보자
트랜잭션
: 작업의 완전성
보장
=> 모두 완벽하게 처리 or 처리 못할 경우 원 상태로 복구
MyISAM
: INSERT 문장
이 실행되면서 차례대로 저장하다가 중복 키 오류
등이 발생하는 경우 이미 INSERT
된 데이터는 두고 종료
=> 부분 업데이트
InnoDB
: 쿼리 중 일부라도 오류
가 발생하면 전체
를 원 상태로 만듦
MySQL 엔진 레벨 잠금
: 스토리지 엔진
을 제외한 나머지 부분
=> 모든 스토리지 엔진
에 영향 미침
=> 테이블 데이터 동기화를 위한 테이블 락
=> 테이블의 구조를 잠그는 메타데이터 락
=> 사용자의 필요에 맞게 사용할 수 있는 네임드 락
글로벌 락(Global Lock)
: 잠금 범위가 가장 큼
=> flush tables with read lock
명령으로 획득
=> 다른 세션
에서 select 제외
한 대부분의 ddl 문장
이나 dml 문장
실행시 대기
=> MySQL 서버 전체에 영향
=> 테이블이나 데이터베이스가 다르더라도 동일하게 영향
=> MyISAM
이나 MEMORY 테이블
에 mysqldump
로 백업
시
InnoDB
엔진은 트랜잭션 지원
하므로 일관된 데이터 상태를 위해 모든 데이터 변경 작업
을 멈출 필요는 없음
XtraBackup
이나 Enterprise Backup
툴 실행 중 스키마 변경
시 백업 실패
가 되므로, 백업 실패를 막기 위해 DDL 명령
실행되면 복제 일시 중지
하는 역할
테이블 락(Table Lock)
: 개별 테이블 단위
로 설정되는 잠금
=> lock tables table_name [Read|Write]
명령으로 획득
=> MyISAM
, InnoDB
동일 설정
=> Unlock Tables
명령으로 잠금 해제
네임드 락(Named Lock)
: 임의의 문자열
에 대해 잠금 설정
=> GET_LOCK()
함수 이용
=> 단순히 사용자가 지정한 문자열에 대해 획득하고 반납
메타데이터 락(Metadata Lock)
: 데이터베이스 객체의 이름
이나 구조
를 변경하는 경우 획득
InnoDB 스토리지 엔진
은 스토리지 엔진 내부
에서 레코드 기반
의 잠금 방식 탑재
=> 동시성 처리
뛰어남
갭(GAP) 락
: 레코드
와 레코드
사이의 간격
을 잠그
는 것
락 에스컬레이션
발생 X
=> 레코드 락
이 페이지 락
또는 테이블 락
으로 업그레이드 되는 경우 없음
레코드 락(Record Lock)
: 레코드 자체
만을 잠그는 것
=> InnoDB는 인덱스의 레코드
를 잠금
=> 프라이머리 키
또는 유니크 인덱스
변경 작업
갭 락(Gap Lock)
: 레코드와 바로 인접한 레코드 사이 간격만
잠금
=> 레코드와 레코드 사이 새로운 레코드가 생성
되는 것을 제어
넥스트 키 락(Next Key Lock)
: 레코드 락
과 갭 락
을 합쳐 놓은 형태의 잠금
=> 대부분 보조 인덱스
를 이용한 변경 작업
=> 바이너리 로그
에 기록되는 쿼리가 레플리카 서버
에서 실행될 때 소스 서버
에서 만들어낸 결과와 동일한 결과
를 만들어내도록 보장하는 것이 주목적
Auto_increment Lock
: Auto_increment
칼럼이 사용된 테이블에 동시에 여러 레코드가 insert
되는 경우, 중복되지 않고 순서대로 증가하는 일련번호 값
을 위한 테이블 수준 잠금
변경해야 할 레코드
를 찾기 위해 검색한 인덱스
의 레코드를 모두 락
걸어야 함
-- ix_firstname 인덱스만 존재
update employees
set hire_date=NOW()
where first_name='Georgi'
and last_name='Klassen';
위 문장이 실행되면 1건의 레코드
가 업데이트 될 것이다.
1건의 업데이트를 위해 253건의 레코드
가 모두 잠긴다.
만약 인덱스가 없다면, 30여만 건
의 모든 인덱스를 잠금
-- 어떤 잠금을 가지고 있는지
select * from performance_schema.data_locks \G
--17번 스레드 강제 종료
kill 17;
트랜잭션의 격리 수준(isolation level)
: 여러 트랜잭션이 동시
에 처리될 때 특정 트랜잭션이 다른 트랜잭션
에서 변경
하거나 조회
하는 데이터를 볼 수 있게 허용할지 말지 결정하는 것
DIRTY READ | NON-REPEATABLE READ | PHANTOM READ | |
---|---|---|---|
READ UNCOMMITTED | 발생 | 발생 | 발생 |
READ COMMITTED | 없음 | 발생 | 발생 |
REPEATABLE READ | 없음 | 없음 | 발생 (Inno DB는 없음) |
SERIALIZABLE | 없음 | 없음 | 없음 |
READ UNCOMMITTED
: 각 트랜잭션에서의 변경 내용이 commit
이나 rollback
여부에 상관없이 다른 트랜잭션
에서 보임
Dirty Read
: 어떤 트랜잭션에서 처리한 작업이 완료되지 않았는데
도 다른 트랜잭션에서 볼 수 있는 현상
READ COMMITTED
: 어떤 트랜잭션에서 데이터를 변경했더라도 commit
이 완료된 데이터만 다른 트랜잭션에서 조회 가능
=> NON-REPEATABLE READ
발생
REPEATABLE READ
: MVCC
를 위해 언두 영역
에 백업된 이전 데이터를 이용해 동일 트랜잭션 내
에서는 동일한 결과
를 보여줄 수 있게 보장
PHANTOM READ
: 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다 안 보였다
하는 현상
SERIALIZABLE
: 읽기 작업
도 공유 잠금
을 획득해야만 하며, 동시에 다른 트랜잭션은 그러한 레코드를 변경하지 못하게 됨
=> InnoDB는 갭 락
과 넥스트 키 락
덕분에 repeatable read 격리 수준
에서도 이미 phantom read 발생X