트랜잭션과 격리 수준
트랜잭션 특징
원자성(Atomicity)
- 트랜잭션이 DB에 보두 반영되거나 모두 반영되지 않아야 한다.
일관성(Consistency)
- 트랜잭션의 작업 처리 결과는 항상 일관성 있어야 한다.
독립성(Isolation)
- 한 트랜잭션이 동시에 병행될 때, 다른 트랜잭션이 연산에 끼어들 수 없다.
지속성(Durability)
- 트랜잭션이 성공적으로 처리되면 영구적으로 반영되어야 한다.
Commit 과 Rollback
Commit : 하나의 트랜잭션이 성공적으로 끝나 DB에 지속성을 만족시켰음을 알리는 연산
Rollback : 하나의 트랜잭션 처리 중 하나가 비정상이였을때 원자성이 깨져 원래 대로 돌린다.
DBMS의 구조
DB의 구조는 Query Processor(쿼리 처리기) 와 Storage System(저장 시스템) 으로 나뉜다.
Buffer는 Storage System에 속하는 모듈 중 하나로 디스크로의 입출력 횟수를 줄이기 위해
Buffer의 레코드를 통해 관리한다.
UNDO
- 수정된 Page들이 Buffer 교체 알고리즘에 따라 디스크에 입출력,
- Buffer는 transaction이 연산에 실패하여 Rollback 해야하는 상황에 이전 UNDO logging를 기반으로 원상 복구하게 되는데 이 복구를 UNDO라고 한다.
MySQL의 엔진 종류
MySQL의 스토리지 엔진
1) MyISAM
- Table과 Index를 다른 파일로 관리
- Read Only가 많은 서비스는 MyISAM엔진이 효율적
2) InnoDB
- 트랜잭션 처리가 필요하고 대용량의 데이터를 다루기 위해서는 InnoDB가 효율적
- InnoDB는 Tablespace 개념을 사용한다.
- PK를 기준으로 클러스터링
- 오라클 의 주요 개념이 많이 적용됨( MVCC , 테이블 스페이스 등)
- ** MVCC: 읽기 작업시, 다른 트랜잭션의 락이 풀리기 기다리지 않고 읽기 가능
Database Lock
데이터베이스의 동시성을 보장하기 위하여 잠금 장치 역할한다. 하나의 데이터를 동시에 여러명이 조작할 수 없도록 함
락의 종류
1. 글로벌 락 - write의 락을 적용함. 모든 테이블의 락을 획득한다.
2. 테이블 락
- Read Lock : 한쪽에서 데이터를 읽을 때 Read Lock을 획득하면 쓰기 불가능
- Write Lock : 한쪽에서 데이터를 수정하거나 insert할 때 반대쪽에서 읽기 불가능
명시적 방법 : LOCK TABLES table_name [ READ | WRITE ]
묵시적 방법 : 쿼리 실행시 자동 잠금, 잠금해
3. 네임드 락(유저 레벨)
-get_lock 명령어로 lock을 획득한다. 한쪽에서 획득하면 다른쪽에선 획득 불가능.
4. 메타데이터 락
- 데이터베이스의 구성(스키마,테이블,뷰)의 이름이나 구조를 변경하는 경우 획득하는 잠
5. 레코드 락
- select되는 Row에 락을 거는 기능(SQL이 자동으로 실행해줌)
6. Auto Increment Lock
- ID와 같이 데이터 생성 시 자동으로 값이 할당되는 값의 경우 insert되는 잠시 동안 걸리는 Lock
격리수준 Isolation Level
여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 말지 결정함
격리 수준의 종류 (격리수준 오름차순)
- read uncommitted == dirty read
- 거의 사용되지 않음
- 트랜잭션의 변경 내용이 commit이나 rollback 여부에 상관 없이 보임
- 에러가 발생해서 rollback된 항목을 commit 전에 접근해서 에러가 발생할 수 있음
- read committed
- 트랜젝션이 완료된 데이터만 다른 트랜잭션에서 조회 가능
- 커밋되기 전에는 언두로그에 있는 곳의 데이터를 읽어옴
- 언두로그 → 뭔가 잘못되면 돌려야돼서 임시로 저장하는 공간
- unrepeatable read(반복 읽기 불가) : 상황 가정 한 트랜잭션 내에서 타 트랜잭션이 테이블을 조작하면 조회 결과물이 다르게 나올 수 있다(일관성에 어긋남)
- 커밋 전에 불러오면 가져오는 값이 없고,
- 커밋 후에 불러오면 가져오는 값이 있음
- 문제 없어 보이지만 정합성에 어긋남
- repeatable read
- 언두 영역에 백업된 이전 데이터를 이용해서 동일 트랜잭션에서는 같은 내용을 보여줄 수 있도록 함
- phantom read
- 언두 레코드에는 lock을 걸 수 없어서 같은 트랜잭션에서 조회 가능
- 언두로그에 존재하지 않던 새로운 컬럼이 나옴 이를 phantom read (유령)라 함
상황 예시)
상황 설정 사용자 A와 사용자 B가 각각 다른 트랜잭션을 수행하고 있음. 사용자 A는 특정 조건 (예: 잔액이 5,000원 이상인 계좌) 을 만족하는 모든 계좌의 수를 확인하려고 함.
- 사용자 A의 첫 번째 쿼리 사용자 A는 트랜잭션에서 조건을 만족하는 계좌가 총 10개임을 확인함.
- 사용자 B의 데이터 변경 동시에, 사용자 B는 다른 트랜잭션에서 새로운 계좌를 추가함. 이 계좌는 사용자 A가 사용한 같은 조건을 만족함. 사용자 B의 트랜잭션이 커밋되어 새 계좌가 데이터베이스에 추가됨.
- 사용자 A의 두 번째 쿼리 사용자 A는 같은 트랜잭션에서 다시 조건을 만족하는 계좌의 수를 확인함. 이번에는 총 11개의 계좌가 있음을 확인함.
4. serializable
- 동시성이 중요한 데이터베이스의 경우 거의 사용되지 않음
- read도 lock을 획득해야만 가능함
- read가 lock을 가지고 있기 때문에, write나 update, delete등을 실행할 수 없음