คำตอบสั้น ๆ: วางแผนอัปเกรดเป็น MySQL 8 จากรุ่น 5.7 ตรวจด้วย util.checkForServerUpgrade ทดสอบบนเครื่องใหม่ มีแผนย้อนกลับ และหลักการเดียวกันสำหรับ MariaDB 10.x
คู่มือนี้อธิบาย MySQL 8 ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
การอัปเกรดเป็น MySQL 8 จากรุ่น 5.7 ไม่ใช่การอัปเดตแพ็กเกจธรรมดา เพราะมีการเปลี่ยนแปลงที่ทำให้แอปเดิมเชื่อมต่อไม่ได้หรือทำให้เซิร์ฟเวอร์ไม่ยอมเริ่มทำงาน เช่นปลั๊กอินยืนยันตัวตนเริ่มต้นตัวใหม่ ชุดอักขระเริ่มต้นที่เปลี่ยนเป็น utf8mb4 และตัวเลือกที่ถูกถอดออก ที่สำคัญที่สุดคือการอัปเกรดแบบ in-place ย้อนกลับไม่ได้ MySQL 5.7 หมดการสนับสนุนไปตั้งแต่ปี 2023 และ MySQL 8.0 หมดการสนับสนุนในเดือนเมษายน 2026 ปลายทางระยะยาวจึงควรเป็น MySQL 8.4 LTS
คู่มือนี้ใช้แนวทางที่ปลอดภัยที่สุดบนคลาวด์ คือสร้าง Cloud Server เครื่องใหม่ ย้ายข้อมูลไปทดสอบจนมั่นใจ แล้วจึงสลับแอป โดยเครื่องเดิมยังอยู่ครบเป็นแผนย้อนกลับ ท้ายคู่มือมีหลักการเดียวกันสำหรับผู้ที่ใช้ MariaDB 10.x
สิ่งที่ต้องเตรียม
- รุ่นปัจจุบันของเซิร์ฟเวอร์ ตรวจด้วย
SELECT VERSION();และไฟล์คอนฟิกที่ใช้อยู่ - Cloud Server เครื่องใหม่ที่ใช้ Ubuntu 24.04 สเปกใกล้เคียงหรือสูงกว่าเครื่องเดิม และพื้นที่ดิสก์เผื่อไฟล์ dump
- MySQL Shell (คำสั่ง mysqlsh) รุ่น 8.4 ขึ้นไป ติดตั้งจาก MySQL APT Repository ของ Oracle
- ข้อมูลสำรองที่กู้คืนได้จริง ดู คู่มือ mysqldump
- รายชื่อแอปทั้งหมดที่เชื่อมต่อฐานข้อมูล พร้อมรุ่นของภาษาและไดรเวอร์ เช่น PHP 7.4 ขึ้นไปจึงรองรับ caching_sha2_password
Oracle ไม่รองรับการข้ามซีรีส์ LTS เส้นทางที่ถูกต้องคือ 5.7 ไป 8.0 แล้วจึงไป 8.4 และระวังว่าการอัปเกรด Ubuntu 18.04 เป็น 20.04 ด้วย do-release-upgrade จะอัปเกรด MySQL 5.7 เป็น 8.0 ไปพร้อมกันโดยอัตโนมัติ ต้องทำตามคู่มือนี้ให้เสร็จก่อน
ขั้นตอนที่ 1: สำรวจระบบเดิมและสำรองข้อมูล
mysql -u root -p -e "SELECT VERSION(); SELECT user, host, plugin FROM mysql.user;"
mysqldump -u root -p --databases appdb shopdb --single-transaction --routines --triggers --events > /backup/apps-57.sql
dump ชุดนี้คือหลักประกันสุดท้าย เก็บไว้นอกเครื่องด้วย สังเกตคอลัมน์ plugin ของผู้ใช้ทุกคนซึ่งน่าจะเป็น mysql_native_password ทั้งหมด และจดค่า character_set_server, collation_server และ sql_mode ของเครื่องเดิมไว้ เพื่อใช้ตั้งบนเครื่องใหม่ให้พฤติกรรมเหมือนเดิม
ขั้นตอนที่ 2: ตรวจความเข้ากันได้กับ MySQL 8 ด้วย Upgrade Checker
MySQL Shell มีเครื่องมือ util.checkForServerUpgrade ที่ตรวจเซิร์ฟเวอร์ 5.7 ว่ามีอะไรจะพังเมื่อขึ้นรุ่นใหม่ ผู้ใช้ที่รันต้องมีสิทธิ์ PROCESS และ SELECT
mysqlsh -- util checkForServerUpgrade root@localhost:3306 --target-version=8.0.43 --config-path=/etc/mysql/mysql.conf.d/mysqld.cnf
ท้ายรายงานมีสรุปสามบรรทัด Errors ต้องแก้ก่อนอัปเกรดทุกข้อ Warnings ควรแก้แต่ไม่บล็อกการอัปเกรด Notices เป็นข้อมูลประกอบ ใส่ --config-path ด้วยเสมอ เพราะเครื่องมือจะตรวจตัวเลือกในไฟล์คอนฟิกที่ถูกถอดออกในรุ่นใหม่ได้ด้วย
ขั้นตอนที่ 3: แก้สิ่งที่เปลี่ยนไปใน MySQL 8
- คำสงวนใหม่ เช่น RANK, ROWS, GROUPS และ WINDOW ถ้ามีคอลัมน์ชื่อเหล่านี้ ให้ครอบชื่อด้วยเครื่องหมาย backtick ทุก Query เช่น
SELECT `rank` FROM products;หรือเปลี่ยนชื่อคอลัมน์ - ตัวเลือกที่ถูกถอดออก ลบ query_cache_type และ query_cache_size ออกจากคอนฟิก และเอา NO_AUTO_CREATE_USER ออกจาก sql_mode ถ้าจะไปต่อ 8.4 ต้องลบ default_authentication_plugin และเปลี่ยน expire_logs_days เป็น binlog_expire_logs_seconds ด้วย
- คำสั่งที่เลิกใช้ สคริปต์ที่ใช้
GRANT ... IDENTIFIED BYสร้างผู้ใช้จะล้มเหลว ต้องเปลี่ยนเป็น CREATE USER ก่อนแล้วค่อย GRANT - ชุดอักขระ ตารางใหม่จะใช้ utf8mb4_0900_ai_ci ถ้าตารางเดิมใช้ collation อื่น ให้ตั้ง collation_server บนเครื่องใหม่ให้ตรงกับของเดิม หรือแปลงทั้งระบบตาม คู่มือแปลงเป็น utf8mb4
รัน Upgrade Checker ซ้ำจน Errors เป็น 0 ก่อนไปขั้นตอนถัดไป
ขั้นตอนที่ 4: เตรียมเครื่องใหม่และย้ายข้อมูลด้วย MySQL Shell
บนเครื่องใหม่ ติดตั้ง MySQL 8.0 แล้วตรวจรุ่นที่ได้ด้วย apt policy mysql-server ใส่ค่า collation_server และ sql_mode ที่จดไว้ลงคอนฟิก จากนั้น dump จากเครื่องเดิมด้วย MySQL Shell ซึ่งรวมบัญชีผู้ใช้มาให้และทำงานหลายเธรด
# บนเครื่องเดิม
mysqlsh root@localhost:3306 --js -e 'util.dumpInstance("/backup/dump-57", {threads: 4})'
# คัดลอกไปเครื่องใหม่ แล้วโหลดบนเครื่องใหม่
mysql -u root -p -e "SET PERSIST local_infile = ON;"
mysqlsh root@localhost:3306 --js -e 'util.loadDump("/backup/dump-57", {threads: 4, loadUsers: true, excludeUsers: ["root"]})'
mysql -u root -p -e "SET PERSIST local_infile = OFF;"
ถ้าติดตั้ง mysqlsh บนเครื่องเดิมไม่ได้เพราะระบบปฏิบัติการเก่าเกินไป ให้รันคำสั่ง dump จากเครื่องใหม่โดยเชื่อมต่อไปที่ IP ภายในของเครื่องเดิมแทน ไฟล์ dump จะถูกเขียนลงเครื่องที่รันคำสั่ง ส่วน loadDump ต้องเปิด local_infile บนเครื่องปลายทางชั่วคราว ปิดกลับทันทีเมื่อเสร็จ ระหว่างโหลด เซิร์ฟเวอร์ใหม่จะแปลงโครงสร้างเป็นแบบของรุ่นใหม่ให้เอง