การทำ Migration ที่จะไม่ทำให้ระบบ Production พัง

การทำ migration ทำงานได้อย่างสมบูรณ์แบบบนเครื่องของคุณ คุณตัดสินใจ deploy ในวันศุกร์ตอน 6 โมงเย็นเพราะคิดว่ามันเป็นงานเล็กๆ จากนั้นการ deploy ก็ค้าง หรือที่แย่กว่านั้นคือ ตารางที่มีข้อมูล 8 ล้านแถวเกิดการ lock นานถึง 40 วินาที จนทำให้เว็บไซต์ของคุณล่ม

Migration ทำงานแตกต่างกันเมื่ออยู่ในระบบ production ฐานข้อมูลในเครื่อง (local) นั้นว่างเปล่าและทำงานรวดเร็ว แต่ฐานข้อมูลบน production มีข้อมูลจริงและมีผู้ใช้งานที่กำลังใช้งานอยู่

ปฏิบัติตามกฎเหล่านี้เพื่อหลีกเลี่ยงหายนะบน production

  • เขียน method down ให้ใช้งานได้เสมอ ทุก migration จำเป็นต้องมีฟังก์ชัน up และ down โดยฟังก์ชัน down จะต้องย้อนกลับการทำงานของฟังก์ชัน up ได้อย่างแม่นยำ หากคุณไม่สามารถเขียน rollback ได้ แสดงว่า migration ของคุณซับซ้อนเกินไป ควรทดสอบบนเครื่องของคุณด้วยคำสั่ง migrate ตามด้วย migrate:rollback ก่อนที่จะ push งาน

  • อย่าแก้ไข migration เก่า คุณอาจต้องการแก้ไขขนาดของ column ในไฟล์ migration เก่า แต่อย่าทำเช่นนั้น เพราะ Laravel จะไม่รันไฟล์นั้นซ้ำบน server ให้ใช้วิธีสร้าง migration ใหม่เพื่อเปลี่ยนโครงสร้างแทน เพราะ migration คือประวัติของการเปลี่ยนแปลง คุณควรเพิ่มบทใหม่แทนที่จะกลับไปแก้ไขบทเก่า

  • ใช้ค่า nullable หรือค่า default การเพิ่ม column แบบ NOT NULL ลงในตารางที่มีข้อมูลอยู่แล้วจะทำให้เกิดข้อผิดพลาด เนื่องจากฐานข้อมูลไม่รู้ว่าจะต้องใส่ค่าอะไรลงในแถวเก่าๆ

ใช้แนวทางเหล่านี้แทน: • กำหนดให้ column ใหม่เป็น nullable • กำหนดค่า default • หาก column นั้นจำเป็นต้องมีค่า (required) ให้ทำเป็น 3 ขั้นตอน: สร้างแบบ nullable ก่อน, ใส่ข้อมูลให้ครบ, แล้วจึงเปลี่ยนเป็น NOT NULL

  • การสูญเสียข้อมูลนั้นเรียกคืนไม่ได้ คำสั่ง dropColumn จะลบข้อมูลทิ้งไปตลอดกาล แม้การ rollback จะสามารถสร้าง column กลับมาใหม่ได้ แต่ข้อมูลข้างในจะหายไปหมด ก่อนที่จะสั่ง drop column ควรตรวจสอบ backup ของคุณให้แน่ใจ วิธีที่ปลอดภัยกว่าคือการหยุดใช้งาน column นั้นใน code ของคุณก่อน รอสักสองสามสัปดาห์ แล้วจึงค่อยลบออกจากฐานข้อมูล

  • แยกการเปลี่ยน schema ออกจากการอัปเดตข้อมูล การรัน User::all() ภายใน migration อาจทำให้ข้อมูลหลายล้านแถวถูกโหลดเข้าสู่ memory จนทำให้การ deploy ล่ม หากคุณจำเป็นต้องอัปเดตข้อมูลระหว่างทำ migration ให้ใช้ chunkById เพื่อประมวลผลข้อมูลเป็นชุดเล็กๆ (batches)

  • ใช้ flag --force ใน pipeline ระบบ automated deployment pipeline จะค้างหาก Laravel ถามเพื่อขอการยืนยัน ให้ใช้คำสั่งนี้ใน deployment scripts ของคุณ: php artisan migrate --force

  • ระวังเรื่อง table locks การเปลี่ยน column หรือการเพิ่ม index ในตารางที่มีขนาดใหญ่มากจะทำให้เกิดการ lock ตาราง ซึ่งส่งผลให้เกิด downtime สำหรับตารางที่มีขนาดใหญ่มาก ควรศึกษาเครื่องมือประเภท online schema change หรือเลือกดำเนินการในช่วงเวลาที่มีผู้ใช้งานน้อย (low traffic)

รายการตรวจสอบก่อนที่คุณจะ push: • method down ใช้งานได้จริงหรือไม่? • ฉันได้ทดสอบ rollback ในเครื่องแล้วหรือยัง? • ฉันกำลังสร้าง migration ใหม่แทนที่จะแก้ไขอันเก่าใช่ไหม? • column ใหม่เป็น nullable หรือมีค่า default หรือไม่? • ฉันมี backup ก่อนที่จะสั่ง drop column หรือไม่?

ที่มา: https://dev.to/denisgusto1/migrations-que-nao-quebram-em-producao-o-guia-que-ninguem-te-deu-363o