어중간한 상태 방지하기SQL 문 레벨에서의 롤백무정지성(Fault Tolerant) 확보하기REDO 로그의 역할이중 기록의 비용잠금 메커니즘에 의한 배타 제어잠금의 범위잠금 기간복제 및 트랜잭션쿼리가 재실행되어 불일치가 일어날 때, 이를 알아내는 방법
NoSQL의 대부분은 트랜잭션 기능을 갖고 있지 않음
어중간한 상태 방지하기
- 어플리케이션 개발에서서는 오류 처리를 반드시 고려해야 함. 갱신하는 동안 오류가 발생했을 때 어떤 상황이 발생하며 거기에서 어떻게 복구할 수 있는지를 생각할 필요가 있음
- 마지막까지 처리를 마치고 결과를 확정시키는 것을 커밋 커밋하지 않고 모든 작업을 원래대로 되돌리는 것을 롤백 이라고 함
SQL 문 레벨에서의 롤백
- UPDATE 문을 한 번 밖에 실행하지 않기 때문에 트랜잭션이 불필요하다 라고 생각할 수 있음
- 그러나. 한번의 업데이트에서 여러 레코드를 업데이트 할 수 있다 → 레코드 업데이트 하다가 강제종료가 되어 버리면 어떻게?? ROLLBACK 다 해주어야 함
- 한 개의 레코드밖에 갱신하지 않는다면 문제 없을까? → 아니야. 인덱스가 있는 테이블에서는 갱신 대상의 열 값만 아니라 갱신 대상의 인덱스도 갱신함!
- 한 개의 SQL 문이라고 해도 내부에서는 복수의 작업을 수행하기에 처리 도중에 멈춘 경우에 데이터가 어중간한 상태가 될 수 있음
무정지성(Fault Tolerant
) 확보하기
데이터 파일
과 REDO 로그 파일
의 두 종류의 파일을 갖는 방식은 트랜잭션을 지원하는 데이터베이스의 표준적인 아키텍처임- OS 장애 등의 서버 장애가 발생하여 그로부터 데이터베이스를 재기동한 때에 장애 직전까지의 커밋 결과를 손실하지 않고 마치는 것이 가능함
- 트랜잭션을 지원하지 않는 데이터베이스의 경우는 OS 장애 뿐 아니라 데이터베이스 프로세스가 비정상적으로 종료하기만 해도 데이터베이스가 손상될 수 있음
- ORACLE, InnoDB 같은 트랜잭션 대응의 데이터베이스에서는 이런 문제 발생 x . 기술적으로 REDO 로그를 이용한 아키텍처로 무정지성을 보장함
REDO 로그의 역할

