백은빈, 이성욱 님의 "Real MySQL" 책을 정리한 포스팅 입니다.
1. Architecture

기능
- 잠금 (레코드 기반)
장점
- 성능
- 높은 동시성 처리
- 안정적
2. 클러스터링
프라이머리 키 기준
- 프라이머리 키는 다른 보조 인덱스에 비해 가중치가 높게 설정됨
3. 외래 키 지원
제약
슈퍼타입-서브타입
- 서브타입 테이블에 슈퍼타입 테이블의 기본 키를 참조하는 외래 키 컬럼을 설정해야 함
잠금이 여러 테이블로 전파됨
- 외래 키 제약이 활성화 되면 부모 테이블과 자식 테이블에 대해 잠금을 수행하게 됨
- 자식 테이블에서 데이터를 업데이트 하거나 삭제할 때 부모 테이블도 잠김
- 여러 테이블이 잠금 상태에 놓이게 되므로 데드락 발생 가능성이 발생함
foreign_key_checks
- 참조 무결성 제약 원칙 활성화
OFF
- 외래 키 관계의 부모 테이블에 대한 작업 무시
- 참조 무결성은 유지되지 않음
3. MVCC (Multi Version Concurrency Control)
- 레코드 레벨 수준의 동시성 제어 기법
Non-Locking Consistent Reads
하나의 레코드에 대해 여러 버전으로 관리
- 여러 트랜잭션이 동시에 실행될 때, 다른 트랜잭션의 데이터 변경을 신경 쓰지 않고 읽기 작업을 할 수 있음
가장 최신의 일관된 상태 제공
- 직전 버전의 데이터 확인 (트랜잭션 시작 시점 기준)
- Undo Log 활용
- Undo Log는 데이터의 이전 버전들을 보관
- 읽기 작업 시 변경 전의 데이터를 조회할 수 있음
UPDATE
Inno Buffer Pool
- 갱신된 값을 메모리에 기록
- 트랜잭션이 커밋되거나 롤백되기 전까지 메모리 상에 존재함
Undo Log
- 데이터가 변경되기 전, 기존 값을 기록
- 롤백할 경우, 데이터를 원래 상태로 되돌릴 수 있도록 함
Commit
Inno Buffer Pool 디스크 플러시
- Buffer Pool에 저장된 갱신된 값을 디스크에 반영
Undo Log 값 초기화
- Undo Log는 롤백을 위한 정보이므로, 커밋후에는 필요없게 됨
- 디스크에 반영된 후 삭제됨
Rollback
- Undo Log에 기록된 값을 사용하여 값을 복원
4. 자동 데드락 감지
잠금 대기 목록
그래프 형태
- 각 트랜잭션의 잠금 사애를 그래프 형태로 관리
- 이 그래프를 보고 서로 대기하는 루프가 발생되면, 데드락 감지 스레드가 개입하여 해결함
데드락 감지
데드락 감지 스레드
- 이 스레드는 일정 주기마다 트랜잭션 상태를 확인하고, 데드락이 감지되면 강제 롤백을 수행함
- 보통 Undo Log 크기가 작은 트랜잭션을 대상으로 롤백을 수행 (서버 부하 관점)
잠금 대기 목록
- 어떤 트랜잭션이 어떤 자원을 기다리고 있는지 정리한 목록
- 잠금 대기 목록을 확인하면서 트랜잭션 간의 교착 상태가 발생했는지 탐색 (순환 대기 검사)
- 잠금 대기 목록을 분석하는 동안, 새로운 트랜잭션이 잠금 정보를 변경하지 못하도록 잠금 대기 목록 자체에 새로운 잠금을 걸고 검사함
시스템 변수
- innodb_deadlock_detect: 데드락 감지 스레드 동작 여부
- innodb_table_locks: 테이블 레벨의 잠금까지 감지하는지 여부
- innodb_lock_wait_timeout: 데드락 상황에서 일정 시간이 지나면 에러나도록 타임아웃 시간 설정
5. 자동화된 장애 복구
- 서버가 예기치 않게 종료되었을 때 자동으로 데이터 복구 작업을 수행함
- 서버가 시작될 때 자동 복구를 수행
장애 복구가 필요한 상황
데이터 파일 또는 로그 손상
트랜잭션 충돌
서버 강제 종료
- 완료되지 못한 트랜잭션
- 데이터 일부만 기록된 디스크 페이지
innodb_force_recovery 시스템 변수
- 복구 모드를 설정하는 시스템 변수
- 레벨이 높을수록 더 많은 보구 작업을 무시하고 서버를 강제로 시작할 수 있음
- SELECT 이외의 쿼리는 수행할 수 없습니다.
복구 모드
- 데이터나 인덱스 페이지에서 손상된 부분이 발견되도 무시하고 서버 재시작
- 백그라운드 스레드가 실행되지 않도록 차단 후 서버 재시작 (체크포인트 작업, 리두 로그 플러시 비활성화)
- 비정상으로 종료된 트랜잭션 롤백하지 않고 서버 재시작 (일부 데이터의 손실될 가능성 고려)
- 인서트 버퍼에 데이터가 남아 있는데, 이 부분에 이상이 감지되더라도 재시작
- 언두 로그, 리두 로그 무시하고 서버 재시작 (데이터 무결성 보장이 어려움)
- 리두 로그가 손상되더라도 복구를 시도함 (데이터 무결성 보장 안됨)
6. InnoDB Buffer Pool
- 디스크의 데이터 파일이나 인덱스 정보를 메모리에 캐시해두는 공간입니다.
- 쓰기 작업을 지연시켜 일괄 작업으로 처리할 수 있게 해주는 버퍼 역할도 같이 합니다.
페이지
클린 페이지
- 디스크에서 읽은 페이지 입니다.
더티 페이지
- 디스크에 반영되지 않고 INSERT, DELETE, UPDATE 쿼리로 변경된 데이터를 가진 페이지 입니다.
레코드 버퍼
- 각 클라이언트 세션에서 테이블의 레코드를 읽고 쓸 때 버퍼로 사용하는 공간
개수
- 전체 커넥션 개수와 각 커넥션에서 읽고 쓰는 테이블의 개수에 따라 결정됩니다.
크기
- 정확한 크기를 측정할 수 없습니다. (동적으로 해제되기도 하므로)
- 청크 단위로 쪼개어 나뉩니다 (128MB)
- 내부 잠금 경합을 줄이기 위함입니다.
시스템 변수
- innodb_buffer_pool_size
- 버퍼 풀 사이즈를 의미합니다.
- 동적 변수 입니다.
- innodb_buffer_pool_instances
- 버퍼 풀을 여러 개로 관리할 수 있습니다.
- 기본 8개
- 버퍼 사이즈가 1GB 이하면 1개
구조
- 페이지 크기 조각 단위로 관리합니다
프리 리스트
- 비어 있는 페이지 목록
- 디스크에서 데이터를 읽어와야 하는 경우 사용됩니다.
LRU 리스트
- 한 번 읽은 데이터를 최대한 메모리에 유지해서 디스크 접근을 최소화함
- 자주 쓰는 데이터는 MRU에 위치하고, 사용 빈도가 낮아지면 LRU 리스트 끝으로 이동해 삭제됨
플러시 리스트
- 디스크에 아직 기록되지 않은 변경된 더티 페이지 목록
- 언젠가 디스크에 저장되어야 함
검색 과정
- 필요한 레코드의 데이터 페이지가 버퍼 풀에 존재하는지 검사
- InnoDB Adaptive Hash Index를 이용해 페이지를 검색
- 인덱스를 이용해 페이지 검색
- 디스크에서 필요한 데이터 페이지를 버퍼 풀에 적재
- 버퍼 풀의 LRU 헤더 부분에 적재된 데이터 페이지가 실제로 읽히면 MRU 헤더 부분으로 이동
- 버퍼 풀에 사주하는 데이터 페이지는 얼마나 최근에 접속했는지에 따라 나이가 부여되며 오랫동안 사용되지 않으면 제거된다
- 쿼리에 의해 재사용되면 나이가 초기화가 되고 MRU 헤더부분으로 옮겨진다.
- 필요한 데이터가 자주 접근됬다면 해당 페이지의 인덱스 키를 Adaptive Hash Index에 추가합니다.
워밍업
- 자주 사용되는 데이터를 버퍼 풀에 적재해두는 과정
- 디스크 i/o가 줄고 성능이 향상됩니다.
플러시
- 디스크와 메모리 간의 데이터 동기화 작업을 의미함
- 백그라운드에서 더티 페이지들의 디스크 플러시 기능을 수행
플러시 리스트 플러시
- 로그 엔트리의 더티 페이지를 디스크로 동기화 합니다.
- 디스크 공간을 재활용할 수 있게 함
LRU 리스트 플러시
- 사용 빈도가 낮은 데이터 페이지들을 제거하고, 새로운 페이지들을 버퍼 풀에 읽어오는 기능
시스템 변수
- innodb_page_cleaners: 더티 페이지를 디스크로 동기화 하는 클리너 스레드의 개수 (한 스레드 당 버퍼 풀 인스턴스 담당)
- innodb_max_dirty_pages_pct: 버퍼 풀의 더티 페이지 비율
- innodb_max_dirty_pages_pct_lwm: 일정 수준 이상의 더티 페이지가 발생하면 조금씩 디스크로 기록하기 위한 기준
- innodb_io_capacity: 디스크 i/o 용량 설정 (시스템이 얼마나 많은 더티 페이지를 일고 쓸수 있는지 결정)
- innodb_io_capacity_max: 디스크가 최대의 성능을 발휘할 때 어느정도 더티 페이지 읽고 쓰기가 가능한지 설정
- innodb_adaptive_flushing: 어댑티브 플러시 기능 활성화 (리두 로그 증가 속도를 분석해서 적절하게 더티 페이지 유지)
- innodb_adaptive_flushing_lwm : 어댑티브 플러시 알고리즘 작동 기준 (활성 리두 로그 공간 점유 비율)
- innodb_flush_neighbors: 더티 페이지를 디스크에 기록할 때 근접한 페이지 중에 더티 페이지가 있다면 같이 기록
- innodb_lru_scan_depth: LRU 리스트의 끝부분부터 시작해서 설정된 개수만큼 페이지를 스캔
Double-Write Buffer
데이터 무결성
- 디스크에 데이터를 기록하는 도중, 시스템이 실패할 경우 데이터 손실을 방지하기 위해 사용됨
- 리두 로그는 변경 내용만 기록하기 때문에 페이지의 일부만 기록되는 문제가 발생할 수 있습니다.
Double-Write
- 디스크에 한번에 기록하지 않고 두번 기록하여, 시스템 실패 시 복구할 수 있게 함
- 페이지에 기록되는 도중 실패할 경우 백업의 목적
페이지 기록 과정
- 더티 페이지를 64개씩 묶어 Double-Write Buffer에 기록
- Double-Write Buffer에서 디스크의 Double-Write 영역으로 일괄 기록
- Double-Write 영역에 기록된 데이터를 각 테이블의 데이터 파일에 개별적으로 기록
- 완료 후 Double-Write Buffer에서 해당 페이지 제거
시스템 변수
- innodb_doublewrite: Double-Write 기능 사용 여부를 활성화
- innodb_flush_log_at_trx_commit: 리두 로그 동기화 설정을 활성화 (리두 로그가 디스크에 동기화되는 시점을 알 수 있음)
Write Buffering
성능 최적화
- 변경 사항을 즉시 디스크에 기록하는 대신, 먼저 리두 로그에 저장
고정 크기 순환 방식
- 고정 크기 파일들을 연결해서 순환 고리처럼 사용 (기록될 때마다 로그 포지션 증가)
- 리두 로그가 다 차면 처음부터 다시 덮어쓰는 방식으로 동작
LSN (Log Sequence Number)
- 리두 로그에 기록될 떄마다 증가하는 일련번호
- LSN을 기준으로 체크포인트와 활성 로그 공간을 관리
활성 리두 공간
- 활성 리두 공간은 재사용 불가능한 공간으로, 더티 페이지와 연관된 로그입니다.
- 재사용 가능한 공간과 당장 재사용이 불가능한 공간으로 구분하여 관리
체크 포인트
- 더티 페이지를 디스크로 동기화하는 시점
- 리두 로그가 가득 차면 체크포인트가 발생합니다
- 체크 포인트가 발생 시
- 체크포인트 LSN보다 작은 리두 로그 엔트리와 관련된 더티 페이지는 모두 디스크로 동기화 됩니다
- 디스크로 기록된 데이터의 리두 로그 공간은 재사용 가능해집니다.
체크포인트 에이지
- 가장 최근의 체크포인트 LSN과 마지막 리두 로그 엔트리의 LSN 차이를 가리킵니다.
- 마지막 체크포인트 이후 남은 데이터 양을 나타냅니다.
- 즉, 활성 리두 공간의 크기를 의미합니다.
백업 및 복구
- 버퍼 풀의 데이터를 복원하거나 백업하는 기능
- 시스템 재시작 후에도 이전의 성능 상태를 복구하는 데 유용함
ib_buffer_pool 파일
- 버퍼 풀의 메타 정보만 저장하는 파일
- LRU 리스트에서 적재된 데이터 페이지의 메타 정보를 포함
- 이 파일을 통해 백업 및 복구 작업을 수행함
시스템 변수
- innodb_buffer_pool_dump_now: 현재 버퍼 풀의 상태 즉시 백업하기 (워밍업 용)
- innodb_buffer_pool_load_now: 백업된 버퍼 풀의 상태 즉시 복구하기 (시스템이 시작될 때 백업된 데이터 복구)
- innodb_buffer_pool_load_abort: 백업 중 복구 작업을 중단하고자 하는 경우 켜기
- innodb_buffer_pool_load_at_startup: 시스템 종료 시, 버퍼 풀 백업 자동화 (자동화)
- innodb_buffer_pool_dump_at_shutdown: 시스템 시작 시, 버퍼 풀 복구 (자동화)
- innodb_buffer_pool_dump_status: 복구 작업의 진행 상태를 확인할 수 있는 변수
테이블
- information_schema.innodb_buffer_page: 버퍼 풀에 적재된 페이지 정보 확인
- information_schema.innodb_cached_indexes: 인덱스별로 버퍼 풀에 적재된 페이지 정보 확인
리두 로그
커밋된 변경 사항을 기록하는 로그 파일
- 예기치 못하게 서버가 종료되었을 경우 데이터 파일에 기록되지 못한 데이터를 잃지 않게 해주는 안전장치 입니다.
- 커밋됬지만 데이터 파일에 기록되지 않은 경우, 리두 로그의 내용을 가져와 데이터 파일에 복사합니다.
로그 버퍼
- 리두 로그를 일시적으로 저장하는 메모리 공간
- 서버가 빈번한 디스크 I/O를 피하게 해주며 전체적인 성능을 향상시킵니다.
- 일정 크기에 도달하거나 트랜잭션이 일어나면 리두 로그 파일에 쓰여집니다.
- 기본적으로 16MB로 설정되어 있습니다.
리두 로그 아카이빙
DO innodb_redo_log_archive_start('backup', '20200722');
DO innodb_redo_log_archive_stop();
리두 로그 활성화 및 비활성화
ALTER INSTANCE ENABLE INNODB REDO_LOG;
ALTER INSTANCE DISABLE INNODB REDO_LOG;
시스템 변수
- innodb_flush_log_at_trx_commit: 리두 로그를 어느 주기로 디스크에 동기화할지 결정하는 변수
- innodb_log_file_size: 리두 로그 파일의 크기를 결정합니다.
- innodb_log_files_in_group: 리두 로그 파일의 개수를 결정합니다.
- innodb_redo_log_archive_dirs : 리두 로그가 저장될 디렉터리를 지정합니다.
- innodb_redo_log_enabled : 리두 로그 활성화 여부를 뜻합니다.
언두 로그
- DML 실행 시, 변경되기 이전 데이터의 버전을 저장하는 공간
ROLLBACK
- ROLLBACK 시, 언두 로그에 있는 데이터를 다시 데이터 파일로 복원
- 현재 트랜잭션이 종료되기 전까지 관련 언두 로그는 삭제되지 않음
- 언두 로그가 많아질수록 메모리 사용량이 증가하여 성능 저하 가능
트랜잭션의 격리 수준 보장
- MVCC를 지원하여 격리수준을 보장함
레코드 모니터링
SHOW ENGINE INNODB STATUS
언두 테이블 스페이스
SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE LIKE 'UNDO LOG';
- 언두 로그가 저장되는 공간
- 시스템 테이블 스페이스와 분리되어 별도의 로그 파일로 저장됨
- 구성 요소
- 롤백 세그먼트: 1개의 언두 테이블 스페이스는 128개 이하의 롤백 세그먼트를 가짐
- 언두 슬롯: 1개의 롤백 세그먼트는 (페이지 크기 / 16byte) 개의 언두 슬롯을 가집니다.
언두 퍼지
- 퍼지 스레드는 주기적으로 깨어나 불필요해진 언두 로그를 삭제하는 작업을 수행
- 트랜잭션이 데이터를 변경하면 언두 로그에 기록되고 트랜잭션이 커밋되면 언두 로그가 불필요해짐
시스템 변수
- innodb_undo_log_truncate: 언두 퍼지를 활성화 여부를 의미한다.
- innodb_purge_resg_truncate_frequency: 언두 퍼지를 빈번하게 하는 정도를 의미한다.
어댑티브 해시 인덱스
- 사용자가 자주 요청하는 데이터에 대해 자동으로 생성하는 인덱스 입니다.
- 인덱스의 B-Tree 검색 시간을 줄여주기 위해 도입된 기능입니다.
- B-Tree 인덱스는 균형 트리 구조이므로 트리 깊이 만큼 노드를 탐색하는 비용이 발생함
- 특정 키 값에 대한 검색이 자주 반복될 경우, B-Tree를 계속 탐색하는 것은 비효율적
- 어댑티브 해시 인덱스를 사용하면 단위 시간으로 데이터를 찾을 수 있음
- 페이지의 키 값을 이용해 해시 인덱스를 만들고 즉시 찾아갈 수 있습니다.
해시 인덱스
- 인덱스 키값과 해당 인덱스 키 값이 저장된 데이터 페이지 주소의 쌍으로 관리됩니다.
- 인덱스 키
- B-Tree 인덱스의 고유번호와 B-Tree 인덱스의 실제 키 값 조합으로 생성됨
- 즉, AHI는 B-Tree 인덱스를 기반으로 생성된 해시 테이블
- innodb_adaptive_hash_index: 어댑티브 해시 인덱스 자동 생성의 활성화 여부
출처
'Database > Mysql' 카테고리의 다른 글
[Real MySQL] 5-1. 트랜잭션과 잠금: 트랜잭션 (1) | 2023.11.24 |
---|---|
[Real MySQL] 4-4. 아키텍쳐: MySQL 로그 파일 (1) | 2023.11.24 |
[Real MySQL] 4-1. 아키텍쳐: MySQL 엔진 아키텍쳐 (0) | 2023.11.23 |
[Real MySQL] 3. 사용자 및 권한 (1) | 2023.11.23 |
[Real MySQL] 2. 설치와 설정 (0) | 2023.11.22 |