Monitoring

Monitoring database cần nhìn vào những chỉ số nào trước?

Thứ tự theo dõi database từ góc nhìn ứng dụng, query latency, connection, lock, slow query và tài nguyên đến backup hoặc replication.

Các chỉ số monitoring database
Mục lục

Khi mở bảng điều khiển của MySQL hay MariaDB, bạn sẽ dễ bị choáng ngợp trước hàng trăm biến trạng thái (Status Variables) khác nhau: từ Innodb_buffer_pool_reads, Key_blocks_unused đến đủ loại tỷ lệ hit cache. Rất nhiều tài liệu khuyên bạn nên theo dõi tỷ lệ cache hit của bộ đệm đĩa hoặc giữ CPU ở mức thấp.

Nhưng trong thực tế vận hành, một cơ sở dữ liệu có tỷ lệ cache hit 99% và CPU chỉ 10% vẫn có thể đang làm sập toàn bộ website.

Điều này xảy ra khi các tiến trình ứng dụng đang xếp hàng chờ mòn mỏi vì cạn kiệt connection pool, hoặc một câu lệnh cập nhật dữ liệu đang giữ khóa (lock) trên một bảng quan trọng khiến hàng chục request khác bị treo cứng. CPU thấp lúc đó không phải vì database đang khỏe, mà vì nó đang phải dừng lại chờ giải phóng tài nguyên.

Để việc giám sát database thực sự có ích khi gặp sự cố, bạn không nên xem các biến số một cách ngẫu nhiên. Hãy quan sát theo đúng thứ tự 6 lớp từ ngoài vào trong:

1. Góc nhìn từ ứng dụng: Ứng dụng có đang nói chuyện được với database không?

Rất nhiều người chỉ kiểm tra xem tiến trình MySQL có đang chạy trên cổng 3306 không. Nhưng tiến trình đang chạy không đồng nghĩa với việc ứng dụng đọc ghi được dữ liệu.

Tín hiệu quan trọng nhất phải đo từ chính ứng dụng web:

  • Thời gian chờ lấy kết nối (Connection Pool Wait Time): Ứng dụng mất bao nhiêu mili-giây để mượn được một kết nối từ pool? Nếu con số này vọt lên vài giây, ứng dụng sẽ phản hồi chậm rì dù bản thân câu query sau đó chạy rất nhanh.
  • Tỷ lệ lỗi cơ sở dữ liệu: Bao nhiêu % request của khách hàng bị trả về mã lỗi 500 do không kết nối được database hoặc bị query timeout?
  • Lệnh kiểm tra sức khỏe (Healthcheck): Một lệnh SELECT 1 chỉ chứng minh kết nối TCP còn sống. Nó không đảm bảo quyền ghi dữ liệu còn nguyên vẹn hay các bảng nghiệp vụ có bị hỏng hay không.

Nếu ứng dụng kêu lỗi kết nối liên tục nhưng database server lại báo hoàn toàn nhàn rỗi, vấn đề thường nằm ở cấu hình pool của ứng dụng hoặc độ trễ mạng nội bộ, chứ không phải do cơ sở dữ liệu bị quá tải.

2. Lưu lượng, tỷ lệ lỗi và độ trễ câu truy vấn

Cơ sở dữ liệu là trái tim của hệ thống xử lý trực tuyến. Bạn cần nắm được 3 nhịp đập cơ bản:

  • Tốc độ xử lý (Query Rate / QPS): Số lượng câu truy vấn được xử lý mỗi giây. Nhìn vào biểu đồ này sẽ giúp bạn nhận ra ngay: đợt lỗi này xảy ra do lượng truy cập tăng đột biến (traffic vọt lên gấp 5 lần), hay do một lần cập nhật code mới vô tình kích hoạt vòng lặp gọi hàng trăm câu query thừa thãi cho mỗi lượt tải trang.
  • Độ trễ câu truy vấn (Query Latency): Hãy nhìn vào các phân vị như P95 hoặc P99 thay vì nhìn con số trung bình. Một câu lệnh trả lỗi trong 5 ms (vì lỗi cú pháp) cũng được tính vào độ trễ trung bình và có thể kéo con số trung bình trông "nhanh hơn", trong khi các câu query lấy giỏ hàng thực tế đang mất tới 4 giây.
  • Tỷ lệ lỗi (Error Rate): Tách bạch rõ các loại lỗi: lỗi do sai thông tin đăng nhập, lỗi chạm ngưỡng timeout, hay lỗi deadlock (hai giao dịch tranh chấp khóa nhau và bị hệ thống hủy bỏ).