- 트랜잭션 커밋하면 그때마다
LSN
(Log Sequence Number)이라는 시퀀스 번호가 증가하고, 그 번호와 갱신 대상의 블록의 정보(갱신할 곳의 블록 ID 및 갱신할 곳의 위치 및 값)를REDO 로그 파일
에 씀
- 열의 값과 인덱스를 갖는
데이터 파일
에는 커밋을 할 때마다 기록을 하는 것이 아니라 캐시 영역에 보관해 두고 정기적으로 디스크에 기록하는 동작을 함(= 체크 포인트) ⇒ REDO 로그 파일이 최신 커밋 정보를 가지고 있는 반면, 본체의 데이터 파일은 오래된 데이터를 가지고 있게 됨 - 캐시 영역에 최신 데이터가 있기에 어플리케이션에서 보면 최신 데이터를 읽고 쓸 수 있음
- 만약 서버 장애 등의 이유로 디스크에 기록을 하지 못하고 데이터베이스가 멈춰서 재기동을 할 때, 캐시 데이터가 없어졌으니
데이터 파일
은 이전 데이터를 갖고 있게 됨 →REDO 로그
의 내용을데이터 파일
에 적용시킴으로데이터 파일
과REDO 로그
의LSN
을 일치시키는 작업 수행함 ↔Clash Recovery(충돌 복구)
이중 기록의 비용
- REDO 로그에도 기록하고 데이터 파일에도 기록하니 2배 느려지는 것 아닐까?
- 그렇지 않다. REDO 로그 파일이 순차적 기록을 해서 =
Sequential Write
는 HDD에서 매우 빠름 - 레코드나 인덱스로의 기록은
Random Write
임. 즉, 기록 대상의 영역(블록)을 메모리로 읽어들이고 그것을 갱신한 후 디스크에 기록하는 흐름. 대상 블록이 메모리에 없으면 디스크에서 읽어 온다라는 식의 처리(랜덤 읽기)도 발생 ⇒ HDD 에서 매우 느림! - 그러나 SSD에 의한 고속화가 진행되면서 점차 REDO 로그 파일의 순차적 기록 시간을 무시할 수 없게 되었음
잠금 메커니즘에 의한 배타 제어
- 예를 들어 어떤 가족이 10만원잔액이 있다고 할 때, 남편이 3만원 입금하고 아내가 5만원 인출하면 잔고는 8만원 이어야 함. 이러한 동시 액세스가 발생했을 경우, 모순된 상태가 되지 않도록 배타제어를 해야 함
- 이를 막기 위한 메커니즘이 바로 잠금
- 잠금 메커니즘의 단점은 동일한 레코드에 대해 갱신이 동시에 한 개의 클라이언트 밖에 할 수 없다는 점
- 여러 클라이언트에서 갱신할 수 있도록 잠금을 걸지 않고 배타 제어를 실시하는
락 프리
(Lock Free
) 알고리즘도 주목 끌고 있음 - 이 경우 충돌이 발생하더라도 일관성 있는 상태로 복원할 수 있도록 구현해야 할 필요가 있어 구현의 복잡성이 크게 향상됨
잠금의 범위
- MyISAM의 경우 테이블에 대한 잠금 ⇒ 이렇게 되면 병렬성이 크게 저하됨
- InnoDB등 현대적 RDBMS에서 확보하고 있는 잠금의 범위는 레코드
- Oracle과 InnoDB의 경우 기록을 하고 있는 동안에도 커밋 완료된 데이터를 읽을 수 있다는 특징이 있어 병렬성 향상에 크게 공헌중
잠금 기간
- 잠금은 트랜잭션의 종료(커밋 또는 롤백) 시까지 유지함
- 커밋 전에 잠금을 해제하면 나중에 롤백할 수 없는 위험이 있기 때문임
복제 및 트랜잭션
- 복제 구성에 있어서 슬레이브에서는
마스터에서 전송되어 온 업데이트성 쿼리를 실행하는 역할
을 함 - 이 처리는 사실 업데이트성 쿼리를 실행하는 것만으로는 충분하지 않고
슬레이브는 마스터에서 보낸 업데이트성 쿼리 중에서 어디까지를 실행했는지
라는 정보도 관리할 필요가 있음 - 그렇게 해야 슬레이브가 멈추었을 경우 어디서부터 다시 시작하면 좋은지 알 수 있음

- 위 이미지에서 슬레이브가 바이너리 로그를 실행할 때 현재 어디까지 실행 했는지를 관리하기 위해
실행을 마친 바이너리 로그의 위치 정보를 관리하는 InnoDB 테이블을 제공
함
- 그리고 갱신 SQL 문의 실행과 위치 정보(어디까지 실행했는지) 갱신을 동일한 트랜잭션에서 실시
- 그럼으로써, 슬레이브가 어느 타이밍에 크래쉬 된다 해도 갱신 확정된 쿼리를 또다시 실행하는 일이 없게 됨
- 이렇게 되면 슬레이브 다운 시 완전 초기부터 재구성 할 필요 없이 차이나는 부분에 대해서만 복구를 진행 할 수 있음
- MySQL Cluster에서는 이미 동일한 기능이 오래전 부터 구현되어 있음
BEGIN; UPDATE user_data SET money=50 WHERE id=1; COMMIT;
BEGIN; UPDATE user_data SET money=50 WHERE id=1; UPDATE slave_relay_data_log_info SET exec_master_pos=100; COMMIT;
쿼리가 재실행되어 불일치가 일어날 때, 이를 알아내는 방법
- 불일치 검출은 전통적으로 테이블의 전부 또는 일부를 스캔하여 체크섬(check-sum)을 계산하거나 하는 등의 형태로 이루어짐
- MySQL에서는 이러한 툴이 존재함