

Khi vận hành MySQL trong môi trường production, chúng ta thường quen thuộc với các hệ thống giám sát như Grafana, Prometheus (mysqld_exporter), Datadog hay các công cụ GUI như DBeaver, MySQL Workbench. Tuy nhiên, khi xảy ra sự cố hoặc database bị treo không phản hồi, công cụ nhanh nhất, nhẹ nhất và cứu cánh đầu tiên của DBA luôn là MySQL Client qua terminal.
Dưới đây là 10 nhóm câu lệnh và kỹ thuật thiết yếu nhất khi bạn phải xử lý sự cố MySQL.
Khi ứng dụng báo lỗi Too many connections hoặc response time tăng đột biến, điều đầu tiên cần làm là kiểm tra xem ai đang làm gì trên database.
SHOW FULL PROCESSLIST;Mẹo: Thêm FULL để xem trọn vẹn câu lệnh truy vấn thay vì chỉ thấy 100 ký tự đầu tiên.
Nếu muốn lọc và sắp xếp chi tiết hơn bằng SQL, hãy truy vấn bảng processlist trong information_schema hoặc performance_schema:
SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO
FROM information_schema.PROCESSLIST
WHERE COMMAND != 'Sleep'
ORDER BY TIME DESC;Các thông tin quan trọng cần đọc:
Các câu lệnh quét Full Table Scan trên bảng hàng chục triệu dòng có thể kéo sập CPU và làm nghẽn toàn bộ luồng xử lý khác.
Để lọc ngay những query đang chạy quá 30 giây:
SELECT
id, user, host, db, time, state, info
FROM information_schema.processlist
WHERE command = 'Query' AND time > 30
ORDER BY time DESC;Nếu server đã bật sys schema (mặc định từ MySQL 5.7.7+), bạn có view rất trực quan:
SQL
SELECT * FROM sys.processlist
WHERE command != 'Sleep'
ORDER BY exec_time DESC;Khi đã xác định được ID (PID) của query chạy hàng nghìn giây làm đứng hệ thống, bạn cần giải phóng tài nguyên ngay lập tức.
(Hỗ trợ từ MySQL 8.0)
KILL QUERY 12345;Lệnh này chỉ dừng thực thi truy vấn đó nhưng giữ lại kết nối TCP của client, hạn chế việc ứng dụng bị văng kết nối đột ngột.
Đóng hoàn toàn kết nối (Connection Kill)
KILL 12345;-- hoặc chỉ định rõ:
KILL CONNECTION 12345;Lệnh này sẽ rollback transaction đang dở dang và ngắt phiên làm việc của ID đó.
Nhiều trường hợp CPU và RAM hoàn toàn rảnh rỗi nhưng API phía backend vẫn timeout hàng loạt. Nguyên nhân kinh điển là Row Lock Contention (nhiều transaction tranh chấp nhau một tài nguyên).
SHOW ENGINE INNODB STATUS\GLưu ý: Dùng \G để format kết quả theo chiều dọc dễ đọc. Hãy cuộn đến các mục:
Từ MySQL 5.7+, bạn có thể xác định ngay session nào đang chặn session nào mà không cần tự parse text:
SELECT * FROM sys.innodb_lock_waits\GKết quả sẽ chỉ rõ:
Một transaction mở ra (START TRANSACTION) nhưng quên COMMIT hoặc do code xử lý logic bên ngoài quá lâu sẽ sinh ra các vấn đề nghiêm trọng: giữ undo log, làm phình file ibdata1, và ngăn dọn dẹp MVCC (Multi-Version Concurrency Control).
Truy vấn tìm transaction "treo":
SELECT
trx_id,
trx_mysql_thread_id AS pid,
trx_state,
TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS duration_sec,
trx_query,
trx_rows_locked,
trx_rows_modified
FROM information_schema.innodb_trx
ORDER BY duration_sec DESC;Nếu một transaction có duration_sec lên đến hàng nghìn giây và trx_query là NULL (nghĩa là nó đang nhàn rỗi nhưng chưa commit), hãy dùng KILL <trx_mysql_thread_id> để ép rollback.
Khi ổ cứng sắp đầy (Disk Usage 90%+), bạn cần định vị ngay bảng nào đang ngốn dung lượng để lên phương án dọn dẹp hoặc archive.
SELECT
table_schema AS database_name,
table_name,
ROUND((data_length + index_length) / 1024 / 1024, 2) AS total_size_mb,
ROUND(data_length / 1024 / 1024, 2) AS data_size_mb,
ROUND(index_length / 1024 / 1024, 2) AS index_size_mb
FROM information_schema.tables
WHERE table_schema NOT IN ('information_schema', 'sys', 'performance_schema', 'mysql')
ORDER BY (data_length + index_length) DESC
LIMIT 15;Truy vấn này bóc tách rõ: dung lượng đến từ dữ liệu thật hay do đánh quá nhiều index thừa.
Nếu server chứa nhiều database hoặc chia sẻ chung cho nhiều microservice:
SELECT
table_schema AS database_name,
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb,
ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS size_gb
FROM information_schema.tables
WHERE table_schema NOT IN ('information_schema', 'sys', 'performance_schema', 'mysql')
GROUP BY table_schema
ORDER BY SUM(data_length + index_length) DESC;Trong mô hình Master-Slave (hoặc Primary-Replica), sự cố phổ biến nhất là Replica bị dừng do lỗi dữ liệu hoặc bị trễ (lag) so với Primary, khiến ứng dụng đọc dữ liệu cũ.
Trên máy Replica:
-- Dành cho MySQL 8.0.22+
SHOW REPLICA STATUS\G-- Dành cho phiên bản cũ hơn:
SHOW SLAVE STATUS\GNhững dòng sống còn cần soi kỹ:
Nếu MySQL liên tục đọc trực tiếp từ ổ cứng thay vì bộ nhớ, hệ thống sẽ chậm đi cả trăm lần.
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';Để tính nhanh hiệu quả bộ nhớ đệm (Hit Rate):
Hit Rate (%)=(1-Innodb_buffer_pool_reads/Innodb_buffer_pool_read_requests)×100Nếu con số này xuống dưới 99%, có thể kích thước innodb_buffer_pool_size đang được cấp phát quá nhỏ so với working dataset của bạn.
PostgreSQL có lệnh \watch, còn trong thế giới MySQL, công cụ đi kèm mysqladmin là giải pháp giám sát thời gian thực cực kỳ nhẹ và không cần cài thêm package.
Chạy trực tiếp từ shell (Bash/Zsh):
mysqladmin -u root -p extended-status -i 1 -r | grep -E "Questions|Queries|Threads_connected|Threads_running"watch -n 1 'mysql -u root -p"password" -e "SHOW PROCESSLIST;"'Màn hình terminal sẽ tự làm mới sau mỗi giây, cho phép bạn quan sát luồng xử lý như một dashboard mini khi đang triển khai hotfix hoặc chống chọi đợt traffic spike.
Kết luận: Nắm vững các lệnh MySQL CLI giúp DBA nhanh chóng xác định nguyên nhân và xử lý sự cố ngay cả khi các công cụ giám sát hoặc GUI không khả dụng. Đây là bộ công cụ quan trọng để kiểm tra query, lock, transaction, replication và tài nguyên database trực tiếp trên terminal.
