반응형
도서 '데이터베이스 첫걸음'을 보고 책 내용과 그 이외의 부족한 부분을 채워가며 공부한 내용입니다.
키워드 : 트랜잭션, DDL, DML, DCL, 잠금 타임아웃, 교착상태
1. 트렌잭션
테이블을 갱신할 때 갱신이 단일 쿼리만으로 구성된 것이 아니고 복수 쿼리를 연속적으로 수행하는 경우가 대부분
갱신 전의 데이터로 select를 사용할 때 이를 포함해 복수쿼리를 일관된 형태의 한 덩어리로 다뤄야 함.
이런 복수의 쿼리를 한 단위로 묶은 것
== DBMS에서 데이터를 다루는 논리적인 작업의 단위
- DB에서 데이터를 다룰 때 장애가 일어난 경우 데이터를 복구하는 작업의 단위가 됨
- DB에서 여러 작업이 동시에 같은 데이터를 다룰 때가 이 작업을 서로 분리하는 단위가 됨
- 트랜잭션은 전체가 수행되거나 전혀 수행되지 않아야 함(All or Nothing)
트랜잭션의 특성
- 원자성
- 데이터의 변경(Insert/Delete/Update)을 수반하는 일련의 데이터 조작이 전부 성공할지 실패할지 보증하는 구조
- 상황 예시
- 서울 -> 부산행 좌석 예매
- 부산에서 숙박 예약
- 부산 -> 서울행 좌석을 예매
- ①~③의 대금을 지급
- 모두 잘 진행된다면 ①~④를 진행 후 COMMIT을 실행해 처리를 확정
- 해당 경우 각 데이터의 조작은 영구적으로 저장되어 결과가 손실되지 않음
- 처리도중 오류가 발생시 ROLLBACK을 실행(①의 직전상태까지 되돌아갈 수 있음)
- 일관성
- 데이터베이스 오브젝트(테이블을 비롯해 데이터베이스 내에 정의할 수 있는 오브젝트)에 대해 각종 정합성 제약을 추가해 데이터 조작 전후에 그 상태를 유지하는 것을 보증하는 것
- ex)시스템에 사용자를 등록할 때 임의로 식별하기 위해 일련번호(사용자 번호)를 사용자에게 발급
- 위의 일련번호는 유니크 제약(유일성 제약)을 설정하면 중복된 사용자 번호를 지정할 수 없음
- 데이터베이스 오브젝트(테이블을 비롯해 데이터베이스 내에 정의할 수 있는 오브젝트)에 대해 각종 정합성 제약을 추가해 데이터 조작 전후에 그 상태를 유지하는 것을 보증하는 것
- 고립성
- 일련의 데이터 조작을 복수 사용자가 동시에 실행해도 '각각의 처리가 모순 없이 실행되는 것을 보증'
- 복수의 트랜잭션이 순서대로 실행되는 경우와 같은 결과를 얻을 수 있는 상태
- 병렬로 실행되지 않는(직렬)상태
- 직렬화 기능
- 직렬화 기능의 고립성에서는 항상 동시에 동작하는 트랜잭션이 1개의 이미지가 되어 성능면에서 실용적이지 못함
- ANSI(American National Standards Institute)
- 직렬화 기능으로부터 격리 수준을 완화해 직렬화 기능 이외에 자신이 아닌 다른 트랜잭션의 영향을 받는 것을 허용하는 4단계
- 커밋되지 않은 읽기
- 커밋된 읽기
- 반복 읽기
- 직렬화 기능
- 직렬화 기능
- 일련의 데이터 조작을 복수 사용자가 동시에 실행해도 '각각의 처리가 모순 없이 실행되는 것을 보증'
-
- 격리수준 완화에 따라 발생하는 현상
- 더티 읽기(Dirty Read):어떤 트랜잭션이 커밋되기 전에 다른 트랜잭션에서 데이터를 읽는 현상
- 애매한 읽기(Fuzy/NonRepeatable Read):어떤 트랜잭션이 이전에 읽어들인 데이터를 다시 읽어들일 때 2회 이후의 결과가 1회 때와 다른 현상
- 팬텀 읽기(Phantom Read):어떤 트랜잭션을 읽을 때 선택할 수 있는 데이터가 나타나거나 사라지는 현상
- 격리수준 완화에 따라 발생하는 현상
격리 수준 | 더티 읽기 | 애매한 읽기 | 팬텀 읽기 |
커밋되지 않은 읽기 | O | O | O |
커밋된 읽기 | X | O | O |
반복 읽기 | X | X | O |
직렬화 기능 | X | X | X |
-
- 상황 예시
- 부산의 지정호텔에 남은 싱글룸 수가 10개
- 현재 빈 싱글룸 수 확인(select)
- 빈 싱글룸 수에서 1을 빼고 결과를 빈 싱글룸 수로 되돌려 씀(update)
- 상황 예시
- 위의 경우 2명이 동시에 룸을 예약할 경우 발생 가능
- 데이터베이스 오브젝트인 테이블에 대해 'Lock(잠금)'을 걸어서 후속 처리를 블록(Block)하는 방법
- 잠금의 단위
- 테이블 전체
- 블록
- 행(주로 사용)
- 지속성
- 일련의 데이터 조작(트랜잭션 조작)을 완료(COMMIT)하고 완료 통지를 사용자가 받는 시점에서 그 조작이 영구적으로 되어 그 결과를 잃지 않는 것을 나타냄
MySQL
- 2종류의 테이블
- MyISAM형 : 트랜잭션을 사용할 수 없는 단순한 구조
- InnoDB형 : 일반적인 DBMS와 똑같은 트랜잭션 구조를 사용할 수 있음
- MVCC라는 구조로 동작
2. 다른 커넥션에서 테이블 보기
DDL(Data Definition Language)
데이터를 저장하는 그릇인 스키마 또는 테이블 등을 작성하거나 제거
CREATE(데이터베이스 or 테이블 작성), DROP(CREATE로 작성한 것 제거), ALTER(CREATE로 작성한 것을 변경)
DML(Dta Manipulation Language)
테이블의 행을 검색하거나 변경하는 데 사용
SELECT, INSERT, UPDATE, DELETE
DCL(Data Control Language)
데이터베이스에서 실행한 변경을 확정하거나 취소하는데 사용
COMMIT, ROLLBACK
기본적으로 DDL에 따른 테이블 작성과 DML에 따른 데이터 저장은 트랜잭션이
커밋되기 전까지는 다른 커넥션에서 보이지 않지만 이에 상관없이 다른 커넥션에서 보이는 경우가 있음
- DDL에 따른 암묵적인 커밋
- MySQL이나 Oracle에서는 CREATE TABLE과 같은 DDL 실행 시 암묵적인 커밋 발생
- 오토커밋 설정
- 트랜잭션의 개시(BEGIN TRANSACTION, START TRANSACTION, SET TRANSACTION 등)가 명시적으로 지정되지 않았을 때 트랜잭션을 구별하는 방법
- 하나의 SQL 문이 하나의 트랜잭션으로 구분(AUTO COMMIT)
- 사용자가 COMMIT 또는 ROLLBAKC을 실행하기까지가 하나의 트랜잭션
- 트랜잭션의 개시(BEGIN TRANSACTION, START TRANSACTION, SET TRANSACTION 등)가 명시적으로 지정되지 않았을 때 트랜잭션을 구별하는 방법
3. 복수 커넥션에서 읽기와 쓰기
MVCC(Multi Versioning Concurrency Control)에 따른 MySQL의 특성
- 읽기를 수행할 경우 갱신 중이라도 블록되지 않음(읽기와 읽기도 블록되지 않음) -> 쓰기-쓰기 상태 불가
- 읽기 내용은 격리 수준에 따라 내용이 바뀌는 경우도 있음
- 갱신 시 배타적 잠금을 얻음. 잠금은 기본적으로 행 단위로 얻으며 트랜잭션이 종료할 때까지 유지하고 격리수준이나 InnoDB의 설정에 따라 실제로 잠금하는 행의 범위가 다른 경우 존재
- 갱신과 갱신은 나중에 온 트랜잭션이 잠금을 획득하려고 할 때 블록됨. 일정 시간을 기다리며 그 사이에 잠금을 획득할 수 없는 경우 '잠금 타임아웃(Lock Timeout)'이 됨
- 갱신하는 경우 갱신 전의 데이터를 UNDO 로그로 '롤백 세그먼트'라는 영역에 유지
- UNDO로그
- 갱신하는 트랜잭션의 롤백 시 갱신 전으로 되돌리는 것
- 복수의 트랜잭션으로부터 격리 수준에 따라 대응하는 갱신 데이터 참조
- UNDO로그
트랜잭션 격리 수준 별 외관
MySQL 트랜잭션 격리 수준 : 반복 읽기(RR, Repeatable Read)
격리 수준 변경
set transaction isolation level repeatable read(격리 수준); start transaction;
반복 읽기
최초 쿼리를 실행한 시점에서 커밋된 데이터를 읽어들임
복수 회의 쿼리 실행 사이에 다른 트랜잭션이 커밋했어도 해당 내용 반영 x
커밋된 읽기
쿼리를 실행한 시점에서 커밋된 데이터를 읽어들임
같은 쿼리를 복수 회 실행하면 그 사이에 다른 트랜잭션에서 커밋할 때가 있는데 이 경우 최신 쿼리의 실행 개시 시점에서 커밋된 데이터를 읽음
갱신을 수행하는 트랜잭션 자신
트랜잭션 격리 수준이나 COMMIT/ROLLBACK에 상관없이 자신이 수행했던 갱신을 즉시 볼 수 있음
커밋되지 않은 읽기가 사용되지 않는 이유
MVCC를 이용하면 읽기가 블록되는 경우는 없음 -> 커밋되지 않은 읽기 필요 X
4. 잠금 타임아웃과 교착 상태
잠금 타임아웃
'갱신'과 '참조'는 서로를 블록하지 않지만 '갱신'과 '갱신'이 부딪치는 경우 나중에 온 갱신이 잠금대기상태
set innodb_lock_wait_timeout=1; (잠금 타임아웃 시간 = 1초)
- 잠금 대기로 타임아웃이 발생하는 경우 DBMS로부터 롤백되는 단위가 다를 때가 있음
- 해당 트랜잭션 전체를 롤백하는 경우와 쿼리만 롤백하는 경우
- 해결책
- 타임아웃 오류 후 명시적으로 ROLLBACK을 함
- innodb_rollback_on_timeout 시스템 변수 설정
- 잠금 타임아웃은 일정 시간 기다리면 상황이 개선될 가능성이 있음
교착 상태
트랜잭션 A가 테이블 a의 잠금을 얻고 트랜잭션 B가 테이블 b의 잠금을 얻었다 가정
이 잠금을 유지한 채 서로 잠금을 건 자원에 잠금이 필요한 처리(INSERT/UPDATE/DELETE)를 실행하면 아무리 기다려도 상황이 바뀌지 않는 상태 발생 -> 교착 상태
- 단순히 기다려도 해결 x
- MySQL은 교착상태가 일어나면 이를 즉시 인식해 시스템 영향이 작은 쪽의 트랜잭션 개시 시점까지 롤백
- 교착 상태의 일반적인 데이터베이스에서 발생할 가능성이 있으며 모든것을 없앨 수는 없음
- 애플리케이션 쪽에서는 항상 트랜잭션이 교착상태를 일으켜 롤백되는 경우에 트랜잭션을 재실행 할 수 있는 구조로 만들어야함
- DBMS 전반적인 대책
- 트랜잭션 자주 커밋
- 정해진 순서로 테이블(그리고 행)에 액세스 하도록 유도
- 어떤 트랜잭션이라도 테이블a -> 테이블b처럼 동일한 순서로 액세스하도록 유도
- 필요없는 경우에는 읽기 잠금 획득(select~ for update 등)의 사용을 피함
- 쿼리에 의한 잠금 범위를 더 좁히거나 잠금 정도를 더 작은 것으로 함
- MySQL 트랜잭션의 격리 수준을 되도록 '커밋된 읽기'로 하기
- 한 테이블의 복수 행을 복수의 연결에서 순서 변경 없이 갱신하면 교착 상태가 발생하기 쉬움
- MySQL의 대책
- 테이블에 적절한 인덱스를 추가해 쿼리가 이를 이용하게 됨
- 인덱스가 사용되지 않는 경우에는 필요한 행의 잠금이 아닌 스캔한 행 전체에 대해 잠금이 걸림
5. 해서는 안 되는 트랜잭션 처리
오토 커밋
쿼리 단위로 커밋하는 설정
- 어플리케이션의 잠금을 실행하는 데는 커밋의 부하가 너무 높음
- 일정 수 이상의 갱신을 수행하는 처리나 트랜잭션의 기능등은 적절한 단위와 트랜잭션 격리 수준에서 트랜잭션을 이용해 오토커밋을 사용하지 않도록 해야함
긴 트랜잭션
데이터베이스 트랜잭션의 동시성이나 자원의 유효성 저하
- 갱신을 포함한 트랜잭션은 같은 테이블과 행을 갱신하려는 다른 트랜잭션을 블록하고 이것이 장시간 이어지면 블록된 트랜잭션을 타임아웃
- 해당 잠금과 블록 사이에 교차가 발생하면 교착 상태가 되고 긴 트랜잭션 중 하나가 롤백될 수 있음
- 교착 빈도를 낮출 필요가 있음
- 주의 사항
- 대량 처리를 한 개의 트랜잭션이 실행
- 대량 처리는 적당한 크기의 트랜잭션으로 나눠서 실행
- ex) 신규 테이블에 데이터를 로드할 때 1만 건당 커밋
- 아무것도 하지 않는 트랜잭션
- 같은 테이블에 갱신을 실행할 때 이 테이블의 반복 읽기를 유지하기 우해 UNDO 로그가 계속 유지된 상태가 됨
- 트랜잭션 중 대화 처리
- 트랜잭션은 되도록 작게하고 트랜잭션을 구성하는 내용에는 언제 끝날지를 알 수 없는 불명확한 처리를 포함해서는 안됨
- 처리 능력 이상의 트랜잭션 수
- 어떠한 잠금이 있는 처리를 수행할 때 이 잠금이 다른 트랜잭션의 처리를 막는다면 잠금 타임아웃이나 교착 상태의 확률이 증가하고 이는 성능저하로 이어짐
- 하드웨어의 부하실험을 통해 어느정도 상한선을 할지 정할 필요가 있음
- 대량 처리를 한 개의 트랜잭션이 실행
참고 자료
1. 미크, 기무라메이지, 데이터베이스 첫걸음(출판지 : 한빛미디어, 2016)
반응형
'데이터 베이스' 카테고리의 다른 글
데이터 베이스 1 (0) | 2023.05.01 |
---|---|
테이블 설계의 기초 (0) | 2022.05.23 |
데이터베이스 아키텍처 구성 (0) | 2022.05.19 |
데이터베이스 DBMS, 비용 (0) | 2022.05.19 |
데이터베이스 기본기능 (0) | 2022.05.19 |