ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [MySQL] #0 MySQL HA + ProxySQL + 모니터링 + 자동화 구축기
    Database 2026. 4. 11. 21:00
    시작하며

    데이터베이스를 다루는 업무에 종사하며, 성능에 대해 자주 고민하게 됩니다.

    하나의 SELECT 쿼리가 수행되는데 10분이 소요된다고 가정했을 때, 과연 그 10분이 해당 쿼리의 최소 수행 시간인지, 아니면 튜닝을 통해 더 단축할 수 있는지, 혹은 데이터베이스 엔진의 문제(버그)인지 고민하게 됩니다.

    수많은 트래픽이 몰리는 대규모 서비스에서 쿼리 하나가 1분 늦어지는 차이는 결코 1분으로 끝나지 않습니다.

    동시다발적인 요청이 서로 얽히기 시작하면 전체 처리 시간이 10분, 나아가 1시간 이상으로 확장되는 이른바 ‘스노우볼 현상’이 발생할 수 있기 때문입니다.  

    이처럼 데이터베이스 성능은 곧 서비스 품질과 직결되는 핵심 요소이며, 문제를 빠르게 식별하고 정확하게 분석하는 능력이 매우 중요합니다.

     

    "측정할 수 없으면 관리할 수 없고, 관리할 수 없으면 개선할 수 없다"는 말처럼, 이번 실습에서는 단순한 성능 최적화를 넘어, 장애 상황에서도 서비스가 중단되지 않는 고가용성(HA) 환경을 구축하고, 이를 데이터 기반으로 모니터링하여 문제를 분석하며, 나아가 이러한 과정을 자동화하여 일관성과 재현성을 확보하는 것을 목표로 합니다.

     

    주요 기술 스택

    Database - MySQL

    MySQL은 오픈소스 관계형 데이터베이스로, 이번 실습에서는 Source / Replica 구조를 구성하여 데이터 복제 환경을 구축했습니다.

    • Binary Log 기반 Replication 구조
    • 읽기/쓰기 분리를 위한 기반 구조 제공
    • 고가용성과 확장성을 고려한 아키텍처 구성

    Proxy - ProxySQL

    ProxySQL은 MySQL 앞단에서 동작하는 프록시 서버로, 쿼리를 분석하여 적절한 DB로 라우팅하는 역할을 수행합니다.

    • Read / Write 분리 (SELECT → Replica, INSERT/UPDATE → Source)
    • Query Rule 기반 트래픽 제어
    • 쿼리 캐싱 및 부하 분산

    Monitoring - Percona Monitoring and Management

    PMM은 MySQL을 포함한 데이터베이스의 성능을 분석하기 위한 통합 모니터링 플랫폼입니다.

    • Query Analytics(QAN)를 통한 슬로우 쿼리 분석
    • CPU, Memory, Disk I/O 등 리소스 모니터링
    • 시계열 데이터 기반 성능 변화 분석

    Observability - Prometheus & Grafana

    PMM은 내부적으로 Prometheus와 Grafana를 기반으로 구성되어 있습니다.

    • Prometheus: DB 및 시스템 메트릭을 수집하고 시계열 데이터로 저장
    • Grafana: 수집된 데이터를 시각화하여 대시보드 형태로 제공

    Automation - Ansible

    Ansible은 인프라를 코드로 관리할 수 있도록 도와주는 자동화 도구입니다.

    • Playbook 기반 서버 설정 자동화
    • MySQL 설치 및 Replication 구성 자동화
    • ProxySQL 설정 및 배포 자동화

     

    전체 아키텍처
    [ Client / Application ]
                ↓
            ProxySQL
                ↓
       ┌───────────────┐
       │ MySQL Source  │
       └───────────────┘
                ↓
       ┌───────────────┐
       │ MySQL Replica │
       └───────────────┘
       
    (모니터링) MySQL / OS → Prometheus → Grafana 
                                     ↓ 
                                    PMM
                                    
    (자동화) Ansible → 전체 환경 구성

     

    실습 환경 준비

    docker/docker-compose version

    C:\Users\jihye\docker-lab>docker -v
    Docker version 28.0.1, build 068a01e
    
    C:\Users\jihye\docker-lab>docker-compose -v
    Docker Compose version v2.33.1-desktop.1

     

    docker-compose.yml

    version: '3.8'
    
    services:
      mysql-master:
        image: percona:8.0
        container_name: mysql-master
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: root
        ports:
          - "3307:3306"
        command: >
          --server-id=1
          --log-bin=mysql-bin
          --binlog-format=ROW
          --innodb-buffer-pool-size=512M
          --max-connections=200
          --sync-binlog=1
        mem_limit: 1g
        healthcheck:
          test: ["CMD", "mysqladmin", "ping", "-proot"]
          interval: 10s
          timeout: 5s
          retries: 5
          start_period: 20s
    
      mysql-replica1:
        image: percona:8.0
        container_name: mysql-replica1
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: root
        ports:
          - "3308:3306"
        depends_on:
          - mysql-master
        command: >
          --server-id=2
          --relay-log=relay-bin
          --log-bin=mysql-bin
          --read-only=1
          --innodb-buffer-pool-size=512M
          --max-connections=200
        mem_limit: 1g
        healthcheck:
          test: ["CMD", "mysqladmin", "ping", "-proot"]
          interval: 10s
          timeout: 5s
          retries: 5
          start_period: 20s
    
      mysql-replica2:
        image: percona:8.0
        container_name: mysql-replica2
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: root
        ports:
          - "3309:3306"
        depends_on:
          - mysql-master
        command: >
          --server-id=3
          --relay-log=relay-bin
          --log-bin=mysql-bin
          --read-only=1
          --innodb-buffer-pool-size=512M
          --max-connections=200
        mem_limit: 1g
        healthcheck:
          test: ["CMD", "mysqladmin", "ping", "-proot"]
          interval: 10s
          timeout: 5s
          retries: 5
          start_period: 20s
    
      proxysql:
        image: proxysql/proxysql
        container_name: proxysql
        restart: always
        ports:
          - "6032:6032"
          - "6033:6033"
        depends_on:
          - mysql-master
          - mysql-replica1
          - mysql-replica2
        mem_limit: 512m
    
      pmm-server:
        image: percona/pmm-server:2
        container_name: pmm-server
        restart: always
        ports:
          - "8080:80"
        mem_limit: 2g

     

    docker-compose down -v
    docker-compose up -d
    
    docker ps
    CONTAINER ID   IMAGE                  COMMAND                   CREATED              STATUS                        PORTS                               NAMES
    7b0d91dd2e5d   proxysql/proxysql      "proxysql -f --idle-…"   About a minute ago   Up About a minute             0.0.0.0:6032-6033->6032-6033/tcp    proxysql
    05d2feed7099   percona:8.0            "/docker-entrypoint.…"   About a minute ago   Up About a minute (healthy)   33060/tcp, 0.0.0.0:3309->3306/tcp   mysql-replica2
    83359f24b26e   percona:8.0            "/docker-entrypoint.…"   About a minute ago   Up About a minute (healthy)   33060/tcp, 0.0.0.0:3308->3306/tcp   mysql-replica1
    e5c14efbc166   percona:8.0            "/docker-entrypoint.…"   About a minute ago   Up About a minute (healthy)   33060/tcp, 0.0.0.0:3307->3306/tcp   mysql-master
    bac6495bad5b   percona/pmm-server:2   "/opt/entrypoint.sh"      About a minute ago   Up About a minute (healthy)   443/tcp, 0.0.0.0:8080->80/tcp       pmm-server

     

     

    마무리

    이번 글에서는 프로젝트의 전체적인 방향과 목적을 소개했습니다.

    다음 글에서는 MySQL Replication(Source/Replica) 구축과 데이터 복제 동작 원리를 중심으로 보다 구체적인 실습 내용을 다룰 예정입니다.

Designed by Tistory.