MySQL
Trang này tập hợp những sự cố MySQL được báo nhiều nhất trên FPT Database Engine, kèm dấu hiệu nhận biết và các bước xử lý. Dùng để tự chẩn đoán, hoặc để thu thập thông tin mà FPT Support cần.
Mỗi mục theo cùng một bố cục: dấu hiệu, nguyên nhân, ảnh hưởng, rồi cách xử lý.
Các sự cố đã biết
- Backup thất bại và yêu cầu chạy OPTIMIZE TABLE
- MySQL crash với composite index trên cột JSON
- Metadata lock storm trên các node slave
Backup thất bại và yêu cầu chạy OPTIMIZE TABLE
Dấu hiệu
Một backup job MySQL thất bại và gửi email thông báo dạng:
cluster_id : abcxyz11
cluster_name : clustername
vdc_name : ABCXYZ_VCD
org_name : ABCXYZ-ORG
start_time : 10/23/2055 00:30:02
backup_type : diff
backup_size : NoneG
backup_log : ERROR: Please run OPTIMIZE TABLE on all listed tables to fix this issue. Tables found: db/transactions...
backup_state : failed
created_at : 10/23/2055 00:31:01
Nguyên nhân là một bug trong Percona XtraBackup, phần mềm FPT Cloud dùng để backup database FPT Database Engine.
Nguyên nhân
Từ MySQL 8.0.29 trở đi, InnoDB hỗ trợ INSTANT ADD/DROP COLUMN. Thao tác INSTANT không sao chép bảng và không dựng lại bảng. Nó chỉ ghi metadata vào InnoDB dictionary, biểu hiện qua TOTAL_ROW_VERSIONS > 0.
XtraBackup chưa tương thích hoàn toàn với bảng mang metadata đó, nên không xử lý được bất kỳ bảng nào đã dùng INSTANT ADD/DROP COLUMN. Backup job dừng lại và yêu cầu bạn chạy OPTIMIZE TABLE.
Ảnh hưởng
- Hiệu năng truy vấn giảm, vì dữ liệu không còn được tổ chức tối ưu.
- Tải hệ thống tăng, tiêu tốn tài nguyên và bộ nhớ.
- Thao tác INSERT và UPDATE chậm hơn.
- Bảng bị phân mảnh làm chậm cả backup lẫn phục hồi.
Cách xử lý
Dựng lại bảng bị ảnh hưởng để xóa metadata INSTANT:
OPTIMIZE TABLE db.transactions;
Sau khi hoàn tất, bảng được dựng lại toàn bộ, metadata phiên bản cột INSTANT biến mất, TOTAL_ROW_VERSIONS trở về 0, và backup chạy bình thường trở lại.
OPTIMIZE TABLE dựng lại toàn bộ bảng và có thể giữ WRITE lock. Trên bảng lớn, việc dựng lại chạy rất lâu, nên hãy đặt lịch ngoài giờ cao điểm và xác nhận còn đủ dung lượng tạm trước khi chạy.
MySQL crash với composite index trên cột JSON
Dấu hiệu
Một node MySQL crash khi truy vấn dùng composite index dựng trên cột JSON:
22:20:45 UTC - mysqld got signal 11 ;
Most likely, you have hit a bug, but this error can also be caused by malfunctioning hardware.
...
Query (407ad76b1830): SELECT `fort_knox_funds_flows`.* FROM `fort_knox_funds_flows`
WHERE (25830440 MEMBER OF(`fort_knox_funds_flows`.`money_movements` ->> "$[*].to_user_id")
OR 25830440 MEMBER OF(`fort_knox_funds_flows`.`money_movements` ->> "$[*].from_user_id"))
ORDER BY `fort_knox_funds_flows`.`created_at` DESC LIMIT 20
Đây là bug của chính MySQL. Xem báo cáo đầy đủ tại MySQL bug 109542.
Nguyên nhân
Từ MySQL 8.0.2x trở đi, một bảng có định nghĩa INDEX tham chiếu tới các trường bên trong cột JSON có thể làm crash server. MySQL không tạo và duy trì index trên cột JSON một cách tin cậy:
- Nó không xử lý đúng object JSON bên trong composite index, gây lỗi bộ nhớ hoặc lỗi xử lý bất đồng bộ.
- Nó không tối ưu được cách dữ liệu JSON được lưu và đọc trong composite index.
- Các tính năng lưu trữ như Full Disk Encryption có thể làm lỗi nghiêm trọng hơn.
Ảnh hưởng
MySQL crash hoặc khởi động lại không báo trước. Trong một số trường hợp database không phục hồi được dữ liệu sau đó, ảnh hưởng trực tiếp tới tính khả dụng và độ tin cậy trên production.
Cách xử lý
- Dùng index đơn cột thay vì composite index khi có cột JSON tham gia.
- Tránh index trực tiếp lên cột JSON. Khi cần, hãy tạo một generated column từ giá trị JSON rồi index cột đó.
- Nâng cấp lên bản MySQL mới hơn như 8.0.42, nơi bug này đã được sửa.
Metadata lock storm trên các node slave
Dấu hiệu
Trên database MySQL HA, node master đọc ghi bình thường, nhưng độ trễ replication trên hai node slave tăng vọt, lên tới khoảng hai giờ. Nhiều thread trên node slave nằm ở trạng thái Waiting for table metadata lock:
1073 admin 10.225.65.36:25680 fpt Query 178 Waiting for table metadata lock SELECT COUNT(1) AS `cnt` FROM `user_notifications` ...
1075 admin 10.225.65.36:25694 fpt Query 178 Waiting for table metadata lock SELECT COUNT(1) AS `cnt` FROM `user_notifications` ...
...
Tình trạng này xuất hiện sau một câu lệnh DDL chạy trên bảng đó, đẩy các node slave vào metadata lock storm.
Nguyên nhân
MySQL dùng metadata lock (MDL) để bảo vệ cấu trúc bảng ở mức schema và mức bảng trong lúc câu lệnh DDL và DML chạy.
Trong MySQL InnoDB Cluster, các transaction DDL được replicate như ALTER TABLE, CREATE INDEX và DROP TABLE được applier thread áp dụng tuần tự trên node slave. Nếu một session người dùng vẫn đang giữ MDL lock, do một truy vấn chạy lâu hoặc một câu DML chưa commit, applier thread phải chờ.
Khi applier thread không lấy được lock kịp thời, các transaction còn lại trong Global Replication Queue xếp hàng phía sau. Applier thread đứng im, mọi thread chạm tới bảng đó cũng đứng theo, và node slave gần như không còn phục vụ được ứng dụng.
Ảnh hưởng
Truy vấn và transaction bị chặn, việc truy cập dữ liệu bị gián đoạn, độ trễ hệ thống tăng. Transaction replication đứng lại, tạo ra độ trễ replication và làm giảm hiệu năng trên toàn database.
Cách xử lý
- Tạm dừng các ứng dụng và dịch vụ đang chạm tới bảng mà câu lệnh DDL nhắm vào. Việc này ngăn truy vấn mới lấy hoặc xếp hàng chờ metadata lock.
- Khởi động lại các node slave để giải phóng thread đang giữ lock. Khởi động lại kết thúc các session đang kẹt để DDL áp dụng được.
Trước khi chạy DDL trên bảng có QPS cao, hãy ngắt các ứng dụng đang dùng bảng và index mà câu lệnh đó ảnh hưởng. Cách này tránh được lock storm ngay từ đầu và giữ cho thay đổi không làm gián đoạn database.
Bước tiếp theo
- Giám sát database với FMON để phát hiện sớm các dấu hiệu này
- Cấu hình lịch backup
- Xem Action Log