3. Quản lý kết nối (Connection): Đừng vội tăng max_connections

Đây là nơi 80% các website quy mô nhỏ gặp sự cố đầu tiên: khách hàng truy cập thấy văng lỗi "Too many connections".

Hai chỉ số bạn cần phân biệt rõ ràng:

  • Tổng số kết nối đang mở (Threads_connected): Số lượng kết nối mà ứng dụng đã thiết lập và đang giữ. Phần lớn trong số này có thể đang ở trạng thái ngủ (Sleep) chờ việc.
  • Số kết nối đang thực sự chạy (Threads_running): Số lượng tiến trình đang thực sự chiếm CPU và đĩa để thực thi câu lệnh SQL. Nếu chỉ số này vọt lên cao (vài chục trên một máy chủ 2-4 core), hệ thống đang rơi vào tình trạng quá tải nghiêm trọng vì tranh chấp tài nguyên.

Khi gặp lỗi hết kết nối, phản xạ đầu tiên của nhiều người là mở file my.cnf và nâng max_connections từ 150 lên 500 hoặc 1.000.

Đây là một quyết định rất nguy hiểm. Mỗi kết nối được tạo ra trong MySQL đều chiếm dụng một lượng bộ nhớ RAM riêng (bộ đệm sắp xếp, bộ đệm kết nối). Nâng số kết nối tối đa lên quá cao trên một VPS có RAM khiêm tốn sẽ dẫn tới tình trạng cạn kiệt RAM hệ thống, kích hoạt cơ chế OOM Killer và làm sập luôn toàn bộ tiến trình database.

Nguyên nhân gốc rễ của việc cạn kết nối thường không phải do giới hạn quá thấp, mà do code ứng dụng giữ kết nối quá lâu mà không trả lại pool, hoặc do có những câu truy vấn bị nghẽn làm ứ đọng toàn bộ hàng đợi phía sau.

4. Khóa bảng (Lock Wait) và Truy vấn chậm (Slow Query)

Khi website chậm mà CPU máy chủ vẫn dưới 20%, thủ phạm gần như luôn nằm ở hàng đợi khóa (Lock) hoặc câu truy vấn chậm (Slow Query).

Khóa giao dịch (Lock Wait) và Bế tắc (Deadlock)

Khi một giao dịch đang thực hiện lệnh UPDATE trên một dòng dữ liệu mà chưa COMMIT, các giao dịch khác muốn sửa dòng đó sẽ phải đứng chờ (Lock Wait). Nếu thời gian chờ này vượt quá ngưỡng cấu hình (innodb_lock_wait_timeout), câu lệnh phía sau sẽ bị hủy với thông báo lỗi timeout.

Tệ hơn, nếu Giao dịch A giữ dòng 1 chờ dòng 2, trong khi Giao dịch B giữ dòng 2 chờ dòng 1, hiện tượng Deadlock sẽ xảy ra. Bạn cần theo dõi số lượng deadlock phát sinh theo thời gian. Nếu sau một đợt cập nhật tính năng mới mà tỷ lệ deadlock tăng vọt, đội ngũ phát triển cần rà soát lại thứ tự cập nhật dữ liệu trong mã nguồn.

Theo dõi Slow Query có kiểm soát

Biến đếm Slow_queries cho bạn biết có bao nhiêu câu truy vấn chạy vượt quá ngưỡng thời gian long_query_time.

Tuy nhiên, đừng bao giờ bật ghi log toàn bộ câu lệnh (General Query Log) trên máy chủ chạy thực tế. Việc ghi lại từng câu SQL sẽ làm nghẽn ổ đĩa và nuốt trọn dung lượng máy chủ trong thời gian ngắn. Thay vào đó, hãy chỉ bật Slow Query Log với ngưỡng thời gian hợp lý (ví dụ: các câu query chạy trên 1 đến 2 giây) để gom đúng danh sách các câu lệnh thiếu index hoặc quét toàn bộ bảng (Full Table Scan).

Để hiểu cách phối hợp log truy vấn chậm này với các loại dữ liệu khác khi xử lý sự cố, bạn có thể xem bài Log, metric và uptime check khác nhau ở điểm nào?.

5. Tài nguyên máy chủ và Ổ đĩa: Bẫy cạn đĩa ngầm

