Hôm qua anh bạn trong team nhắn hỏi: “Server MySQL đang chậm, CPU 80%, mày biết bắt đầu tối ưu từ đâu không?” — Câu hỏi quen thuộc mà mình đã gặp không ít lần. Sau khi thử vài công cụ khác nhau, mình vẫn quay lại MySQLTuner vì nó nhanh, thẳng vào vấn đề, và không đòi hỏi kinh nghiệm DBA sâu.
Vấn đề thực tế: MySQL mặc định không phù hợp với production
Mình nhớ rất rõ lần đầu gặp tình huống này: khi table users vượt 10 triệu row, slow query bắt đầu xuất hiện liên tục, load server tăng cao dù hardware vẫn còn dư tải. Mình phải tối ưu index, nhưng đồng thời mới nhận ra rằng cấu hình MySQL mặc định hoàn toàn không phù hợp với lượng dữ liệu lớn.
File cấu hình mặc định my.cnf được MySQL thiết kế để chạy được trên mọi máy — kể cả máy chỉ có 512MB RAM. Server bạn có 16GB RAM mà MySQL chỉ được dùng 128MB cho InnoDB buffer pool? Đó là lãng phí tài nguyên cực kỳ lớn.
Thay vì ngồi đọc tài liệu rồi tự tính từng thông số, MySQLTuner làm phần việc khó đó cho bạn.
MySQLTuner là gì và hoạt động như thế nào?
Về bản chất, MySQLTuner là script Perl mã nguồn mở. Nó kết nối thẳng vào MySQL đang chạy, đọc số liệu runtime thực tế, rồi trả về danh sách những thông số đang có vấn đề — kèm con số cụ thể bạn nên set.
Điểm mạnh khiến mình dùng nó thường xuyên:
- Không cần cài thêm package phức tạp — Perl có sẵn trên hầu hết Linux
- Chạy trực tiếp trên server đang live, phân tích dữ liệu uptime thực tế
- Output có màu sắc rõ ràng:
[OK]xanh là tốt,[!!]đỏ là cần xem xét - Đưa ra giá trị cụ thể nên set, không chỉ nói chung chung “cần tăng lên”
Không thay thế được DBA chuyên nghiệp. Nhưng 10–15 phút chạy MySQLTuner thường tìm ra 2–3 điểm nghẽn lớn nhất mà bạn có thể fix ngay trong ngày.
Cài đặt và chạy MySQLTuner
Cách 1: Tải script trực tiếp từ GitHub
# Tải MySQLTuner về máy
wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl
# Cấp quyền thực thi
chmod +x mysqltuner.pl
# Chạy với thông tin đăng nhập MySQL
perl mysqltuner.pl --user root --pass yourpassword
Cách 2: Cài qua package manager (Ubuntu/Debian)
sudo apt install mysqltuner -y
# Chạy trực tiếp
mysqltuner
Nếu muốn kết quả chi tiết hơn, thêm flag --verbose:
perl mysqltuner.pl --user root --pass yourpassword --verbose
Lưu ý quan trọng: MySQLTuner phân tích dữ liệu từ thống kê uptime thực tế. Nếu MySQL vừa mới restart, kết quả sẽ không chính xác vì chưa đủ dữ liệu. Tốt nhất hãy chạy sau khi server đã hoạt động ít nhất 24–48 giờ dưới tải thực tế.
Đọc hiểu kết quả MySQLTuner
Phần General Statistics
-------- General Statistics ------------------------------------------
[OK] Currently running supported MySQL version 8.0.32
[OK] Operating on 64-bit architecture
[!!] Uptime = 2d 3h 14m (should be > 7 days for accurate data)
Dòng [OK] màu xanh là ổn. Dòng [!!] màu đỏ là cần chú ý. Uptime dưới 7 ngày thì kết quả chỉ mang tính tham khảo.
Phần Performance Metrics
-------- Performance Metrics -----------------------------------------
[--] Reads / Writes: 84% / 16%
[!!] Thread cache is disabled
[!!] Table cache hit rate: 11% (400 open / 3K opened)
[OK] Temporary tables created on disk: 12% (2K on disk / 20K total)
[OK] Open file limit used: 0% (36/65K)
Đây là phần quan trọng nhất. Nhìn vào ví dụ trên, hai vấn đề hiện ra ngay:
- Thread cache đang tắt — mỗi connection mới sẽ tạo thread mới, rất tốn tài nguyên khi có nhiều connection ngắn
- Table cache hit rate chỉ 11% — MySQL phải liên tục mở/đóng file descriptor vì
table_open_cachequá thấp
Phần Recommendations — đọc kỹ nhất
-------- Recommendations ---------------------------------------------
General recommendations:
Enable the slow query log to troubleshoot bad queries
Set thread_cache_size to 4 as a starting point
Variables to adjust:
thread_cache_size (> 0)
table_open_cache (> 400)
innodb_buffer_pool_size (>= 5G) if possible.
innodb_log_file_size should be (= 512M)
Con số cụ thể luôn có sẵn — đây là phần bạn sẽ copy thẳng vào my.cnf.
Áp dụng các gợi ý tối ưu vào cấu hình
Trước khi sửa bất cứ thứ gì, mình luôn backup config:
sudo cp /etc/mysql/mysql.conf.d/mysqld.cnf \
/etc/mysql/mysql.conf.d/mysqld.cnf.bak.$(date +%Y%m%d)
echo "Backup xong, bắt đầu chỉnh sửa..."
Tối ưu InnoDB Buffer Pool — quan trọng nhất
[mysqld]
# Set khoảng 70–80% RAM nếu MySQL là ứng dụng chính trên server
# Server 16GB RAM → set 12G
innodb_buffer_pool_size = 12G
# Nếu buffer pool > 1G, nên dùng nhiều instance để giảm contention
innodb_buffer_pool_instances = 4
# Tăng log file size để giảm I/O checkpoint
innodb_log_file_size = 512M
Tối ưu connections và cache
[mysqld]
# Thread cache — tái sử dụng thread thay vì tạo mới mỗi connection
thread_cache_size = 16
# Tăng table cache để giảm việc mở/đóng file liên tục
table_open_cache = 2000
table_definition_cache = 1400
# Bộ nhớ temp table trong RAM — giảm disk I/O khi sort/group
tmp_table_size = 128M
max_heap_table_size = 128M
Save file xong, restart MySQL và kiểm tra service có lên lại không:
sudo systemctl restart mysql
sudo systemctl status mysql
# Kiểm tra các biến đã được áp dụng chưa
mysql -u root -p -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
Đợi ít nhất 48 giờ để thu thập đủ dữ liệu thống kê, rồi chạy lại MySQLTuner để xem số [!!] đã giảm bao nhiêu.
Một số điều cần lưu ý
- Không áp dụng mù quáng: MySQLTuner gợi ý dựa trên thống kê hiện tại. Nếu traffic bất thường hoặc server vừa restart, kết quả có thể lệch so với thực tế.
- Thay đổi từng bước nhỏ: Đừng sửa 10 thông số cùng lúc. Ưu tiên InnoDB buffer pool trước, test vài ngày, rồi mới tiếp tục các thứ khác.
- Theo dõi sau khi thay đổi: Dùng
SHOW STATUS LIKE 'Innodb_buffer_pool%'để kiểm tra hiệu quả thực tế — đặc biệt chú ýInnodb_buffer_pool_reads(càng thấp càng tốt). - innodb_buffer_pool_size là tối quan trọng: Nếu chỉ được sửa một thứ, hãy sửa cái này. Phần lớn hiệu năng MySQL đến từ việc data nằm trong RAM thay vì phải đọc từ disk.
Kết luận
Workflow mình thường áp dụng: chạy MySQLTuner → ghi lại tất cả dòng [!!] → tìm hiểu ý nghĩa từng cái → áp dụng theo thứ tự ưu tiên (InnoDB buffer pool trước, rồi đến connection settings) → đợi 48h → chạy lại để verify tiến độ.
MySQLTuner không trị được mọi bệnh — khi config đã tuning tốt mà slow query vẫn còn, bước tiếp theo là đào vào từng câu SQL với EXPLAIN và query profiling. Nhưng cấu hình đúng là nền tảng cần có trước, không có nó thì tối ưu query cũng chỉ đi được nửa đường.

