[Real MySQL 1권] 4.1.1 MySQL의 전체 구조, MySQL 스레딩 구조
아키텍쳐란?
architecture = 구조
소프트웨어나 시스템의 구조와 구성 요소, 그리고 이들 간의 관계를 설명하는데 사용되는 용어
4장에서는 MySQL 데이터베이스 관리 시스템의 내부 구조와 구성 요소들이 어떻게 상호 작용하고 조직되어 있는지 학습합니다.
4.1 MySQL 엔진 아키텍처
다른 DBMS에 비해 구조가 상당히 독특하며, 다른 DBMS에서는 가질 수 없는 엄청난 혜택을 누릴 수 있다. 반대로 다른 DBMS에 문제되지 않을 것들이 가끔 문제가 되기도한다.
4.1.1 MySQL 전체구조
- 일반 상용 RDBMS와 같이 대부분의 프로그래밍 언어로부터 접근 방법을 모두 지원한다.
- 모든 언어로 MySQL 서버에서 쿼리를 사용할 수 있게 지원한다.
- MySQL 서버는 크게 MySQL엔진과 스토리지 엔진으로 구분
- MySQL의 쿼리파서나 옵티마이저 등과 같은 기능을 스토리지 엔진과 구분하고자 ‘MySQL 엔진’, ‘스토리지 엔진’으로 구분
- 그리고 이 둘을 모두 합쳐서 그냥 ‘MySQL’ or ‘MySQL서버’라 부름
4.1.1.1 MySQL 엔진
역할 : 요청된 SQL 문장을 분석하거나 최적화 하는 등 DBMS의 두뇌에 해당하는 처리를 수행 (1개 사용 가능)
구성 : 커넥션 핸들러 + SQL 파서 및 전처리기 + 옵티마이저
- 커넥션 핸들러 : MySQL 엔진은 클라이언트로부터의 접속 및 쿼리 요청
- SQL 파서 및 전처리기
- 옵티마이저 : 쿼리의 최적화된 실행을 위함
- MySQL은 표준 SQL 문법을 지원하기 떄문에 표준 문법에 따라 작성된 쿼리는 타 DBMS와 호환되어 실행될 수 있다.
4.1.1.2 스토리지 엔진
역할 : 실제 데이터를 디스크 스토리지에 저장하거나 디스크 스토리지로부터 데이터를 읽어오는 부분 전담 (여러개 동시 사용 가능)
예제
mysql > CREATE TABLE test_table (fd1 INT, fd2 INT) ENGINE=INNODB;
- 테이블이 사용할 스토리지 엔진을 지정하면 이후 해당 테이블의 모든 읽기 작업이나 변경 작업은 정의된 스토리지 엔진이 처리한다.
- test_table은 InnoDB 스토리지 엔진을 사용하도록 정의
- test_table에 대해 INSERT, UPDATE, DELETE, SELECT… 등의 작업이 발생하면 InnoDB 스토리지 엔진이 그러한 처리를 담당
- 각 스토리지 엔진은 성능 향상을 위해 키 캐시(MyISAM 스토리지 엔진)나 InnoDB 버퍼 풀(InnoDB 스토리지 엔진)과 같은 기능을 내장하고 있다.
4.1.1.3 핸들러 API
API (Application Programming Interface, 응용 프로그래밍 인터페이스)
MySQL 엔진의 쿼리 실행기에서 데이터를 쓰거나 읽어야 할 때는 각 스토리지 엔진에 쓰기 or 읽기를 요청하는데, 이러한 요청을 핸들러(Handler) 요청이라 하고, 여기서 사용되는 API를 핸들러 API라고 한다.
InnoDB 스토리지 엔진 또한 이 핸들러 API를 이용해 MySQL 엔진과 데이터를 주고 받는다.
SHOW GLOBAL STATUS LIKE 'Handler%';
핸들러 API를 통해 얼마나 많은 데이터(레코드) 작업이 있었는지 확인 가능하다.
4.1.2 MySQL 스레딩 구조
MySQL 서버는 스레드 기반으로 작동(프로세스 기반 X)하며, 크게 포그라운드(Foreground) 스레드와 백그라운드 스레드(Background)로 구분할 수 있다.
mysql > SELECT thread_id, name, type, processlist_user, processlist_test
FROM performance_schema, threads ORDER BY type, thread_id;
MySQL 서버에서 실행 중인 스레드 목록은 다음과 같이 performance_schema 데이터베이스의 threads 테이블을 통해 확인할 수 있다.
동일한 이름의 스레드가 2개 이상씩 보이는 것은 MySQL 서버의 설정 내용에 의해 여러 스레드가 동일 작업을 병렬로 처리하는 경우다.
cf) 스레드(thread) : 프로그램이나 프로세스 내에서 실행되는 흐름의 가장 작은 단위. 스레드는 프로세스 내에서 독립적으로 실행되며, 주로 병렬 처리나 멀티태스킹을 위해 사용된다.
4.1.2.1 포그라운드 스레드(클라이언트 스레드)
포그라운드 스레드 : 클라이언트가 MySQL 서버에 접속하게되면 MySQL서버는 그 클라이언트의 요청을 처리해 줄 스레드를 생성해 그 클라이언트에 할당한다
이 스레드는 DBMS 앞단에서 사용자(클라이언트)와 통신하기 때문에 포그라운드 스레드라고하며, 사용자가 요청한 처리를 하기 때문에 사용자 스레드라고도 한다.
- ⇒ MySQL에서 사용자 스레드와 똑같은 의미로 사용됨
역할 :
- 최소한 MySQL 서버에 접속된 클라이언트 수만큼 존재
- 주로 각 클라이언트 사용자가 요청하는 쿼리 문장을 처리
- 데이터를 MySQL의 데이터 버퍼나 캐시로부터 가져온다.
- 버퍼나 캐시에 없는 경우에는 직접 디스크 데이터나 인덱스 파일로부터 데이터를 읽어와서 작업 처리
작동원리 :
클라이언트 사용자가 작업을 마치고 커넥션을 종료 → 해당 커넥션을 담당하던 스레드는 다시 스레드 캐시(Thread cache)로 되돌아감
- 이때 이미 스레드 캐시에 일정 개수 이상의 대기 중인 스레드가 있으면 → 스레드 캐시에 넣지 않고 스레드를 종료시켜 일정 개수의 스레드만 스레드 캐시에 존재하게 한다.
- 스레드 캐시에 유지할 수 있는 최대 스레드 개수는 thread_cache_size 시스템 변수로 설정
(1) MyISAM 테이블은 디스크 쓰기 작업까지 포그라운드 스레드가 처리하지만(MyISAM도 지연된 쓰기가 있지만 일반적인 방식은 아님)
(2) InnoDB 테이블은 데이터 버퍼나 캐시까지만 포그라운드 스레드가 처리하고, 나머지 버퍼로부터 디스크까지 기록하는 작업은 백그라운드 스레드가 처리한다.
4.1.2.2 백그라운드 스레드
MyISAM의 경우에는 별로 해당 사항이 없는 부분
InnoDB는 다음과 같이 여러 가지 작업이 백그라운드로 처리된다
- 인서트 버퍼(Insert Buffer)를 병합하는 스레드
- 로그를 디스크로 기록하는 스레드 (Log thread)
- InnoDB 버퍼 풀의 데이터를 디스크에 기록하는 스레드 (Write thread)
- 데이터를 버퍼로 읽어 오는 스레드
- 잠금이나 데드락을 모니터링 하는 스레드
write thread : 버퍼의 데이터를 디스크로 쓰기 작업을 처리.
- 아주 많은 작업들을 백그라운드로 처리
- 그렇기에 디스크를 최적으로 사용할 수 있을 만큼 충분히 설정하는 것이 좋다.
사용자 요청을 처리하는 도중 write 작업은 delay되어 처리될 수 있지만,
데이터의 read작업은 절대 delay 될 수 없다.
그렇기에 일반적인 상용 DMBS에는 작업을 버퍼링해서 일괄 처리하는 기능이 탑재되어있다.
- InnoDB 또한 이러한 방식으로 쓰기 작업을 처리
- cf) : MyISAM은 쓰기 버퍼링 기능을 사용할 수 없음
- INSERT, UPDATE, DELETE 쿼리로 데이터가 변경되는 경우 데이터가 디스크 데이터 파일로 완전히 저장될 때까지 기다리지 않아도된다.
- 이외에 인서트 버퍼를 병합하는 스레드, 데이터를 버퍼로 읽어오는 스레드, 데드락이나 잠금을 모니터링하는 스레드 등 다양한 작업들이 백그라운드 스레드에서 처리된다.
아키텍쳐란?
architecture = 구조
소프트웨어나 시스템의 구조와 구성 요소, 그리고 이들 간의 관계를 설명하는데 사용되는 용어
4장에서는 MySQL 데이터베이스 관리 시스템의 내부 구조와 구성 요소들이 어떻게 상호 작용하고 조직되어 있는지 학습합니다.
4.1 MySQL 엔진 아키텍처
다른 DBMS에 비해 구조가 상당히 독특하며, 다른 DBMS에서는 가질 수 없는 엄청난 혜택을 누릴 수 있다. 반대로 다른 DBMS에 문제되지 않을 것들이 가끔 문제가 되기도한다.
4.1.1 MySQL 전체구조
- 일반 상용 RDBMS와 같이 대부분의 프로그래밍 언어로부터 접근 방법을 모두 지원한다.
- 모든 언어로 MySQL 서버에서 쿼리를 사용할 수 있게 지원한다.
- MySQL 서버는 크게 MySQL엔진과 스토리지 엔진으로 구분
- MySQL의 쿼리파서나 옵티마이저 등과 같은 기능을 스토리지 엔진과 구분하고자 ‘MySQL 엔진’, ‘스토리지 엔진’으로 구분
- 그리고 이 둘을 모두 합쳐서 그냥 ‘MySQL’ or ‘MySQL서버’라 부름
4.1.1.1 MySQL 엔진
역할 : 요청된 SQL 문장을 분석하거나 최적화 하는 등 DBMS의 두뇌에 해당하는 처리를 수행 (1개 사용 가능)
구성 : 커넥션 핸들러 + SQL 파서 및 전처리기 + 옵티마이저
- 커넥션 핸들러 : MySQL 엔진은 클라이언트로부터의 접속 및 쿼리 요청
- SQL 파서 및 전처리기
- 옵티마이저 : 쿼리의 최적화된 실행을 위함
- MySQL은 표준 SQL 문법을 지원하기 떄문에 표준 문법에 따라 작성된 쿼리는 타 DBMS와 호환되어 실행될 수 있다.
4.1.1.2 스토리지 엔진
역할 : 실제 데이터를 디스크 스토리지에 저장하거나 디스크 스토리지로부터 데이터를 읽어오는 부분 전담 (여러개 동시 사용 가능)
예제
mysql > CREATE TABLE test_table (fd1 INT, fd2 INT) ENGINE=INNODB;
- 테이블이 사용할 스토리지 엔진을 지정하면 이후 해당 테이블의 모든 읽기 작업이나 변경 작업은 정의된 스토리지 엔진이 처리한다.
- test_table은 InnoDB 스토리지 엔진을 사용하도록 정의
- test_table에 대해 INSERT, UPDATE, DELETE, SELECT… 등의 작업이 발생하면 InnoDB 스토리지 엔진이 그러한 처리를 담당
- 각 스토리지 엔진은 성능 향상을 위해 키 캐시(MyISAM 스토리지 엔진)나 InnoDB 버퍼 풀(InnoDB 스토리지 엔진)과 같은 기능을 내장하고 있다.
4.1.1.3 핸들러 API
API (Application Programming Interface, 응용 프로그래밍 인터페이스)
MySQL 엔진의 쿼리 실행기에서 데이터를 쓰거나 읽어야 할 때는 각 스토리지 엔진에 쓰기 or 읽기를 요청하는데, 이러한 요청을 핸들러(Handler) 요청이라 하고, 여기서 사용되는 API를 핸들러 API라고 한다.
InnoDB 스토리지 엔진 또한 이 핸들러 API를 이용해 MySQL 엔진과 데이터를 주고 받는다.
SHOW GLOBAL STATUS LIKE 'Handler%';
핸들러 API를 통해 얼마나 많은 데이터(레코드) 작업이 있었는지 확인 가능하다.
4.1.2 MySQL 스레딩 구조
MySQL 서버는 스레드 기반으로 작동(프로세스 기반 X)하며, 크게 포그라운드(Foreground) 스레드와 백그라운드 스레드(Background)로 구분할 수 있다.
mysql > SELECT thread_id, name, type, processlist_user, processlist_test
FROM performance_schema, threads ORDER BY type, thread_id;
MySQL 서버에서 실행 중인 스레드 목록은 다음과 같이 performance_schema 데이터베이스의 threads 테이블을 통해 확인할 수 있다.
동일한 이름의 스레드가 2개 이상씩 보이는 것은 MySQL 서버의 설정 내용에 의해 여러 스레드가 동일 작업을 병렬로 처리하는 경우다.
cf) 스레드(thread) : 프로그램이나 프로세스 내에서 실행되는 흐름의 가장 작은 단위. 스레드는 프로세스 내에서 독립적으로 실행되며, 주로 병렬 처리나 멀티태스킹을 위해 사용된다.
4.1.2.1 포그라운드 스레드(클라이언트 스레드)
포그라운드 스레드 : 클라이언트가 MySQL 서버에 접속하게되면 MySQL서버는 그 클라이언트의 요청을 처리해 줄 스레드를 생성해 그 클라이언트에 할당한다
이 스레드는 DBMS 앞단에서 사용자(클라이언트)와 통신하기 때문에 포그라운드 스레드라고하며, 사용자가 요청한 처리를 하기 때문에 사용자 스레드라고도 한다.
- ⇒ MySQL에서 사용자 스레드와 똑같은 의미로 사용됨
역할 :
- 최소한 MySQL 서버에 접속된 클라이언트 수만큼 존재
- 주로 각 클라이언트 사용자가 요청하는 쿼리 문장을 처리
- 데이터를 MySQL의 데이터 버퍼나 캐시로부터 가져온다.
- 버퍼나 캐시에 없는 경우에는 직접 디스크 데이터나 인덱스 파일로부터 데이터를 읽어와서 작업 처리
작동원리 :
클라이언트 사용자가 작업을 마치고 커넥션을 종료 → 해당 커넥션을 담당하던 스레드는 다시 스레드 캐시(Thread cache)로 되돌아감
- 이때 이미 스레드 캐시에 일정 개수 이상의 대기 중인 스레드가 있으면 → 스레드 캐시에 넣지 않고 스레드를 종료시켜 일정 개수의 스레드만 스레드 캐시에 존재하게 한다.
- 스레드 캐시에 유지할 수 있는 최대 스레드 개수는 thread_cache_size 시스템 변수로 설정
(1) MyISAM 테이블은 디스크 쓰기 작업까지 포그라운드 스레드가 처리하지만(MyISAM도 지연된 쓰기가 있지만 일반적인 방식은 아님)
(2) InnoDB 테이블은 데이터 버퍼나 캐시까지만 포그라운드 스레드가 처리하고, 나머지 버퍼로부터 디스크까지 기록하는 작업은 백그라운드 스레드가 처리한다.
4.1.2.2 백그라운드 스레드
MyISAM의 경우에는 별로 해당 사항이 없는 부분
InnoDB는 다음과 같이 여러 가지 작업이 백그라운드로 처리된다
- 인서트 버퍼(Insert Buffer)를 병합하는 스레드
- 로그를 디스크로 기록하는 스레드 (Log thread)
- InnoDB 버퍼 풀의 데이터를 디스크에 기록하는 스레드 (Write thread)
- 데이터를 버퍼로 읽어 오는 스레드
- 잠금이나 데드락을 모니터링 하는 스레드
write thread : 버퍼의 데이터를 디스크로 쓰기 작업을 처리.
- 아주 많은 작업들을 백그라운드로 처리
- 그렇기에 디스크를 최적으로 사용할 수 있을 만큼 충분히 설정하는 것이 좋다.
사용자 요청을 처리하는 도중 write 작업은 delay되어 처리될 수 있지만,
데이터의 read작업은 절대 delay 될 수 없다.
그렇기에 일반적인 상용 DMBS에는 작업을 버퍼링해서 일괄 처리하는 기능이 탑재되어있다.
- InnoDB 또한 이러한 방식으로 쓰기 작업을 처리
- cf) : MyISAM은 쓰기 버퍼링 기능을 사용할 수 없음
- INSERT, UPDATE, DELETE 쿼리로 데이터가 변경되는 경우 데이터가 디스크 데이터 파일로 완전히 저장될 때까지 기다리지 않아도된다.
- 이외에 인서트 버퍼를 병합하는 스레드, 데이터를 버퍼로 읽어오는 스레드, 데드락이나 잠금을 모니터링하는 스레드 등 다양한 작업들이 백그라운드 스레드에서 처리된다.