Cơ sở dữ liệu tiêu thụ tài nguyên phần cứng theo cách rất đặc thù:

  • Bộ nhớ RAM: MySQL sử dụng InnoDB Buffer Pool để lưu dữ liệu và index trên RAM. Vì vậy, việc tiến trình MySQL chiếm 60%–70% tổng RAM của VPS là hành vi bình thường và đáng mừng. Điều bạn cần theo dõi không phải là lượng RAM MySQL đang giữ, mà là chỉ số MemAvailable của hệ điều hành và việc VPS có bị ghi đọc Swap hay không (xem bài Ngưỡng cảnh báo CPU, RAM và Disk cho VPS).
  • Dung lượng Ổ đĩa: Database không chỉ phình to do dữ liệu người dùng nạp vào. Nó còn sinh ra các file nhật ký nhị phân (Binary Logs / Binlogs), file log giao dịch (Redo/Undo logs), và các bảng tạm (Temporary Tables) được ghi xuống đĩa khi câu query thực hiện sắp xếp dữ liệu lớn. Khi ổ đĩa chạm mức 100%, MySQL sẽ lập tức dừng hoạt động và từ chối khởi động lại cho tới khi có khoảng trống.

Khi gặp tình huống lạ lùng là hệ thống phản hồi rất ì ạch nhưng CPU hiển thị rất thấp, bạn có thể tham khảo quy trình phân tích tại bài Website chậm nhưng CPU thấp: Nên kiểm tra gì tiếp theo?.

6. Trạng thái sao lưu (Backup) và Nhân bản (Replication)

Nếu hệ thống của bạn có sử dụng cụm máy chủ phụ (Read Replica) để chia tải đọc, hai chỉ số bắt buộc phải theo dõi là:

  1. Tiến trình nhân bản có đang chạy không: Các thread đọc và ghi log replication có bị ngắt kết nối không.
  2. Độ trễ nhân bản (Replication Lag): Bản sao đang đi chậm hơn máy chủ chính bao nhiêu giây. Nếu lag lên tới vài phút, khách hàng vừa đăng ký tài khoản xong sẽ không thể đăng nhập được ngay nếu request đọc bị điều hướng sang máy chủ phụ.

Đối với hoạt động sao lưu, hãy cài đặt cảnh báo dựa trên tiêu chí: Thời điểm tạo bản backup thành công gần nhất là lúc nào? Nếu đã quá 26 giờ mà không có file backup mới nào được ghi nhận, hệ thống phải phát cảnh báo ngay để tránh tình trạng script cron bị lỗi ngầm mà không ai hay biết.

Chi tiết cách lên lịch và kiểm tra tính toàn vẹn của file sao lưu được hướng dẫn tại bài Chiến lược backup VPS cho doanh nghiệp nhỏ. Để đặt các chỉ số database này vào một khung giám sát chung với CPU, RAM, dung lượng và uptime của máy chủ, bạn nên tham khảo bài trụ cột Nên monitoring những gì trên một VPS chạy website?. Nếu cơ sở dữ liệu bị sập hoặc từ chối khởi động sau sự cố, hãy xem thứ tự chẩn đoán an toàn tại bài MySQL hoặc MariaDB không khởi động: thứ tự kiểm tra an toàn.

Checklist theo dõi Database cho VPS nhỏ

  • ☐ Ứng dụng có ghi nhận thời gian chờ lấy kết nối từ pool và tỷ lệ lỗi truy vấn database.
  • ☐ Đo lường độ trễ câu truy vấn theo phân vị P95/P99, không dùng độ trễ trung bình.
  • ☐ Phân biệt số kết nối đang mở (Threads_connected) và số kết nối đang thực thi (Threads_running).
  • ☐ Không tự ý tăng max_connections bừa bãi khi chưa kiểm tra dung lượng RAM của VPS.
  • ☐ Đã bật Slow Query Log với ngưỡng thời gian hợp lý (1–2 giây) và có cấu hình tự động dọn dẹp file log.
  • ☐ Theo dõi tỷ lệ Deadlock và thời gian chờ khóa bảng sau mỗi đợt deploy tính năng mới.
  • ☐ Đặt cảnh báo dung lượng ổ đĩa từ sớm để tránh việc binlog hoặc bảng tạm làm đầy đĩa cứng đột ngột.
  • ☐ Có cảnh báo kiểm tra sự tồn tại của bản backup mới mỗi ngày.

Chia sẻ bài viết hữu ích

Gửi bài viết này cho đồng nghiệp

Đọc tiếp

Bài nên đọc tiếp

Xem tất cả bài về Monitoring