Chuyển tới nội dung chính

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

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.

cảnh báo

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ý

  1. 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.
  2. 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.
mẹo

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