MySQL 5.7 lên 8.0: Lộ trình nâng cấp an toàn và các “hố tử thần” cần tránh

MySQL tutorial - IT technology blog
MySQL tutorial - IT technology blog

Checklist: Nâng cấp MySQL trong 5 phút

Nếu bạn cần một quy trình “mì ăn liền” để áp dụng ngay cho server staging, đây là 5 bước mình đã đúc kết sau hàng chục dự án thực tế:

  1. Quét tương thích: Cài MySQL Shell và chạy util.checkForServerUpgrade(). Đừng bỏ qua bước này nếu bạn không muốn database bị “văng” lỗi khi vừa khởi động 8.0.
  2. Backup thực dụng: Đừng tin vào vận may. Hãy dùng mysqldump --all-databases --routines --events > full_backup.sql để có đường lùi an toàn nhất.
  3. Shutdown sạch: Tắt server 5.7 sau khi đã set innodb_fast_shutdown = 0 để đảm bảo toàn bộ dữ liệu từ Buffer Pool đã được ghi xuống disk.
  4. Thay thế binary: Cài đặt package MySQL 8.0 qua apt hoặc yum.
  5. Theo dõi log: MySQL 8.0 sẽ tự động nâng cấp data dictionary. Bạn chỉ việc ngồi chờ và theo dõi qua lệnh tail -f /var/log/mysql/error.log.

Tại sao phải “chia tay” MySQL 5.7 ngay lúc này?

MySQL 5.7 đã chính thức “nghỉ hưu” (EOL) từ tháng 10/2023. Tiếp tục sử dụng đồng nghĩa với việc hệ thống của bạn sẽ phơi mình trước các lỗ hổng bảo mật mà không còn bản vá nào nữa.

Nhưng lý do thực sự nằm ở hiệu năng. MySQL 8.0 xử lý JSON cực nhanh, hỗ trợ CTE giúp query phức tạp trở nên gọn gàng. Trong một dự án thương mại điện tử mình từng tham gia, việc chuyển lên 8.0 đã giúp các câu lệnh thống kê doanh thu chạy nhanh hơn 30% nhờ tận dụng Window Functions – thứ mà ở bản 5.7 mình phải viết subquery lồng nhau đến phát mệt.

Ba thay đổi “chí mạng” dễ làm sập hệ thống

Nâng cấp không chỉ là bấm nút Update. Có 3 thay đổi lớn về kiến trúc có thể khiến ứng dụng của bạn “đứng hình” ngay lập tức.

1. Chuẩn mã hóa Password mới

Vấn đề: MySQL 8.0 đổi plugin mặc định sang caching_sha2_password. Nếu bạn dùng PHP cũ (dưới 7.4) hoặc Node.js đời đầu, bạn sẽ dính ngay lỗi “Authentication method unknown”.

Giải pháp: Nếu chưa kịp update code, hãy ép MySQL 8.0 quay về kiểu cũ trong file my.cnf:

[mysqld]
default-authentication-plugin=mysql_native_password

Hoặc sửa thủ công cho từng user cụ thể:

ALTER USER 'user_app'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password_cua_ban';

2. Xung đột từ khóa (Reserved Keywords)

Vấn đề: Danh sách từ cấm của MySQL 8.0 vừa kết nạp thêm các từ như GROUPS, RANK, ROW_NUMBER. Nếu bảng của bạn có cột tên là rank mà không bọc trong dấu backtick ( ` ), query sẽ báo lỗi syntax ngay.

Kinh nghiệm xương máu: Mình từng chứng kiến một hệ thống CMS sập hoàn toàn chỉ vì đặt tên cột cấu hình là system. Lên 8.0, toàn bộ module đó chết đứng vì trùng từ khóa hệ thống. Hãy dùng MySQL Shell để quét trước khi quá muộn.

# Lệnh quét nhanh trên MySQL Shell
mysqlsh --user root --execute "util.checkForServerUpgrade()"

3. Khai tử Query Cache

Thực tế: MySQL 8.0 đã loại bỏ hoàn toàn Query Cache. Nếu bạn đang dựa vào bộ cache này để gánh tải cho server yếu, bạn sẽ thấy CPU nhảy từ 20% lên 80% chỉ sau một đêm nâng cấp.

Giải pháp: Đừng cố tìm cách bật lại vì nó không còn tồn tại. Hãy tập trung tối ưu Index hoặc đẩy cache ra ngoài bằng Redis hoặc Memcached.

Quy trình In-Place Upgrade an toàn

Đây là cách mình thường dùng cho các server chạy Ubuntu hoặc CentOS để giảm thiểu rủi ro.

Bước 1: Kiểm tra tiền nâng cấp

Hãy chắc chắn không có bảng nào bị hỏng và không tồn tại kiểu dữ liệu cũ từ thời 5.5. Hãy chạy lệnh kiểm tra tổng thể:

mysqlcheck -u root -p --all-databases --check-upgrade

Bước 2: Cấu hình tắt máy an toàn

Trước khi tắt service, hãy ép MySQL flush toàn bộ dữ liệu đang treo trên bộ nhớ xuống ổ cứng bằng lệnh:

SET GLOBAL innodb_fast_shutdown = 0;

Sau đó mới thực hiện stop service: systemctl stop mysql.

Bước 3: Cài đặt và cấu hình

Trên Ubuntu, bạn chỉ cần cập nhật repository và chạy install. Trong lúc cài, hệ thống sẽ hỏi về cơ chế mật khẩu SHA2. Nếu ứng dụng của bạn đã cũ, hãy chọn Retain MySQL 5.7 Compatibility để tránh lỗi kết nối.

Xử lý lỗi lệch Collation (Bảng cũ vs Bảng mới)

MySQL 8.0 dùng utf8mb4_0900_ai_ci làm mặc định. Nếu dữ liệu cũ của bạn là utf8_general_ci, việc JOIN các bảng giữa cũ và mới sẽ nảy sinh lỗi Collation mismatch.

Khi bảng users đạt ngưỡng 10 triệu row, việc đổi collation cho toàn bộ bảng là một cực hình vì gây lock bảng rất lâu. Kinh nghiệm của mình là: Hãy giữ nguyên collation cũ cho các bảng hiện tại, và chỉ áp dụng chuẩn mới cho các tính năng hoặc bảng mới tạo sau này.

Mẹo nhỏ để tránh “ăn hành”

  • Luôn dùng bản Clone: Hãy clone database ra một server test, chạy thử toàn bộ quy trình nâng cấp trên đó trước khi đụng vào production.
  • Kiểm soát RAM: MySQL 8.0 ngốn thêm khoảng 200MB-500MB RAM chỉ riêng cho Performance Schema. Nếu server chỉ có 1GB-2GB RAM, hãy tắt bớt tính năng này để tránh bị OOM (Out of Memory) killer.
  • Check lại sql_mode: Chế độ ONLY_FULL_GROUP_BY mặc định ở bản 8.0 sẽ khiến các đoạn code PHP cũ viết query GROUP BY sai chuẩn SQL bị lỗi ngay lập tức.

Nâng cấp lên 8.0 là việc sớm muộn cũng phải làm. Chỉ cần bạn cẩn thận ở bước kiểm tra tương thích, bạn đã loại bỏ được 90% rắc rối có thể xảy ra.

Share: