❤️ AZDIGI chính thức cập nhật hệ thống blog mới hoàn chỉnh. Tuy nhiên có thể một số bài viết bị sai lệch hình ảnh, hãy ấn nút Báo cáo bài viết ở cuối bài để AZDIGI cập nhật trong thời gian nhanh nhất. Chân thành cám ơn.

VPS chậm đột ngột, website load mãi không xong? Có thể disk I/O đang quá tải. Disk I/O (Input/Output) là tốc độ đọc/ghi dữ liệu của ổ cứng. Khi I/O cao, toàn bộ server phải chờ ổ cứng xử lý, làm CPU và RAM dù còn trống cũng không thể hoạt động hiệu quả.

Ổ cứng là phần chậm nhất trong hệ thống. CPU xử lý nano giây, RAM micro giây, nhưng ổ cứng cần mili giây. Khi quá nhiều tiến trình cùng đọc/ghi dữ liệu, ổ cứng thành bottleneck, kéo cả server xuống.

⚠️ Lưu ý: I/O cao không chỉ làm chậm tiến trình đang ghi dữ liệu mà còn block cả những tiến trình khác. Website bạn có thể chạy PHP nhẹ nhàng nhưng vẫn timeout vì MySQL đang chờ ghi log.

Phát hiện I/O cao

Kiểm tra %wa (I/O wait) bằng top

Chạy lệnh top hoặc htop, quan sát cột %wa:

top

Output mẫu:

%Cpu(s):  2.3 us,  0.7 sy,  0.0 ni, 78.2 id, 18.8 wa,  0.0 hi,  0.0 si,  0.0 st
Tasks: 147 total,   2 running, 145 sleeping,   0 stopped,   0 zombie

Ở đây %wa = 18.8% có nghĩa CPU đang chờ I/O 18.8% thời gian. Nếu %wa > 10-20% liên tục, bạn có vấn đề I/O.

Trong htop, tìm thanh màu đỏ hoặc nâu trong biểu đồ CPU. Đó chính là I/O wait.

Sử dụng vmstat để theo dõi

vmstat 1 5

Output mẫu:

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  2      0 451832  89472 1426584    0    0  1247  2891  45   78  3  2 85 10  0
 0  3      0 449216  89472 1428456    0    0  1891  3456  52   82  2  3 82 13  0
 2  1      0 448104  89472 1429832    0    0  2134  4123  59   91  4  3 79 14  0

Chú ý các cột:

  • wa: I/O wait percentage, > 10% là có vấn đề
  • bi: Blocks read from disk (KB/s)
  • bo: Blocks written to disk (KB/s)
  • b: Number of processes blocked waiting for I/O

Nếu cột b luôn có giá trị > 0 và wa cao, I/O đang nghẽn.

Phân tích chi tiết với iostat

iostat -xz 1

Output mẫu:

Device            r/s     w/s     rkB/s     wkB/s   rrqm/s   wrqm/s  %rrqm  %wrqm r_await w_await aqu-sz rareq-sz wareq-sz  svctm  %util
sda              8.23   25.67    156.78    891.23     0.12     4.56   1.44  15.07   12.34   45.67   1.23     19.05     34.72   8.23  67.89
sdb             45.12   12.34   1234.56    456.78     2.34     1.23   4.94   9.07   89.12   234.56   8.45     27.38     37.02  19.45  89.23

Các chỉ số quan trọng:

  • %util: Phần trăm thời gian disk bận, > 80% = bottleneck nghiêm trọng
  • await: Thời gian chờ trung bình (ms), > 20ms trên SSD = chậm bất thường
  • aqu-sz: Trung bình số request đang chờ xử lý, > 2-3 = quá tải

ℹ️ Lưu ý quan trọng: %util có thể misleading trên NVMe vì có thể xử lý song song nhiều operations. Disk NVMe có thể show %util = 100% nhưng vẫn handle thêm request được.

Tìm process gây I/O cao

Dùng iotop

sudo iotop -o

Tham số -o chỉ hiện processes đang có I/O activity.

Output mẫu:

Total DISK READ :       4.56 M/s | Total DISK WRITE :      12.34 M/s
Actual DISK READ:       4.12 M/s | Actual DISK WRITE:      11.89 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
 1234  be/4 mysql        2.34 M/s      8.91 M/s  0.00 % 89.12 % mysqld --defaults-file=/etc/mysql/my.cnf
 5678  be/4 backup       1.89 M/s      2.34 M/s  0.00 % 45.67 % rsync -av /home/ /backup/
 9012  be/4 www-data     0.23 M/s      0.89 M/s  0.00 % 12.34 % php-fpm: pool www

Ở đây MySQL chiếm 89% I/O time với 8.91 MB/s write rate.

Sử dụng pidstat

pidstat -d 1 5

Output mẫu:

Linux 5.4.0-74-generic (web-server)    03/24/2026  _x86_64_    (2 CPU)
11:30:45 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
11:30:46 PM   105      1234    156.78    891.23      0.00      45  mysqld
11:30:46 PM     0      5678    234.56    123.45      0.00      23  rsync
11:30:46 PM    33      9012     23.45     67.89      0.00       8  apache2

Cột iodelay hiển thị tổng thời gian (ticks) process đã bị block vì I/O.

Nguyên nhân phổ biến gây I/O cao

MySQL queries nặng không có index

Database query không tối ưu buộc MySQL scan toàn bộ table, tạo ra read I/O khủng khiếp.

-- Query tệ: scan 1 triệu records
SELECT * FROM users WHERE email LIKE '%@gmail.com';
-- Query tốt: dùng index
SELECT * FROM users WHERE email = 'user@gmail.com';

Kiểm tra slow query log và thêm index cho những query hay chạy:

EXPLAIN SELECT * FROM users WHERE created_at > '2024-01-01';
ALTER TABLE users ADD INDEX idx_created_at (created_at);

Tham khảo: MySQL chậm trên VPS: Nguyên nhân và cách tối ưu

Backup chạy vào giờ cao điểm

Script backup chạy rsync hoặc tar vào lúc website đông người dùng. Backup đọc hàng GB data, ổ cứng không kịp handle cả backup và traffic.

# Bad: backup không giới hạn tốc độ
rsync -av /home/ /backup/

# Better: giới hạn bandwidth rsync -av --bwlimit=10000 /home/ /backup/

# Best: chạy với priority thấp nice -n 19 ionice -c 3 rsync -av /home/ /backup/

Log files ghi liên tục quá lớn

Web server access log, error log, MySQL log ghi liều lớn. Có site traffic cao log vài GB/ngày.

# Kiểm tra log file lớn nhất
find /var/log -type f -exec ls -lh {} \; | sort -k5 -hr | head -10
# Kiểm tra processes đang ghi log nhiều
lsof +D /var/log | grep -v ' 0r'

Cấu hình logrotate để tự động rotate:

# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    missingok
    rotate 7
    compress
    delaycompress
    notifempty
    create 0644 www-data adm
    sharedscripts
    prerotate
        if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
            run-parts /etc/logrotate.d/httpd-prerotate; \
        fi \
    endscript
    postrotate
        invoke-rc.d nginx rotate >/dev/null 2>&1
    endscript
}

Swap thrashing (thiếu RAM)

Server thiếu RAM buộc kernel ghi memory ra swap file trên disk. Mỗi khi cần dữ liệu đã swap, phải đọc lại từ disk, tạo I/O liên tục.

# Kiểm tra swap usage
free -h
# Kiểm tra swap activity
vmstat 1 5
# Cột si (swap in), so (swap out) > 0 = đang swap

Giải pháp: thêm RAM hoặc tối ưu applications để dùng ít memory hơn.

Tham khảo: VPS hết RAM: Cách kiểm tra và giải pháp tăng memory

Noisy neighbor trên shared VPS

VPS chia sẻ physical disk với VPS khác. Nếu VPS cùng node có traffic I/O cao, disk performance của bạn bị ảnh hưởng.

💡 Dấu hiệu: I/O chậm vào giờ cao điểm mặc dù server bạn không load cao. Disk latency tăng đột biến không rõ lý do.

Giải pháp giảm tải I/O

Di chuyển backup sang giờ thấp điểm

Đặt backup chạy 2-3 giờ sáng thay vì giờ hành chính:

# Crontab entry
0 3 * * * nice -n 19 ionice -c 3 /scripts/backup.sh

Thêm nice để giảm CPU priority và ionice để giảm I/O priority.

Cấu hình logrotate tự động

Thiết lập rotate log hàng ngày thay vì chờ log file phình to:

# Kiểm tra logrotate config
logrotate -d /etc/logrotate.conf
# Force rotate ngay
logrotate -f /etc/logrotate.d/nginx

Tối ưu MySQL performance

Enable query cache và thêm indexes:

# Trong my.cnf
query_cache_type = 1
query_cache_size = 256M
innodb_buffer_pool_size = 1G

Phân tích slow queries:

# Enable slow query log
mysql -e "SET GLOBAL slow_query_log = 'ON';"
mysql -e "SET GLOBAL long_query_time = 2;"
# Xem slow queries
mysqldumpslow /var/log/mysql/slow.log | head -10

Thêm RAM để giảm swap

Nâng cấp RAM VPS hoặc tối ưu memory usage:

# Giảm MySQL memory footprint
# Trong my.cnf
[mysqld]
innodb_buffer_pool_size = 512M    # Thay vì 1G
max_connections = 100             # Thay vì 151

Thay đổi I/O scheduler

Linux có nhiều I/O scheduler khác nhau. Scheduler mặc định không phải lúc nào cũng tối ưu.

# Xem scheduler hiện tại
cat /sys/block/sda/queue/scheduler

# Đổi scheduler cho NVMe (không queue, direct access) echo none > /sys/block/nvme0n1/queue/scheduler

# Đổi scheduler cho HDD (deadline scheduling) echo mq-deadline > /sys/block/sda/queue/scheduler

Để permanent, thêm vào /etc/default/grub:

GRUB_CMDLINE_LINUX="elevator=mq-deadline"

Sử dụng tmpfs cho temporary files

