4.0 개요
정리하면서 돌아보기
- MySQL의 서버의 전체 구조는 어떻게 구성되어 있는가?
- MySQL은 다른 DBMS와 어떤 점이 다른가?
- MySQL의 스레드와 메모리
- MySQL의 5.0 버전과 8.0 버전의 차이: 플러그인 구조와 컴포넌트 구조
- MySQL의 쿼리는 어떤 과정을 거쳐 실행되는가?
- InnoDB란?
- InnoDB에서 레코드 기반의 잠금이란?
- MVCC
- InnoDB에서 버퍼 풀이란?
- Undo Log, Redo Log
- MyISAM 엔진은 무엇인가
- InnoDB 엔진과 MyISAM 엔진의 차이?
Plain Text
복사
내가 알고 있던 것 ⇒ 추가로 알게 된 것
- InnoDB라는 게 있다(쿼리 실행하다가 로그에서 몇 번 봤음)
- MySQL의 장점은 트랜잭션으로 ACID 원칙을 지키는 것
- 트랜잭션은 커밋으로 반영하고 롤백으로 되돌린다
==============================================
- InnoDB 엔진이 트랜잭션/격리 수준을 보장하기 위해 DML 변경 이전 데이터를 별도로 백업한다(언두 로그)
- 트랜잭션이 롤백되면 언두 로그에 백업해 둔 이전 버전 데이터로 복구한다
- 트랜잭션 격리 수준에 맞게 변경 전의 데이터를 가져와야 하는 상황일 때, 언두 로그에서 데이터를 가져오기도 한다
- 5.0 버전에서는 MyISAM 엔진이, 8.0 버전에서는 InnoDB 엔진이 내장되어 있다
Plain Text
복사
느낀 점
- DBMS를 깊게 공부한다는 건 그냥 컴퓨터 구조를 공부하는 것과 똑같다
Plain Text
복사
4.1 MySQL 엔진 아키텍처
MySQL 전체 아키텍처
MySQL 서버 구성
•
MySQL 엔진: 요청된 쿼리문을 분석하거나 최적화
•
스토리지 엔진: 실제 데이터를 디스크 스토리지에 저장하거나 읽어온다
MySQL 엔진
스토리지 엔진은 핸들러 API를 만족하면 누구든지 스토리지 엔진을 구현해서 MySQL 서버에 추가하여 사용할 수 있다.
Plain Text
복사
스토리지 엔진
•
INSERT, UPDATE, SELECT, DELETE 등의 작업이 발생하면 스토리지 엔진이 처리를 담당
•
성능 향상을 위해 키 캐시(MyISAM), 버퍼 풀(InnoDB)과 같은 기능을 내장
핸들러 API
•
핸들러 요청 쿼리 실행기에서 데이터를 쓰거나 읽을 때 각 스토리지 엔진에 하는 쓰기 또는 읽기 요청
•
핸들러 API 핸들러 요청 시 사용되는 API
•
핸들러 API를 통해 얼마나 많은 데이터(레코드) 작업이 있었는지 확인 가능
SHOW GROBAL STATUS LIKE 'Handler%'
MySQL 서버는 스레드 기반으로 동작한다.
Thread vs Process
•
Process는 메모리에 올라와 실행되고 있는 프로그램의 인스턴스로, 운영체제로부터 시스템 자원을 할당받는 작업 단위. 실제 실행되고 있는 프로그램을 의미한다.
•
Thread는 프로세스 내에서 실행되는 여러 흐름의 단위로, 프로세스의 특정한 수행 경로를 의미한다.
MySQL은 왜 스레드 기반으로 동작할까?
•
만약에 쿼리를 실행할 때마다 하나의 프로세스가 생긴다면 메모리나 CPU에서 할당되는 비용이 너무 클 것 같다.
•
MySQL 서버 자체가 하나의 프로세스(3306포트)에서 실행된다고 볼 수도 있을 것 같다.
•
스레드 기반의 동작 ⇒ MySQL 서버 안에 엔진이 있고, 서버=프로세스라고 생각했을 때, 내부의 어떤 작업들이 멀티 스레드를 기반으로 실행되고, 프로세스의 자원을 공유한다고 생각할 수 있다.
그렇다면 프로세스 기반의 DBMS가 있을까?
PostgreSQL이 있다.
포그라운드 스레드
•
최소한 MySQL 서버에 접속된 클라이언트의 수 만큼 존재
•
각 클라이언트 사용자가 요청하는 쿼리 문장을 처리
•
클라이언트가 작업을 마치고 커넥션을 종료하면, 해당 커넥션을 담당하던 스레드는 다시 스레드 캐시로 되돌아감
•
데이터를 MySQL의 데이터 버퍼나 캐시로부터 가져오고, 없는 경우에는 직접 디스크의 데이터나 인덱스 파일에서 데이터를 읽어와서 작업을 처리함(InnoDB는 버퍼/캐시까지만 포그라운드 스레드가, 나머지 기록 작업은 백그라운드 스레드가 처리함)
•
사용자 스레드 == 포그라운드 스레드
백그라운드 스레드
•
대표적인 백그라운드 스레드 처리(InnoDB)
◦
Insert Buffer를 병합하는 스레드
◦
로그를 디스크로 기록하는 스레드
◦
InnoDB 버퍼 풀의 데이터를 디스크에 기록하는 스레드
◦
데이터를 버퍼로 읽어 오는 스레드
◦
잠금이나 데드락을 모니터링하는 스레드
•
Log Thread
•
Write Thread: 아주 많은 작업을 백그라운드로 처리하기 때문에 일반적인 내장 디스크를 사용할 때는 2~4 정도, DAS나 SAN같은 스토리지를 사용할 때는 디스크를 최적으로 사용할 수 있을 만큼 충분히
•
쓰기 작업은 지연될 수 있지만, 읽기 작업은 지연될 수 없다
◦
InnoDB는 쓰기 작업을 버퍼링해서 일괄 처리하는 기능이 있다(일반적임)
◦
MyISAM은 포그라운드 스레드가 쓰기 작업까지 함께 처리하도록 설게되어 있다
메모리 할당 및 사용 구조(글로벌 vs. 로컬)
글로벌 메모리 영역 | 로컬 메모리 영역
(세션 메모리 영역) | |
메모리 공간 | MySQL 서버가 시작되면서 운영체제로부터 할당 | 클라이언트 스레드(포그라운드 스레드)에게 독립적으로 할당 |
대표적인 영역 | - 테이블 캐시
- InnoDB 버퍼 풀
- InnoDB 어댑티브 해시 인덱스
- InnoDB 리두 로그 버퍼 | - 정렬 버퍼
- 조인 버퍼
- 바이너리 로그 캐시
- 네트워크 버퍼 |
중요한 특징 | - 각 쿼리의 용도별로 필요할 때만 공간이 할당되고, 필요하지 않은 경우 아예 할당 안 할수도 있음 |
플러그인 ⇒ 컴포넌트
플러그인 모델
•
서버만 잘 준비되어 있다면, 플러그인처럼 설치해서 바로 사용할 수 있는 형태를 플러그인 스토리지 엔진 모델이라고 한다.
•
플러그인 서버끼리는 통신할 수 없고, MySQL 서버의 변수/함수를 직접 호출하기에 캡슐화가 되지 않아 보안이 미흡하다는 점, 상호 의존 관계 설정이 불가능해서 초기화가 어렵다는 점 등의 단점으로 컴포넌트 아키텍처가 지원된다.
쿼리 실행 구조
1.
쿼리 파서
•
사용자 요청으로 들어온 쿼리를 토큰으로 분리해 트리 형태의 구조(파서 트리)로 만들어내는 작업
•
쿼리의 기본 문법 오류가 먼저 발견되고, 사용자에게 오류 메세지를 전달
2.
전처리기
•
파서 트리를 기반으로 쿼리 문장에 구조적인 문제점이 있는지 확인
•
토큰을 테이블 이름/칼럼 이름/내장 함수와 같은 개체를 매핑 → 해당 객체의 존재 여부와 객체의 접근 권한 등을 확인
•
실제 존재하지 않거나, 권한상 사용할 수 없는 개체의 토큰이 이 단계에서 걸러짐
파서 트리
3.
옵티마이저
•
쿼리 문장을 저렴한 비용으로 가장 빠르게 처리할지를 결정하는 역할(9장에 나옴)
4.
실행 엔진(쿼리 실행기)
•
실행 엔진이 핸들러에게 임시 테이블을 만들라고 요청
•
다시 실행 엔진은 WHERE 절에 일치하는 레코드를 읽어오라고 핸들러에게 요청
•
읽어온 레코드들을 1번에서 준비한 임시 테이블로 저장하라고 핸들러에 요청
•
데이터가 준비된 임시 테이블에서 필요한 방식으로 데이터를 읽어오라고 핸들러에게 다시 요청
•
최종적으로 실행 엔진이 결과를 사용자나 다른 모듈로 넘김
5.
핸들러(스토리지 엔진)
•
MySQL 서버의 가장 밑단에서 실행 엔진의 요청에 따라 데이터를 디스크로 저장하고 디스크에서 읽어오는 역할을 담당
쿼리 캐시
•
빠른 응답을 필요로 하는 웹 기반의 응용 프로그램에서 중요
•
SQL 쿼리의 실행 결과를 메모리에 캐시 + 동일한 쿼리가 실행되면 테이블을 읽지 않고 즉시 결과를 반환함
•
하지만 테이블의 데이터가 변경되면 캐시에 저장된 결과 중에서 변경된 테이블과 관련된 것들은 모두 삭제해야함(Invalidate) ⇒ 성능 저하 유발, 버그의 주요 원인
•
버전 8에서 사장됨
스레드 풀
•
내부적으로 사용자의 요청을 처리하는 스레드 개수를 줄여서, 동시 처리되는 요청이 많더라도 MySQL 서버의 CPU가 제한된 개수의 스레드 처리에만 집중할 수 있게 함
⇒ 서버의 자원 소모를 줄임
⇒ CPU의 프로세서 친화도가 높아짐
⇒ 운영체제 입장에서 불필요한 컨텍스트 스위치를 줄여서 오버헤드를 낮춤
눈에 띄는 성능 향상은 잘 없고 오히려 성능 저하도 발생할 수 있으니 주의
•
엔터프라이즈에서는 제공하지만 커뮤니티 에디션에서는 제공하지 않음
•
엔터프라이즈 스레드 풀은 MySQL 서버 프로그램에 내장
•
Percona Server에서 제공하는 스레드 풀은 플러그인 형태로 작동함
트랜잭션 지원 메타데이터
•
데이터베이스 서버에서 테이블의 구조 정보와 Stored Program 등의 정보
•
~5.7 테이블 구조, 일부 Stored Program의 정보를 파일 기반으로 관리
⇒ 트랜잭션 미지원 ⇒ 생성 도중 문제가 생긴다면 정합성 문제
•
8.0~ 모두 InnoDB 테이블에 저장하도록 개선됨
•
시스템 테이블과 데이터 딕셔너리 정보
⇒ mysql 이라는 이름의 DB에 저장(mysql.ibd)