Tối ưu MySQL cho VPS ít RAM hiệu quả

SSH vào VPS 2GB RAM, gõ free -h thấy MySQL ngốn gần hết bộ nhớ, truy vấn chậm dần rồi có lúc bị treo. Đây là tình huống quen thuộc khi cài MySQL theo cấu hình mặc định lên VPS cấu hình thấp. Bài này mình sẽ hướng dẫn cách tối ưu MySQL cho VPS ít RAM, tập trung vào MySQL 8.0 trên Ubuntu 24.04 LTS, nhưng các tham số vẫn áp dụng được cho MariaDB và các bản phân phối Linux khác.
Mục tiêu không phải là ép MySQL chạy nhanh hơn phần cứng cho phép, mà là để nó dùng đúng lượng RAM bạn có, không bị hệ điều hành kill vì thiếu bộ nhớ, và giữ hiệu năng ổn định cho cả web server lẫn database trên cùng một máy.
Yêu cầu trước khi bắt đầu
- VPS chạy Ubuntu 24.04 LTS hoặc Debian 12, đã cài sẵn MySQL 8.0 (
mysql --versionđể kiểm tra). - Quyền sudo hoặc root để sửa file cấu hình và restart dịch vụ.
- Biết đường dẫn file cấu hình chính:
/etc/mysql/mysql.conf.d/mysqld.cnf(Ubuntu/Debian) hoặc/etc/my.cnf(AlmaLinux/Rocky). - Xác định RAM khả dụng của VPS: chạy
free -mđể xem tổng RAM và RAM còn trống.
Nếu bạn đang thuê VPS Linux cấu hình thấp, việc nắm các tham số dưới đây sẽ giúp bạn chủ động hơn khi cài đặt và vận hành database.
Vì sao MySQL mặc định ngốn RAM?
MySQL 8.0 mặc định cấu hình cho máy chủ chuyên dụng, không phải VPS nhỏ. Tham số innodb_buffer_pool_size mặc định khoảng 128MB, nhưng các buffer khác như innodb_log_buffer_size, performance_schema (bật mặc định từ MySQL 5.7), và số connection pool mỗi thread đều chiếm RAM. Trên VPS 2GB, sau khi hệ điều hành, Nginx, PHP-FPM và MySQL cùng chạy, RAM sẽ nhanh chóng cạn kiệt.
Hệ quả là kernel phải dùng swap liên tục, database chậm rõ rệt, thậm chí bị OOM killer giết process. Vấn đề không phải MySQL "xấu", mà là nó được cấu hình cho một môi trường khác với môi trường bạn đang chạy.
Bước 1 - Đo RAM thực tế và xác định đúng tham số cần chỉnh
Trước khi sửa gì, hãy đo lượng RAM MySQL đang dùng và xem cấu hình hiện tại. Lệnh free -h cho tổng quan, mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';" cho giá trị cụ thể của từng tham số.
free -h
mysql -u root -p -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
Trên VPS 2GB, mình thường đặt innodb_buffer_pool_size = 512M, tức khoảng 25-30% tổng RAM. Đây là vùng nhớ chứa data và index thường xuyên truy cập, nên đây là tham số ảnh hưởng lớn nhất đến hiệu năng. Đặt quá cao sẽ khiến MySQL chiếm gần hết RAM, để lại quá ít cho Nginx và PHP-FPM. Đặt quá thấp thì mỗi truy vấn phải đọc từ đĩa, chậm hơn rất nhiều.
Dưới đây là bảng giá trị gợi ý theo RAM VPS, áp dụng cho MySQL 8.0 trên Ubuntu 24.04:
| RAM VPS | innodb_buffer_pool_size | key_buffer_size | max_connections |
|---|---|---|---|
| 1GB | 256M | 16M | 50 |
| 2GB | 512M | 32M | 100 |
| 4GB | 1G | 64M | 200 |
Lưu ý bảng trên là điểm khởi đầu an toàn, không phải công thức cứng nhắc. Nếu VPS của bạn chạy WordPress, bạn cần để dư RAM cho PHP-FPM; nếu chỉ chạy database thuần, có thể tăng buffer pool lên thêm một chút.
Bước 2 - Chỉnh file cấu hình mysqld.cnf
Sửa file cấu hình chính của MySQL. Trên Ubuntu 24.04, file nằm tại /etc/mysql/mysql.conf.d/mysqld.cnf. Mở bằng nano hoặc vim với quyền sudo:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
Trong phần [mysqld], thêm hoặc chỉnh các dòng sau. Đây là bộ tham số mình dùng cho VPS 2GB:
[mysqld]
# Bộ nhớ chính cho InnoDB
innodb_buffer_pool_size = 512M
innodb_log_buffer_size = 8M
innodb_buffer_pool_instances = 1
# Giới hạn kết nối và thread
max_connections = 100
thread_cache_size = 8
performance_schema = OFF
# MyISAM (nếu có bảng cũ dùng engine này)
key_buffer_size = 32M
# Giới hạn sort và join buffer
sort_buffer_size = 2M
join_buffer_size = 2M
read_buffer_size = 1M
read_rnd_buffer_size = 1M
# Tắt query cache (đã loại bỏ hoàn toàn trong MySQL 8.0)
# Không cần thêm dòng query_cache_type nữa
Giải thích nhanh các tham số quan trọng:
innodb_buffer_pool_instances = 1: với buffer pool 512MB, chỉ cần 1 instance. Nhiều instance chỉ hữu ích khi buffer pool lớn hơn vài GB.performance_schema = OFF: vô hiệu hóa performance schema, tiết kiệm khoảng 200-300MB RAM trên MySQL 8.0. Bạn sẽ mất dữ liệu giám sát chi tiết, nhưng với VPS nhỏ thì đánh đổi này đáng giá. Bật lại khi cần debug sâu.thread_cache_size = 8: số thread cache để tái sử dụng, giảm chi phí tạo thread mới mỗi lần kết nối.- Các buffer
sort_buffer_size,join_buffer_size,read_buffer_sizechỉ cấp phát mỗi lần cần, nhưng nếu đặt quá cao, mỗi kết nối có thể chiếm thêm vài MB, nhân với số kết nối sẽ thành con số lớn.
Một điểm quan trọng: query_cache đã bị loại bỏ hoàn toàn trong MySQL 8.0. Nếu bạn tìm thấy hướng dẫn cũ nói bật query cache, hãy bỏ qua. Trên MariaDB 10.6 trở lên cũng vậy, query cache bị vô hiệu hóa mặc định.
Sau khi sửa xong, kiểm tra cú pháp cấu hình rồi restart MySQL:
sudo mysqld --validate-config
sudo systemctl restart mysql
sudo systemctl status mysql
Lệnh mysqld --validate-config sẽ báo lỗi nếu bạn gõ sai tên biến hoặc giá trị không hợp lệ. Output mong đợi là không có thông báo lỗi, sau đó service chuyển sang trạng thái active (running).
Bước 3 - Xử lý swap để tránh OOM
VPS RAM thấp gần như bắt buộc phải có swap. Swap không làm MySQL nhanh hơn, nhưng là lớp đệm để hệ điều hành không vội giết process khi RAM đầy. Kiểm tra swap hiện tại:
free -h | grep -i swap
sudo swapon --show
Nếu chưa có swap hoặc quá nhỏ, tạo file swap 2GB trên Ubuntu 24.04:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Đồng thời chỉnh tham số vm.swappiness để kernel không lạm dụng swap khi RAM còn trống. Giá trị 10 là hợp lý cho VPS chạy database:
sudo sysctl vm.swappiness=10
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
Lưu ý: swap chỉ là giải pháp tình thế. Nếu MySQL thường xuyên phải đọc từ swap, hiệu năng sẽ tệ. Lúc đó bạn nên cân nhắc nâng cấp lên VPS có RAM lớn hơn hoặc tối ưu query cho đỡ tốn tài nguyên.
Bước 4 - Kiểm tra và tinh chỉnh sau khi chạy
Sau khi restart, kiểm tra lại mức RAM MySQL đang dùng và xem các biến đã được áp dụng chưa:
mysql -u root -p -e "SHOW VARIABLES WHERE Variable_name IN ('innodb_buffer_pool_size','max_connections','performance_schema');"
ps aux | grep mysqld | grep -v grep
Lệnh ps aux cho thấy RSS (RAM thực tế) của tiến trình mysqld. Nếu mức RAM giảm rõ so với trước khi chỉnh, bạn đã đi đúng hướng.
Tiếp theo, theo dõi số kết nối thực tế để xem max_connections = 100 có phù hợp không:
mysql -u root -p -e "SHOW STATUS LIKE 'Max_used_connections';"
Nếu con số này thấp hơn 100 nhiều (ví dụ chỉ 20-30), bạn có thể giảm max_connections xuống 50 hoặc 60 để tiết kiệm thêm RAM. Nếu nó gần chạm 100, hãy tăng lên nhưng nhớ rằng mỗi kết nối có thể chiếm vài MB RAM.
Ngoài ra, hãy theo dõi slow query log. Đây là cách hàng đầu để biết truy vấn nào đang chậm và cần tối ưu thay vì tăng RAM mù quáng. Bật slow query log trong cùng file mysqld.cnf:
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2
Mọi truy vấn chạy trên 2 giây sẽ được ghi vào file log. Kiểm tra định kỳ file này bằng lệnh sudo tail -f /var/log/mysql/mysql-slow.log sẽ cho bạn biết truy vấn nào cần thêm index hoặc viết lại.
Xử lý lỗi thường gặp
Trong quá trình tinh chỉnh, bạn có thể gặp vài lỗi phổ biến sau đây.
Lỗi 1: MySQL không restart được sau khi sửa cấu hình
Kiểm tra log lỗi ngay lập tức:
sudo tail -100 /var/log/mysql/error.log
Lỗi hay gặp là sai tên biến (ví dụ gõ innodb_buffer_pool_siz thiếu chữ e) hoặc giá trị không hợp lệ. Đọc kỹ dòng báo lỗi, sửa lại và chạy sudo mysqld --validate-config lần nữa trước khi restart.
Lỗi 2: MySQL bị kill đột ngột (OOM)
Nếu VPS hết RAM và kernel giết mysqld, kiểm tra bằng sudo journalctl -k | grep -i oom. Cách xử lý: giảm tiếp innodb_buffer_pool_size xuống 384M hoặc 256M, tắt performance_schema nếu chưa tắt, và giảm max_connections. Đồng thời xem lại Nginx và PHP-FPM có đang cấu hình quá nhiều worker không.
Lỗi 3: Truy vấn vẫn chậm dù đã chỉnh buffer pool
Buffer pool chỉ giúp khi dữ liệu nóng nằm được trong RAM. Nếu database của bạn lớn hơn RAM nhiều lần, chưa chắc đã có lỗi cấu hình. Chạy EXPLAIN trên các truy vấn chậm, kiểm tra index bằng SHOW INDEX FROM table_name;, và xem slow query log. Nhiều khi thêm một index còn hiệu quả hơn tăng gấp đôi RAM.
Câu hỏi thường gặp
MySQL 8.0 trên VPS 1GB RAM có chạy được không?
Chạy được nhưng phải tinh chỉnh kỹ. Đặt innodb_buffer_pool_size = 256M, tắt performance_schema, giới hạn max_connections = 50, và tạo swap 1-2GB. Kỳ vọng hiệu năng ở mức chấp nhận được cho website nhỏ, không phải cho ứng dụng có lượng truy cập lớn.
Vì sao MySQL của tôi vẫn dùng nhiều RAM hơn con số buffer pool?
Buffer pool chỉ là phần RAM lớn nhất, nhưng MySQL còn dùng RAM cho connection thread, sort buffer, join buffer, InnoDB log buffer và các cấu trúc nội bộ khác. Nếu performance_schema bật, nó có thể ngốn thêm vài trăm MB. Vì vậy, RAM thực tế của mysqld thường cao hơn buffer pool từ 20-40%.
Tôi có nên dùng MariaDB thay MySQL để nhẹ hơn không?
MariaDB là lựa chọn hợp lý cho VPS RAM thấp vì nó có nhiều tham số tinh chỉnh tương tự và thường dùng ít RAM hơn trong cùng một tác vụ. Tuy nhiên, nếu ứng dụng của bạn đã phát triển trên MySQL, việc chuyển đổi không đáng để làm chỉ vì lý do RAM. Bạn có thể tham khảo thêm bài về tối ưu MariaDB cho VPS RAM thấp nếu muốn tìm hiểu lựa chọn này.
Chỉnh buffer pool xuống thấp có làm mất dữ liệu không?
Không. innodb_buffer_pool_size chỉ là vùng đệm trong RAM, không phải nơi lưu trữ dữ liệu lâu dài. Giảm giá trị này chỉ làm tăng số lần đọc từ đĩa, khiến truy vấn có thể chậm hơn, nhưng không gây mất dữ liệu. Thay đổi này không cần dump hay backup lại database.
Bài viết liên quan
- Tối ưu MySQL, MariaDB buffer pool, index, slow query log
- Cấu hình swap và tối ưu bộ nhớ cho VPS RAM thấp
- Chọn RAM và CPU cho n8n theo số workflow thực tế
- Tối ưu MariaDB cho VPS RAM thấp trên Ubuntu 24.04


