Real MySQL 8.0 - 11.8 쿼리 성능 테스트 부분에서 Direct I/O라는 용어가 나왔는데, MySQL 튜닝의 중요한 요소인 것 같아서 정리하게 되었다.
Direct I/O 란?
운영체제의 파일 시스템 캐시를 사용하지 않고 데이터를 직접 디스크에 읽거나 쓰는 방법
- 일반적으로 운영체제는 파일을 읽을 때 파일 시스템 캐시를 사용하여 읽기 속도를 향상시킨다. (`Buffered I/O`)
- 파일이 한 번 읽힌 후, 해당 데이터는 캐시에 저장되어 다음에 동일한 데이터에 액세스할 때 디스크로부터 읽는 대신 캐시에서 데이터를 제공한다.
- 즉, 캐시 히트했을 경우의 데이터 읽기 속도가 빨라진다.
- 그런데 InnoDB는 이미 `버퍼 풀`이라는 훨씬 고도화된 메모리 영역을 가지고 있기 때문에 동일한 데이터를 버퍼 풀과 운영체제의 캐시에 이중으로 저장해서 메모리를 낭비할 필요가 없다. ➡️ `Double Buffering`
- InnoDB의 버퍼 풀 캐시는 운영체제의 캐시보다 더 체계적이고 효율적이기 때문에 운영체제의 캐시가 별로 도움이 되지 않는다.
- 운영체제의 캐시는 DB 작업 외에 작업 시 언제든지 지워질 수 있다.
- 파일 캐시를 경유하지 않고 버퍼 풀에서 디스크로 직접 액세스해서 불필요한 지연(2중 캐시 처리)이 발생하지 않도록 하는 방식이 바로 `Direct I/O`이다.
- 메모리 효율적 사용: 복사 과정 감소
- 캐시 관리 단순화: 파일 시스템 캐시를 사용하지 않기 때문에 캐시 관리의 복잡성을 피할 수 있음
🐈 참고
- `Double Buffering`: 메모리상에서 buffer pool과 OS Cache에 중복으로 데이터를 저장하는 것
- `Double Write Buffer`: 데이터의 안전성을 위해 디스크상에 중복된 데이터를 이중으로 저장하는 것
innodb_flush_method
InnoDB 스토리지 엔진에서 Flush 작업을 어떻게 수행할 것인지를 결정하는 설정 옵션
- `Flush`: 데이터를 일시적인 저장소(캐시나 버퍼)에서 영구적인 저장소(디스크)로 옮기는 작업 (`In-Memory` ➡️ `On-Disk`)
- 운영체제는 디스크에 데이터를 쓰는 작업을 운영체제의 버퍼로 기록하는 작업과 버퍼의 내용을 디스크로 복사하는 두 단계의 작업을 어떻게 조합하느냐에 따라 3가지 관점으로 쓰기 방식을 분류한다.
- 동기 vs 비동기
- 동기(Sync): 두 단계의 작업을 동시에 같이 실행하는 방식
- 비동기(Async): 두 단계 작업을 각각 다른 시점에 실행하는 방식 ➡️ 직접적으로 사용되지는 않음
- 메타 데이터(파일의 속성, 권한 등) 반영 여부
- `fsync`: 데이터와 파일의 메타데이터를 한꺼번에 변경하는 방식
- `fdatasync`: 파일의 메타정보는 무시하고 순수하게 사용자의 데이터만 변경하는 방식
- Direct I/O 사용 여부
- 동기 vs 비동기
option 종류
fsync
기본값. 데이터나 로그 파일을 열고 쓸 때 `fsync()`를 사용함
- 파일의 데이터와 메타데이터를 모두 디스크에 동기화(sync)
+) fdatasync
`fdatasync()` 시스템 콜을 지원하는 플랫폼에서 `fsync()` 대신에 `fdatasync()`을 사용하도록 허용함
- 파일의 데이터만 디스크에 동기화하고, 메타 데이터는 필요한 경우에만 디스크에 write
- `fdatasync`는 데이터 안정성을 보장하는데 필요한 최소한의 동기화를 수행하기 때문에 `fsync`보다 약간의 성능 향상을 얻을 수 있음
O_DIRECT
데이터 파일을 열 때는 `O_DIRECT`, 데이터 파일과 로그 파일을 쓸 때는 `fsync()`를 사용함
- 대용량 데이터를 읽을 때 디스크에서 직접 가져오면 읽기 성능을 향상시킬 수 있음
- 데이터를 기록할 때는 안전하게 디스크에 반영하기 위해 `fsync()`를 사용함
그런데 왜 Direct I/O가 기본값이 아닐까?
- Buffered I/O 방식과 비교했을 때 메모리도 효율적으로 사용할 수 있고
- 교재(Real MySQL 8.0) 에서도 InnoDB가 일반적으로 Direct I/O 방식을 사용한다고 해서
`innodb_flush_method`의 기본값도 Direct I/O 방식일 줄 알았다
InnoDB는 일반적으로 파일 시스템이나 캐시나 버퍼를 거치지 않는 Direct I/O 방식을 사용하므로 운영체제의 캐시가 그다지 큰 영향을 미치지 않는다. - Real MySQL 8.0 - 11.8.1.1
+) MySQL의 기본 스토리지 엔진은 InnoDB
하지만 (위에서 언급했듯이) 기본값은 `fsync`이다.
아마 다음의 이유가 아닐까 생각한다.
- `fsync()`를 사용했을 때의 데이터 안정성과 일관성
- Direct I/O를 사용했을 때 오히려 성능이 떨어질 수 있음
fdatasync vs O_DIRECT ❓
https://www.mimul.com/blog/sysvar_innodb_flush_method/
- 128MB 이전에는 `fdatasync` 방식이 성능이 더 높고
- 128MB 이후부터는 `O_DIRECT` 방식의 성능이 더 높게 나왔다.
- 앞쪽으로 `fdatasync` 방식의 성능이 더 높은 것은 InnoDB 버퍼 풀에 없는 데이터가 OS 파일 캐시에 있어 디스크 I/O를 줄일 수 있기 때문에 성능 이점을 얻은 것 같다. ➡️ 즉, OS 파일 캐시가 InnoDB 버퍼 풀에 대한 보조 캐시 역할 수행했기 때문!
- `O_DIRECT`가 `fdatasync`에 비해 동등한 성능 이상을 발휘하기 위해서는 다음 조건 중 하나를 충족해야 한다.
- 모든 데이터가 InnoDB 버퍼 풀에 들어가거나
- 물리 메모리의 절반 정도를 InnoDB 버퍼 풀에 할당하는 경우
- RAID 컨트롤러에 Write Cache가 붙어있고, 그 Write Cache가 Battery Backed Unit(BBU)이 있을 경우
➡️ 즉, 디스크 I/O 횟수가 많지 않은 경우 성능 향상 효과가 있다.
정리
디스크 I/O가 MySQL 성능에 큰 영향을 주는 만큼, 상황에 맞게 적절한 파일 I/O 방식을 선택하는 것이 중요해 보인다.
버퍼 풀의 크기와 데이터의 안정성의 중요도 등 다양한 요소가 선택에 영향을 주는 만큼, 각 방식의 특징을 잘 알아두고 직접 테스트를 해서 설정값을 조절하는 방법을 잘 익혀둬야겠다!
Ref
https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_flush_method
https://nomadlee.com/mysql-database-commit-architecture/
https://systemv.tistory.com/49
'Backend > Database' 카테고리의 다른 글
[MySQL] 데이터베이스 확장 방식 (0) | 2024.03.21 |
---|---|
[MySQL] 커서(Cursor) (0) | 2024.03.14 |
[MySQL] 문자열 패턴 매칭 연산자 (REGEXP, LIKE) (0) | 2024.02.22 |
[MySQL] 실행 계획 - partitions 칼럼 (0) | 2024.02.15 |
[MySQL] 히스토그램 (0) | 2024.02.07 |