Mount RAM disk cho temporary data:

# Thêm vào /etc/fstab
tmpfs /tmp tmpfs defaults,size=1G 0 0
tmpfs /var/tmp tmpfs defaults,size=512M 0 0
# Mount ngay
mount -t tmpfs -o size=1G tmpfs /tmp

⚠️ Lưu ý: dữ liệu trong tmpfs mất khi reboot.

So sánh hiệu năng HDD vs SSD vs NVMe

Loại ổ cứng IOPS (4K random) Latency Sequential Read Sequential Write Giá/GB
HDD 7200 RPM 100-200 5-10ms 150 MB/s 140 MB/s Thấp nhất
SATA SSD 10,000-100,000 0.1-1ms 500 MB/s 450 MB/s Trung bình
NVMe SSD 100,000-1,000,000 0.02-0.1ms 3,500 MB/s 3,000 MB/s Cao nhất

Random I/O (database): NVMe nhanh hơn HDD 500-5000 lần
Sequential I/O (backup): NVMe nhanh hơn HDD 20-25 lần
Latency: NVMe có độ trễ thấp hơn HDD 50-250 lần

Trong thực tế, website WordPress trên NVMe load 2-3 giây, cùng cấu hình trên HDD có thể mất 10-15 giây.

Khi nào nên upgrade?

  • VPS dùng HDD: Upgrade SSD ngay nếu có website database-heavy
  • VPS dùng SSD: Upgrade NVMe nếu có hàng nghìn concurrent users
  • VPS shared storage: Upgrade dedicated NVMe nếu I/O wait > 20%

Lựa chọn VPS NVMe hiệu năng cao

Disk I/O cao không chỉ ảnh hưởng tốc độ website mà còn làm tăng server response time, giảm user experience và SEO ranking. Việc chọn VPS với storage performance tốt là yếu tố then chốt.

AZDIGI cung cấp VPS NVMe RAID-10 với hiệu năng vượt trội:

  • NVMe SSD: Tốc độ đọc/ghi nhanh gấp 20-50 lần so với HDD thường
  • RAID-10: Kết hợp tốc độ của RAID-0 và độ an toàn của RAID-1
  • Dedicated resources: Không share disk với VPS khác, tránh noisy neighbor
  • Backup tự động: Snapshot hàng ngày không ảnh hưởng performance

VPS NVMe RAID-10 đặc biệt phù hợp cho:

  • Website WordPress với database lớn (> 1GB)
  • E-commerce site có nhiều transaction
  • Web application với real-time data processing
  • Development environment cần compile code nhanh

Xem thông tin VPS X-Platinum →

Tại sao %util = 100% có nghĩa ổ cứng đã quá tải?

Không hoàn toàn đúng. Trên HDD cũ, %util = 100% nghĩa là disk chỉ xử lý được 1 request tại 1 thời điểm, vậy 100% = quá tải. Nhưng SSD/NVMe hiện đại có thể xử lý song song hàng trăm requests, nên %util = 100% không có nghĩa quá tải. Chỉ số chính xác hơn là await (latency) và aqu-sz (queue size). Nếu await > 20ms trên SSD hoặc aqu-sz > 10 thì mới thực sự quá tải.

Tại sao VPS 8GB RAM vẫn swap nhiều?

Linux kernel default swappiness = 60, nghĩa là khi RAM usage > 40% đã bắt đầu swap. Điều này không phải vì thiếu RAM mà là kernel strategy để free memory cho file cache. Giảm swappiness xuống 10-20 để ít swap hơn: echo ‘vm.swappiness = 10’ >> /etc/sysctl.conf và sysctl vm.swappiness=10.

iostat hiển thị 0 I/O nhưng server vẫn chậm là do đâu?

Có thể do network I/O (NFS, iSCSI) hoặc memory contention. iostat chỉ monitor local disk, không track network storage. Dùng ‘sar -n DEV 1’ để xem network traffic hoặc ‘sar -r 1’ để xem memory pressure.

Backup tối nay tốn bao nhiêu I/O?

Estimate dựa trên data size. Backup 100GB cần Read I/O: 100GB (đọc data gốc) và Write I/O: 100GB (ghi backup file), total: 200GB I/O trong thời gian backup. Nếu disk bandwidth = 100 MB/s, backup tốn ít nhất 33 phút. Add compression, checksum thì có thể 45-60 phút.

Làm sao biết ổ cứng của mình là HDD hay SSD?

Dùng lệnh ‘lsblk -d -o name,rota’ để kiểm tra. Nếu cột ROTA = 1 là HDD (có đĩa quay), ROTA = 0 là SSD. Hoặc check với ‘cat /sys/block/sda/queue/rotational’ – output 1 = HDD, 0 = SSD.

Chia sẻ:
Bài viết đã được kiểm duyệt bởi AZDIGI Team

Về tác giả

Trần Thắng

Trần Thắng

Chuyên gia tại AZDIGI với nhiều năm kinh nghiệm trong lĩnh vực web hosting và quản trị hệ thống.

Hơn 10 năm phục vụ 80.000+ khách hàng

Bắt đầu dự án web của bạn với AZDIGI