Bối cảnh & Tại sao cần giám sát MySQL chuyên sâu
Bạn đã từng ôm laptop lúc 2 giờ sáng vì ứng dụng dính lỗi 504 Gateway Timeout chưa? Cảm giác gõ vội SHOW PROCESSLIST; mà không biết chuyện gì vừa diễn ra trước đó 5 phút thực sự rất bực bội. Cách xử lý truyền thống thường là bật slow query log hoặc đọc file log thủ công. Cách này vừa chậm, vừa đẩy chúng ta vào thế bị động.
Khi bảng users vượt mốc 10 triệu bản ghi, slow query xuất hiện dồn dập. Đánh thêm index chỉ giải quyết được bề nổi. Bài toán gốc rễ nằm ở tầm nhìn toàn cảnh hạ tầng: InnoDB Buffer Pool còn trống bao nhiêu? Đĩa đang gánh bao nhiêu IOPS? Lượng connection chạm trần max_connections từ lúc nào?
Bộ ba mysqld_exporter + Prometheus + Grafana giải quyết trọn vẹn bài toán đó:
- mysqld_exporter: Service thu thập dữ liệu chạy độc lập cạnh MySQL. Nó truy vấn các bảng trạng thái nội bộ rồi phơi (expose) metric ra cổng HTTP theo format Prometheus.
- Prometheus: Cơ sở dữ liệu time-series định kỳ kéo (pull) dữ liệu từ exporter về lưu trữ, đồng thời liên tục tính toán rule để kích hoạt alert.
- Grafana: Dashboard trực quan hóa, biến hàng triệu dòng số liệu thành biểu đồ trực quan và bắn thông báo tức thì sang Telegram hoặc Slack.
Cài đặt bộ công cụ giám sát
Nguyên tắc số một: tuyệt đối không dùng user root của MySQL cho exporter. Hãy cấp quyền tối thiểu trên một user riêng để hạn chế tối đa rủi ro bảo mật.
1. Tạo user MySQL dành riêng cho mysqld_exporter
Đăng nhập vào MySQL server và chạy script phân quyền:
CREATE USER 'mysqld_exporter'@'127.0.0.1' IDENTIFIED BY 'MatKhauPhucTap@2026' WITH MAX_USER_CONNECTIONS 3;
GRANT PROCESS, REPLICATION CLIENT, SELECT ON performance_schema.* TO 'mysqld_exporter'@'127.0.0.1';
FLUSH PRIVILEGES;
Lưu ý quan trọng: Cờ WITH MAX_USER_CONNECTIONS 3 là chốt chặn an toàn. Dù exporter có bị kẹt query hay treo tiến trình, nó cũng không bao giờ chiếm dụng quá 3 kết nối của ứng dụng chính.
2. Cài đặt mysqld_exporter trên server database
Tải binary trực tiếp từ GitHub repository của Prometheus:
cd /tmp
wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.15.1/mysqld_exporter-0.15.1.linux-amd64.tar.gz
tar -xvf mysqld_exporter-0.15.1.linux-amd64.tar.gz
sudo mv mysqld_exporter-0.15.1.linux-amd64/mysqld_exporter /usr/local/bin/
sudo useradd -rs /bin/false prometheus_exporter
Lưu thông tin đăng nhập vào file cấu hình bảo mật /etc/.mysqld_exporter.cnf:
[client]
user=mysqld_exporter
password=MatKhauPhucTap@2026
host=127.0.0.1
port=3306
Khóa quyền đọc nghiêm ngặt, chỉ cho phép service user truy cập:
sudo chown prometheus_exporter:prometheus_exporter /etc/.mysqld_exporter.cnf
sudo chmod 600 /etc/.mysqld_exporter.cnf
3. Khởi tạo systemd service
Tạo file unit /etc/systemd/system/mysqld_exporter.service:
[Unit]
Description=Prometheus MySQL Exporter
After=network.target mysql.service
[Service]
User=prometheus_exporter
Group=prometheus_exporter
Type=simple
ExecStart=/usr/local/bin/mysqld_exporter \
--config.my-cnf=/etc/.mysqld_exporter.cnf \
--collect.info_schema.innodb_metrics \
--collect.info_schema.processlist \
--collect.global_status \
--collect.global_variables
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Bật service và kiểm tra kết nối:
sudo systemctl daemon-reload
sudo systemctl enable --now mysqld_exporter
# Kiểm tra output metric
curl -s http://localhost:9104/metrics | grep -E '^mysql_up'
Đầu ra hiển thị mysql_up 1 xác nhận exporter đã kết nối vào database thông suốt.
Cấu hình kết nối Prometheus và thiết lập cảnh báo
Khi đầu ra metric đã sẵn sàng, bước tiếp theo là khai báo target thu thập dữ liệu và viết rule phát hiện sự cố trên server Prometheus.
1. Khai báo Job Scrape trong prometheus.yml
Bổ sung cấu hình target vào file /etc/prometheus/prometheus.yml:
scrape_configs:
- job_name: 'mysql_production'
scrape_interval: 15s
scrape_timeout: 10s
static_configs:
- targets: ['192.168.1.50:9104']
labels:
environment: 'production'
cluster: 'core-database'
Kinh nghiệm thực chiến: Chu kỳ scrape_interval: 15s là khoảng thời gian cân bằng nhất. Quét quá dồn dập ở mức 1-2s dễ tạo thêm tải truy vấn metadata lên database, đặc biệt khi hệ thống đang xử lý tải cao.
2. Thiết lập Alert Rules thực tế
Tạo file /etc/prometheus/alert_rules_mysql.yml với các ngưỡng kiểm tra sát sườn:
groups:
- name: mysql_critical_alerts
rules:
# Cảnh báo instance MySQL bị sập
- alert: MySQLInstanceDown
expr: mysql_up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "MySQL instance {{ $labels.instance }} ngừng hoạt động"
description: "Không thể kết nối tới MySQL instance trong hơn 1 phút."
# Cảnh báo connection pool chạm ngưỡng nguy hiểm
- alert: MySQLTooManyConnections
expr: (mysql_global_status_threads_connected / mysql_global_variables_max_connections) * 100 > 85
for: 2m
labels:
severity: warning
annotations:
summary: "MySQL quá tải connection: {{ $value | printf '%.2f' }}%"
description: "Số lượng kết nối đã vượt 85% ngưỡng max_connections cho phép."
# Cảnh báo InnoDB Buffer Pool Hit Ratio quá thấp
- alert: MySQLInnoDBBufferPoolHitRatioLow
expr: 100 - (rate(mysql_global_status_innodb_buffer_pool_reads[5m]) / rate(mysql_global_status_innodb_buffer_pool_read_requests[5m]) * 100) < 95
for: 5m
labels:
severity: warning
annotations:
summary: "Tỉ lệ cache hit của InnoDB thấp: {{ $value | printf '%.2f' }}%"
description: "Hit ratio tụt dưới 95% trong 5 phút. Buffer pool đang thiếu RAM hoặc có query quét toàn bảng liên tục."
Kiểm tra & Giám sát qua Grafana Dashboard
Dữ liệu đã đổ về Prometheus. Giờ là lúc biến chúng thành bảng điều khiển trực quan trên Grafana.
1. Kết nối Data Source và import Dashboard có sẵn
- Truy cập Grafana qua trình duyệt (cổng mặc định
3000). - Vào Connections > Data Sources > Chọn Prometheus > Nhập địa chỉ Prometheus server (ví dụ
http://prometheus-server:9090). - Thay vì tốn thời gian dựng từng panel, hãy vào Dashboards > New > Import, dán ID 7362 (Dashboard cộng đồng phổ biến cho mysqld_exporter) và chọn Data Source vừa tạo.
2. 4 Metric then chốt cần bám sát
Dashboard có hàng chục panel, nhưng khi có sự cố, bạn chỉ cần tập trung vào 4 chỉ số cốt lõi:
- Threads Running vs Threads Connected: Giả sử
threads_connectedđạt 500 nhưngthreads_runningdưới 15, database vẫn an toàn vì đa phần là connection idle từ application pool. Nhưng nếuthreads_runningvượt quá số core CPU (ví dụ server 8 vCPU mà metric này vọt lên 40), hệ thống đang nghẽn do lock hoặc query dồn ứ. - InnoDB Buffer Pool Hit Ratio: Con số này cần duy trì từ 99% trở lên. Nếu tụt xuống 92-94%, dung lượng
innodb_buffer_pool_sizekhông đủ chứa tập dữ liệu nóng (hot data). Database buộc phải đọc từ ổ cứng, khiến disk I/O tăng và latency tăng vọt từ vài mili-giây lên hàng trăm mili-giây. - Queries per Second (QPS) & Questions: Giúp xác định chính xác biểu đồ tải theo giờ. Bạn sẽ biết rõ khung giờ ứng dụng chịu tải cao nhất (ví dụ từ 20h – 22h) để tránh lên lịch cronjob nặng hay chạy script backup vào thời điểm nhạy cảm này.
- InnoDB Log File Syncs: Đo tần suất ghi transaction log (Redo Log) xuống đĩa. Nếu metric này tăng vọt và Disk I/O Queue nhảy vọt, hãy cân nhắc điều chỉnh thông số
innodb_flush_log_at_trx_committừ1sang2(chấp nhận rủi ro mất 1 giây dữ liệu khi server mất điện đột ngột để giảm tải I/O).
3. Thử nghiệm kịch bản báo động thực tế
Muốn biết hệ thống cảnh báo có hoạt động hay không, hãy thử tắt service bằng lệnh sudo systemctl stop mysql trên môi trường staging. Đúng 1 phút sau, mở tab Alerting trên Grafana hoặc Prometheus xem rule MySQLInstanceDown đã chuyển sang trạng thái Firing hay chưa. Nhận được thông báo qua Telegram hoặc Slack đúng như thiết lập, bạn có thể hoàn toàn yên tâm triển khai ra production.
