1. 스레드 풀의 필요성

MySQL 서버는 멀티스레드 프로그램이다.

 

서버로 요청이 들어올 때마다 배정되는 포그라운드 스레드도 있고

계속 돌고있는 백그라운드 스레드도 있다.

 

그런데 스레드가 너무 많아지면 성능이 떨어진다.

갑자기 요청이 천개가 들어왔다고 해서 스레드를 천개나 만들어버리면, 컨텍스트 스위칭 관련 비용이 커져서 시스템 성능이 저하된다.

(자세한 문제점은 [스레드가 너무 많으면 성능이 저하되는 이유와 해결 방법] 참고)

 

그래서 멀티스레드 프로그램들은 스레드 풀(thread pool)을 이용해서  스레드의 갯수를 제한 한다.

 

2. 스레드 풀 원리

서버는 요청이 들어올 때마다 새 스레드를 생성하는 대신, 스레드 풀에게 작업을 위임한다.

 

스레드 풀은 놀고있는 스레드가 생기면 작업을 스레드에 할당하여 실행되도록 한다.

작업은 내부적으로 큐에 저장되며, 쓰레드 풀의 쓰레드들은 여기서 작업을 빼서 실행한다. 큐에 새로운 작업이 들어오면 놀고 있는 쓰레드가 큐에서 작업을 빼서 실행한다. 이를 두고 쓰레드에 작업이 할당되었다고 하며, 작업이 할당되지 않은 쓰레드들은 큐에 새 작업이 들어올 때까지 대기 상태로 유지된다. 3)

 

예를들어, 스레드풀의 스레드 갯수를 10개로 정해놨다면

갑자기 요청이 100개 들어왔을 때

처음 10개의 요청에 대해서는 스레드를 배정하고 나머지는 큐에다 넣어서 대기시킨다.

 

3. MySQL - Percona Server

MySQL 서버 엔터프라이즈 에디션은 스레드 풀 기능이 내장되어있지만

MySQL 커뮤니티 에디션에서 스레드 풀 기능을 쓰려면 플러그인을 설치해야한다.

책 Real MySQL 8.0 에서는 Percona Server라는 스레드 풀 플러그인을 소개하고 있다.

 

MySQL 서버에 스레드 풀을 설치하기만 하면 무조건 성능이 올라가는게 아니다. 스레드풀로 성능을 높이려면 셋팅을 잘 해줘야 한다.

 

♣ thread_pool_size 시스템 변수

스레드그룹의 갯수를 조정한다.

(스레드 그룹에 대해서는 바로 다음에 나오는 thread_pool_oversubscribe 설명 참고.

보통 스레드그룹은 한번에 한개의 active 스레드를 갖는다.)

일반적으로 이 값을 CPU 코어 갯수와 맞추는 것이 CPU 프로세서 친화도를 높이는데 좋다.

 

 thread_pool_oversubscribe

한개의 스레드 그룹 안에서 몇개의 스레드까지

동시에 active 상태일 수 있게할 것인지.

디폴트 값은 3이다.

 

스레드 그룹은 보통 한번에 한개의 active 스레드를 갖는데,

만약 타이머 스레드가 지연(stall)을 감지하면 스레드 그룹에 active 스레드를 추가할수 있다.

 

thread_pool_oversubscribe 변수 값이 너무 크면

스케줄링해야 할 스레드가 많아져서 스레드풀이 비효율적으로 작동할 수도 있다.

(자세한 내용은 [MariaDB 스레드 풀 시스템 및 상태변수] 의 thread_pool_oversubsribe 설명 참고)

 

 thread_pool_stall_limit

스레드 그룹은 보통 한번에 한개의 active 스레드를 갖는데

만약 타이머 스레드가 지연(stall)을 감지하면 스레드 그룹에 active 스레드를 추가할수 있다고

앞에서 설명했다.

 

만약 모든 스레드 그룹들이 각자 스레드를 처리하는 중이라면

새로운 작업이 있을 때 큐에서 대기시킬지, 아니면 스레드 그룹들 중 하나에 추가시킬지를 정해야한다.

 

이것을 정하는 것은 타이머 스레드이다.

 

타이머 스레드는 주기적으로 스레드 그룹들의 상태를 체크한다.

 

어떤 스레드 그룹의 active 스레드가

thread_pool_stall_limit 시간안에 작업을 끝내지 못하면

타이머 스레드는 지연(stall)이 일어났다고 보고

해당 그룹에 새로운 스레드를 생성해서 추가한다.

  • 응답시간에 민감한 서비스라면 이 변수 값을 적절히 낮춰서 설정해야한다.
    왜냐하면, 스레드의 갯수가 최대일 때 (바로 다음에 설명할 thread_pool_max_threads 갯수에 도달했을 때)
    이 스레드 작업은 최소한 thread_pool_stall_limit 시간만큼 대기해야 한다.
    이 값이 크면 자리가 났는데도 괜히 좀 더 기다리게 될 수 있다.
  • 하지만 이 값을 0에 가까운 값으로 설정하는 것은 권장하지 않는다.
    이럴바엔 스레드 풀을 사용하지 않는 편이 낫다고 함.

 thread_pool_max_threads

전체 스레드 풀에 있는 스레드 갯수의 최댓값.

스레드 총 갯수는 이 값을 절대 넘을 수 없다.

 

- ppt -

4. Percona Server 선순위, 후순위 큐를 이용한 작업 순서 재배치

Percona Server의 스레드 풀 플러그인은 선순위 큐와 후순위 큐를 이용해 특정 트랜잭션이나 쿼리를 우선적으로 처리할 수 있는 기능도 제공한다.

 

그림을 통해 이해해보자.

아래 그림은 사용자로부터 요청이 유입된 순서이다.

아래는 Percona Server의 스레드 풀에서 지원하는 선순위 큐와 후순위 큐를 이용해 재배치한 작업의 순서이다.

 

 

작업 순서를 재배치함으로써 트랜잭션들이 최대한 빨리 종료될 수 있게 한다.

 


참고

1

Real MySQL 8.0 (백은빈, 이성욱)

2

스레드가 너무 많으면 성능이 저하되는 이유와 해결 방법

https://www.codeguru.com/cplusplus/why-too-many-threads-hurts-performance-and-what-to-do-about-it/

3

쓰레드 풀(Thread Pools)

https://parkcheolu.tistory.com/30

4

MariaDB 스레드 풀 시스템 및 상태변수 (thread_pool_size, thread_pool_oversubscribe)

https://runebook.dev/ko/docs/mariadb/thread-pool-system-and-status-variables/index

5

하드웨어 스레드와 소프트웨어 스레드

https://juneyr.dev/thread

6

멀티코어 프로그래밍에서 흔히 발생하는 문제 1부

https://andromedarabbit.net/멀티코어-프로그래밍에서-흔히-발생하는-문제-1부/

 

+ Recent posts