-
[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.1docker-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: 2gdocker-compose down -v docker-compose up -d docker psCONTAINER 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) 구축과 데이터 복제 동작 원리를 중심으로 보다 구체적인 실습 내용을 다룰 예정입니다.
'Database' 카테고리의 다른 글
[MySQL] #2 ProxySQL를 통한 DB Read/Write 분리 및 캐싱 (0) 2026.04.11 [MySQL] #1 Replication(Source/Replica) 구축과 동작 원리 이해 (0) 2026.04.11 [mongodb] MongoDB Docker 설치 및 실습 (1) 2025.05.04 [mongodb] Python에서 MongoDB 연동, 기초 실습 (pymongo) (0) 2025.05.04 [Oracle] Predicate Information - Access, Filter (0) 2024.07.13