DBOps by Liquibase (Part I)

jo@sabotender
KBTG Life
Published in
7 min readMar 15, 2022

ก่อนที่จะเขียนบทความนี้ ผมพยายามหาความแตกต่างระหว่าง DBOps, DatabaseOps และ DevOps for Database สุดท้ายผมก็ยังไม่ได้คำตอบที่ชัดเจนพอที่จะเอามาสรุปได้ แต่ถ้าจะให้อธิบายถึงสิ่งที่กวนใจผมในการทำงานก่อนหน้านี้ และเป็นที่มาของบทความก็คือ…

ทำอย่างไรให้ Developers ทำการ Deploy Changes ไปที่ Databases ได้แบบ Automated?

ในบทความนี้ผมเลือกที่จะใช้คำว่า DBOps ไปก่อน แค่เพราะมันสั้นดี ไม่มีอะไรมากไปกว่านี้ครับ

Why do we need it?

ในการพัฒนาซอฟต์แวร์ส่วน Back-end ที่เกือบทั้งหมดมักจะต้องทำการติดต่อกับ Database สักยี่ห้อหนึ่งเป็นอย่างน้อย นอกจาก Developers อย่างพวกเราจะต้องเขียนโค้ดแล้ว ก็ยังต้องเขียน Database Scripts เพื่อเอาไปสร้างที่เก็บข้อมูลใน Database อีกด้วย สำหรับคนที่ยังไม่รู้จักหรือยังไม่เคยนำศาสตร์แห่ง DBOps ไปใช้งาน อยากให้ลองนึกดูก่อนครับว่า โปรเจคหรืองานที่เราทำอยู่มีปัญหาเหล่านี้กันบ้างไหม

  • ไม่มีที่จัดเก็บ Database Scripts ที่เป็นมาตรฐานเดียวกันภายในทีม เมื่อ Developer แต่ละคนต่างคนต่างเขียนขึ้นมา เวลาจะ Release ทีนึงก็เกิดมหกรรมในการค้นหา นำมารวมกัน รีบเอาไปรีวิวกับ DBA สุดท้ายถ้าพบว่าต้องแก้ไข ก็จะกลายเป็นงานด่วนจานร้อนขึ้นมาทันที มีช่องว่างสำหรับ Human Error หลายจุดมาก
  • บอกไม่ได้ว่าแอปพลิเคชันเวอร์ชันนี้ ต้องใช้กับ Database Schema เวอร์ชันไหน และจาก Script ตัวไหน พอหันกลับมามองดูตัวเองพบว่ามี Script เก็บไว้แค่เวอร์ชันล่าสุดเท่านั้น เวลาจะใช้หรือสร้าง Environment ใหม่ก็ต้องไปหาโคลน Database มาจาก Environment ที่ยังเหลืออยู่
  • Database Access Codes ไม่สอดคล้องกับ Database Schema เวลาเพื่อนแก้ Schema แล้วเราอัพเดตมาแต่โค้ด แต่ Database ยังไม่ได้แก้ตาม หรือในทางกลับกัน แก้ไข Database แล้วแต่โค้ดยังไม่ได้แก้ พอรันโปรแกรมก็ตาย ในทีมมีกันหลายคน เราบ้าง เพื่อนบ้าง นัวไปหมด ผิดพลาดกันแต่ละที แก้ไขแบบแมนนวล รอกันไปรอกันมา
  • เขียน Database Scripts ขึ้นมาสักชุดหนึ่ง ในบาง Environment ที่รันเองได้ เราก็เอาไปรันผ่านโปรแกรม Database Client เอง ส่วนในบาง Environment ที่รันเองไม่ได้ ก็ต้องส่ง Scripts ให้กับ DBA เพื่อไปรันให้ พอมีหลาย Environments รันเองบ้าง ให้ DBA บ้าง สนุกสนาน โค้ดไป เทสไป แก้บั๊กไป ผ่านไปสักพักจำไม่ได้ว่าแต่ละ Environment ต่างกันยังไง
  • เอา Database Changes ไปรัน Deploy บน Production ในวันมหานิยม เวลาผ่านไปเนิ่นนานกว่าจะได้ Deploy เพราะต้องต่อคิวรอ DBA มารันให้ นั่งรอไปเสียวไปว่างาน Deploy ฉันจะ Delay ไหม
  • ในโปรเจคที่มีระยะเวลาพัฒนาและเทสนานๆ เกิดปัญหาว่า Database Scripts ที่ใช้ในขั้นตอน Deployment to Production ไม่เหมือนกับ Database Scripts เวอร์ชันสุดท้ายที่ผ่านการทดสอบจาก Users ซึ่งประเด็นนี้น่าสนใจครับ หลายคนอาจจะคิดว่ารีวิวกับ Lead แล้ว รีวิวกับ DBA ก็แล้วทำไมยังเกิดปัญหาได้อีก
  • เวลาจะ Deploy นอกจากจะมี Database Scripts สำหรับ Change ครั้งนั้นแล้ว ต้องเตรียม Scripts สำหรับ Roll Back ด้วย แต่ Roll Back Scripts มักจะไม่ค่อยได้เทสกัน ถ้าเกิดต้อง Roll Back กันจริงๆ ขึ้นมา ก็ไปวัดใจกันหน้างาน จากประสบการณ์ผมบอกได้เลยว่าการทดสอบ Scripts เดินหน้าถอยหลังไปมาเป็นกิจกรรมที่ค่อนข้างยุ่งยากและใช้เวลามาก บางทีมีเรื่องข้อมูลที่ต้องมา Back up กันเดินหน้าถอยหลังตาม Scripts อีก งานก็เร่ง ใกล้ Deadline แล้วยังปั่นกันอยู่เลย แค่คิดหลายคนก็เหนื่อยแล้ว โดยเฉพาะถ้าเรารัน Database Scripts เองไม่ได้ ต้องให้ DBA เป็นคนรันให้ ก็เปิด Service Requests กันสนุกสนาน ไม่ทันทำมาหากิน สุดท้ายเกิดเป็นความเสี่ยงในขณะ Deploy เพราะ Scripts บางตัวเทสกันไม่ทัน

ถ้าเราไม่พบกับปัญหาเหล่านี้เลย DBOps อาจจะยังไม่จำเป็นครับ แต่ถ้าใครเจอปัญหาเหล่านี้มาบ้าง DBOps จะเริ่มน่าสนใจสำหรับคุณละ ถ้าคุณอยากแก้ปัญหาเหล่านี้แบบยั่งยืน ก็ต้องเปลี่ยนวิธีทำงานให้ Automated มากขึ้น

Why DBOps?

แม้ว่าในบางโปรเจคหรือบางทีมอาจจะไม่มีปัญหากับการจัดการกับ Database Changes หรือ Database Scripts อย่างที่กล่าวมาข้างต้น หรืออาจจะรู้สึกว่าเรายังจัดการและจัดเก็บกันแบบที่เป็นอยู่กันได้ มีปัญหาก็ยังแก้กันไหว และเคยชินกับการทำงานในรูปแบบเดิมๆ กันอยู่ ก็ไม่ถือว่าผิดครับ แต่ถ้าเรามองหาวิธีการทำงานรูปแบบใหม่ที่จะมาเพิ่ม Productivity ให้กับนักพัฒนา ลองมาดู DBOps กันได้ครับ ซึ่งในย่อหน้านี้ผมอยากจะอธิบายเพิ่มสักหน่อยว่าทำไม DBOps ถึงมีความจำเป็นในยุคปัจจุบัน

การมาของ Agile

ผมว่า Agile ไม่ได้ใหม่สำหรับโลกใบนี้แล้วครับ โดยเฉพาะถ้าเรารู้จักบรรพบุรุษของมันที่ชื่อ eXtreme Programming ซึ่งจุดเปลี่ยนที่มันมาสัมพันธ์กับ DBOps หลักๆ ก็คือ…

  1. แนวคิดเกี่ยวกับ Changes
  2. Deliverables ของ Developers

โดยถ้าเราวิเคราะห์เปรียบเทียบกับ Waterfall เราจะเห็นได้ชัดขึ้นดังนี้ครับ

รูปแสดงการออกแบบ database ในโปรเจคแบบ waterfall รูปแบบหนึ่งใน KBTG
รูปแสดงการออกแบบ Database ในโปรเจคแบบ Waterfall รูปแบบหนึ่งใน KBTG

ในการทำงานแบบ Waterfall เราไม่อยากให้มี Changes อะไรเกิดขึ้นระหว่างทาง ผมจะได้ยินบ่อยมากกับวลีที่ว่า

“ยิ่ง Changes ไปเกิดขึ้นที่เฟสหลังๆ Cost ในการแก้ไขก็จะยิ่งสูง”

ดังนั้นคนที่เป็น Project Manager ในโปรเจคแบบ Waterfall ก็จะพยายามทุกวิถีทางเพื่อไม่ให้มี Changes เกิดขึ้น โดยเฉพาะ Requirement Changes ซึ่งสอดคล้องกับลักษณะของ Waterfall ที่เราจะทำงานเข้มๆ กันในช่วงแรกเพื่อไม่ให้เกิด Changes ขึ้นในช่วงหลัง เช่น เราเก็บ Requirements กันอย่างละเอียด จดลงเอกสารกันทุกเม็ด รีวิวและ Sign-off กันเพื่อที่จะไม่ให้ Requirements มาเปลี่ยนทีหลัง หรือว่าเราดีไซน์กันละเอียดๆ เขียนเอกสาร Flowchart หรือ Diagrams กันโหดๆ เพื่อที่จะไม่ให้เกิดการพัฒนาที่ผิดพลาดหรือความเข้าใจที่คลาดเคลื่อนกันตอนโค้ด เป็นต้น

ทีนี้มองกลับมาที่งานออกแบบ Database ในโปรเจคแบบ Waterfall จุดต่างสำคัญคือเรามักจะรู้ Requirements ทั้งหมดตั้งแต่ก่อนการออกแบบ Database (อย่างน้อยก็ที่ Users คอนเฟิร์มหรือ Signed มาว่าจะไม่เปลี่ยนแน่แล้วในตอนนั้น ซึ่งก็อาจจะมาเปลี่ยนในตอนหลังอยู่ดี ฮือ…) เพราะเฟส Requirement Gathering อยู่ก่อนเฟสดีไซน์นั่นเอง และหลังจากการออกแบบฐานข้อมูล เขียน ER Diagram หรืออะไรก็แล้วแต่ เราก็จะได้ Database Scripts ชุดใหญ่มาชุดหนึ่งสำหรับ Requirements ทั้งหมดทั้งมวล พร้อมกับความหวังว่าจะไม่มี Changes เกิดขึ้นระหว่างทาง และ Database Scripts ชุดนั้นก็จะถูกนำไปใช้ตามเฟสของการพัฒนาและถูกนำไปใช้กับ Environment ต่างๆ ไหลไปกับน้ำตกจนสุดท้ายถูก Deployed ไปอยู่บน Production

แม้ว่าในความเป็นจริง เรามักมีการแก้ไข Database Scripts ตามเฟสต่างๆ ของ Waterfall อยู่ดี เช่น ในเฟส Development เราอาจจะมีการแก้ไขโครงสร้างฐานข้อมูลเมื่อเราพบว่าโครงสร้างอีกแบบหนึ่งจะทำให้เราเขียนโค้ดได้ดีกว่า หรือในขั้นตอนการทดสอบ เราอาจจะต้องเพิ่ม Scripts สำหรับ Performance Tuning เช่น การสร้าง Indexes การเพิ่ม Constraints หรือกระทั่งแก้บั๊กบางตัวที่ลึกลงไปถึงระดับของโครงสร้างข้อมูลในฐานข้อมูล แต่กรรมวิธีการแก้ไข Database Scripts ในโปรเจคแบบ Waterfall มักจะไม่ยุ่งยากเท่าไหร่ เพราะเราสามารถเก็บรวบรวม Scripts ทั้งก้อนไว้ที่เดียว ทำการแก้ไขพร้อมกำกับด้วยเลขเวอร์ชันแล้วเวลานำไปใช้ก็บอกทุกคนในทีมว่าให้เอาเวอร์ชันล่าสุดไปใช้นะจ๊ะ

รูปแสดงการออกแบบ database ในการทำงานแบบ Agile รูปแบบหนึ่งใน KBTG
รูปแสดงการออกแบบ Database ในการทำงานแบบ Agile รูปแบบหนึ่งใน KBTG

สำหรับการทำงานแบบ Agile เราจะได้ยินวลีที่ว่า

“จง Embrace Changes”

นั่นหมายถึงการที่ Agile ยอมรับว่า Changes เป็นเรื่องปกติ ดังนั้น Agile จะหาวิธีว่าทำอย่างไรที่จะจัดการและควบคุม Changes ได้อย่างมีประสิทธิภาพ ในโปรเจคแบบ Waterfall เราจะตั้งใจออกแบบระบบให้สมบูรณ์ตาม Requirements ทั้งหมดให้เสร็จภายในเฟส Design ตามแผนที่ได้สัญญากับ Project Manager ไว้ ออกแบบแล้วก็ค่อยไปเขียนโค้ดกัน แต่ใน Agile เราจะมองงานออกแบบระบบเป็นงานที่ต้องทำและปรับปรุงอย่างต่อเนื่อง โดยทำสลับไปกับการเขียนโค้ด การเทส และการ Delivery ซึ่งเมื่อถึงการทำงานในรอบหน้า เราอาจจะได้รับ Changes ของงานที่เราเพิ่งส่งออกไปในรอบที่แล้วมาทำก็เป็นได้

ถ้าดูจากภาพด้านบน เมื่อ Developer แต่ละคนได้รับ User Story ของตัวเองมาทำงาน Developer แต่ละคนก็จะเขียน Database Scripts ที่จำเป็นสำหรับ User Story นั้นขึ้นมาพร้อมกับโค้ดของแอปพลิเคชันที่ตนเองรับผิดชอบ เราจะเห็นว่าถ้า Developers ในทีมมีหลายคน ต่างคนทำงานกับ User Story ที่แตกต่างกัน ก็จะเกิดเป็น Database Scripts เล็ก ๆ จำนวนมาก นอกจากเราจะต้อง Merge Source Codes ของแอปพลิเคชันแล้ว เรายังมีงานที่จะต้อง Merge Database Scripts ของ Release นั้น ๆ ให้ถูกต้อง และส่งต่อไปให้ถึง Production ในขณะเดียวกันเราก็จะผลิต Database Scripts ของ User Story ถัดไปออกมาอีกอย่างต่อเนื่อง

การจัดการ Database Scripts ในการทำงานแบบ Agile มีความซับซ้อนขึ้นจากจำนวน Scripts ที่มีมากขึ้นและรอบของการ Delivery ที่เร็วขึ้น ผมเคยเห็นบางทีมดึงงานออกแบบฐานข้อมูลออกมารวมศูนย์อยู่ที่คนที่เก่งด้านฐานข้อมูลที่สุดของทีม เป็นการทำงานลูกผสมแบบ Centralized กับ Decentralized เข้าด้วยกัน ซึ่งในจุดนี้ แต่ละทีมก็จะต้องชั่งน้ำหนักดูว่าวิธีการทำงานแบบใดที่เหมาะสมกับตนเอง และ DBOps ก็เป็นวิธีหนึ่งที่สามารถช่วยได้

การมาของ CI/CD

เมื่อเราเริ่มทำงานแบบ Agile ด้วยจิตมุ่งหวังว่าอยากจะส่งมอบงานให้เร็วขึ้นกว่าเดิม แต่ถ้าเรายังมีกระบวนการ Code-Build-Test-Deploy แบบแมนนวลอยู่ มันก็ไปได้ไม่สุด เหมือนมีอะไรมาถ่วงแข้งถ่วงขาไว้ ปกติเรามักเริ่มต้นกระบวนการ CI/CD จาก Source Code Repositories เช่น GitHub, GitLab, Bitbucket ฯลฯ และเคยชินกับการเก็บ Source Codes ของแอปพลิเคชันไว้ในนั้น แต่อย่าลืมว่า Database Scripts นั้นก็เป็น Source Codes อย่างหนึ่ง ซึ่งสุดท้ายก็ต้องมีการ Deploy ขึ้นไปบน Production ด้วย ดังนั้นหาก Application Source Codes ของเราอยู่ในรถซูเปอร์คาร์ที่ชื่อ CI/CD แล้ว ก็ไม่ควรปล่อยเพื่อนที่ชื่อ Database Scripts ให้เดินเท้าต้วมเตี้ยมอยู่ ควรเอาเพื่อนขึ้นรถมาด้วย

การพัฒนาขึ้นของ Infrastructure และการมาของ Cloud Computing

เมื่อเราทำงานกันแบบ Agile และนำ CI/CD Tools ต่าง ๆ เข้ามาใช้ แต่เรามี Infrastructure ที่ทำงานช้ามาก ถ้าจะ Provisioning เครื่องทีนึงรอกันสัปดาห์นึง ก็นึกภาพไม่ออกว่ามันจะเร็วดั่งใจได้อย่างไร แต่โชคดีครับ ตอนนี้เราอยู่ในยุคที่ Infrastructure หาได้ง่ายมาก เราสามารถสร้าง (Provisioning) ได้เอง และมีราคาถูกลงเยอะมากเมื่อเทียบกับหลายสิบปีที่แล้ว และในขณะที่ราคาถูกลง พลังการประมวลผลมีมากขึ้น ความเร็วสูงขึ้น ทำให้เราสามารถพัฒนาซอฟต์แวร์รูปแบบใหม่ ๆ ที่เมื่อก่อนทำได้ยาก หรืออาจจะไม่สามารถทำได้เลย ยกตัวอย่างเช่น Micro-Services อันป๊อปปูล่า, Distributed Systems ที่มีขนาดใหญ่มากๆ หรือ Big Data Processing ที่ต้องการพลังในการประมวลผลบน Data Storage ขนาดมหึมา เป็นต้น และเมื่อแอปพลิเคชันมีขนาดใหญ่ขึ้น ซับซ้อนขึ้น นักพัฒนาต้องทำงานร่วมกันมากขึ้น เราก็ต้องการวิธีการทำงานที่รวดเร็วขึ้น ยุ่งยากน้อยลง ลดการเกิด Human Errors เพื่อที่ Developers จะได้ใช้เวลาโฟกัสกับการพัฒนา การออกแบบระบบหรือการเขียนโค้ดได้เต็มที่ ไม่ต้องใช้เวลาไปกับงานรูทีน งานเอกสาร งานแอดมินต่างๆ โดยไม่จำเป็น

ดังนั้นคำถามที่ว่า ทำไมต้อง DBOps? DBOps มีประโยชน์อย่างไร? DBOps เหมาะกับใคร? จะมีคำตอบที่ใกล้เคียงกันดังนี้ครับ

  • เพื่อลด Pain Points ในการทำงานที่เกิดจากการจัดการ Database Scripts แบบ Manual พูดอีกนัยหนึ่งคือการลด Human Errors ที่ยิ่งระบบมีความซับซ้อนเท่าไร ยิ่งมีโอกาสเกิดสูงขึ้นเท่านั้น (ย้อนกลับไปดูตัวอย่าง Pain Points ได้ในตอนต้นของบทความนะครับ)
  • เพื่อยกระดับ Agile และ CI/CD ของคุณขึ้นไปอีกขั้นหนึ่ง แน่นอนการทำงานโดยรวมของคุณจะไหลลื่นขึ้น จะเนียนมากขึ้น
  • เพื่อยกระดับ Practices การทำงานของทีมให้มีมาตรฐานสูงขึ้น เริ่มต้นโดยการ Maintain Database Changes as Codes

What are our practices?

รูปแสดงการผนึกกำลัง Database Design เข้ากับ Agile และ CI/CD

ถ้าไปหาข้อมูลการทำ DBOps ในอินเตอร์เน็ต แน่นอนเราจะเจอเครื่องมือมากมายหลายแบบหลายยี่ห้อ และคู่มือการใช้งานอีกเป็นกระบุง แล้วเราจะเลือกอะไรดี?

ผมใช้วิธีกำหนดบริบทที่เราต้องการก่อน แล้วค่อยๆ ตีขอบเขตให้แคบลงว่ามีเครื่องมืออะไรที่ตรงกับที่เราต้องการบ้าง ซึ่งบริบทของ KBTG ก็คือวิธีการทำงานหรือวิธีในการพัฒนาซอฟต์แวร์ในปัจจุบันของเรานั่นเอง ทีนี้ในภาพใหญ่เรามี Agile / Scrum Methodology เรามี Core CI/CD Tool คือ Jenkins และ Source Codes ของเราก็อยู่บน GitLab ดังนั้นจิ๊กซอว์ตัวถัดไปที่จะทำให้เราเป็นปึกแผ่นแข็งแรงขึ้นได้ก็คือ Database Design ในวิถีของ DBOps

ทีนี้ในรายละเอียด ผมจึงได้เขียน Practices ที่อยากได้ไว้ดังต่อไปนี้

  • Database Changes ต้องอยู่ใน GitLab ที่เป็น Source Code Repositories & Version Control System ตามหลักที่เราอยากจะให้ Git เป็น The Single Source of Truth และเพื่อให้เราได้ประโยชน์ในเชิง Database Changes as Codes อีกหลายอย่าง เช่น การทำ Code Review, การทำ Merge Request, การใช้ Tags และการแยก Branch เป็นต้น
  • Database Changes ต้องอยู่ในรูปแบบที่อ่านและทำความเข้าใจได้ง่าย เพื่อลด Learning Curve ให้ต่ำ ถ้าให้ดีควรเป็น Portable Format ที่ไม่ Proprietary จนเกินไป
  • Database Changes อยากให้อยู่ในรูปของ Database Migration ที่เดินหน้าไปเรื่อยๆ ถึงแม้ว่า Database Changes จะอยู่ใน Git เราก็ไม่อยากให้ Developers กลับมาแก้ไขไฟล์เก่าเพื่อที่จะทำงานชิ้นใหม่ แต่อยากให้ไปสร้างไฟล์ใหม่เดินหน้าไปเลย มันบริหารจัดการและตรวจสอบง่ายกว่า
  • Deploy Database Changes ได้ ควรต้องรองรับการ Roll Back ได้ด้วย
  • มองหาเครื่องมือในแบบฟรี Open Sources ที่พัฒนาด้วยภาษาที่เรามีบุคลากรเพียงพอที่จะอ่าน Source Codes และทำความเข้าใจการทำงานของมันได้ มี Community ที่ Active และถ้ามี Supporting Model แบบ Commercial ด้วยก็จะอุ่นใจขึ้นอีกระดับนึง เราสามารถลงทุนจ่ายค่าซอฟต์แวร์ได้ แต่เราควรจ่ายเมื่อจำเป็นเท่านั้น
  • เครื่องมือควรใช้งานกับ Databases ส่วนมากที่มีใช้งานอยู่ในบริษัทได้ เพราะเราก็ไม่อยากให้มีต้นทุนที่ไม่จำเป็นในการบริหารจัดการเครื่องมือที่ทำหน้าที่เดียวกันหลายๆ ตัว เพียงเพื่อจะใช้งานกับ Databases ต่างยี่ห้อกัน
  • สุดท้ายต้องทำงานเข้ากับ Core CI/CD Tool ของเราคือ Jenkins ได้

โดยหลักการทำงานเบื้องต้นที่ร่างไว้ในตอนแรกก็จะประมาณรูปภาพด้านล่างนี้ครับ

รูปแสดงการ flow ทำงานของ DBOps ในเบื้องต้น
รูปแสดงการ Flow ทำงานของ DBOps ที่ร่างไว้ในเบื้องต้น

DBOps by Liquibase

รูปจาก Liquibase Project ใน GitHub

จากการค้นหาและลองใช้เครื่องมือหลาย ๆ ตัวในขั้นตอน PoC มาพักใหญ่ เราตกลงว่าจะเดินหน้า Pilot อย่างจริงจังกับเครื่องมือที่ชื่อ Liquibase เป็นตัวแรก โดย Liquibase มีทั้งรุ่น Community Edition ที่ใช้งานได้ฟรี และรุ่นที่ต้องเสียเงินแล้วจะได้มาซึ่งความสามารถอื่นๆ ที่เพิ่มขึ้น แต่ในขั้นตอนนี้เราคิดว่าจะลองตัว Community Edition ก่อน เพื่อเก็บฟีดแบ็คและถ้ามีปัญหาใดที่ทำให้เครื่องมือนี้ไปต่อไม่ได้ ต้องไปหาเครื่องมืออื่นแทน หรือว่าควรจะต้องเสียเงินซื้อ Edition ที่สูงขึ้นก็จะได้มาพิจารณากันบนสิ่งที่ได้ทดลองกันมาแล้ว ซึ่งสมบัติและความสามารถของ Liquibase รุ่น Community Edition มีประมาณนี้ครับ

  • Liquibase Community Edition เป็น Free Open Sources อยู่บน GitHub พัฒนาด้วยภาษา Java เป็นหลัก มีภาษาอื่นๆ ติดมาด้วย แต่น้อยมากๆ
  • รองรับการทำงานกับฐานข้อมูล 30+ ยี่ห้อ ซึ่งมีทั้ง Relational Databases, NoSQL Databases และ Cloud Databases (ดูรายชื่อฐานข้อมูลที่รองรับได้ที่นี่)
  • เปิดให้เราสามารถเขียน Extension เพื่อทำงานกับฐานข้อมูลอื่นๆ ได้ หากที่มีอยู่ไม่เพียงพอ
  • รองรับการทำงานทั้งแบบ CLI (Command-Line Interface) และ Docker Image รวมไปถึงมี Plug-in บน Jenkins
  • สำหรับ Java Developers สามารถเรียกใช้ Liquibase ผ่านทาง Build Tools เช่น Maven, Gradle และ Ant ได้
  • รองรับการเขียน Database Changes ในหลายฟอร์แมท เช่น SQL, XML, JSON, YAML เป็นต้น
  • รองรับทั้งการ Deploy และ Roll Back Database Changes
  • รองรับการทดสอบการ Roll Back Database Changes และ Dry Run ด้วยการพิมพ์ SQL Statements ที่จะถูกรันออกมาบน Console หรือบันทึกลงไฟล์
  • มีฟีเจอร์ที่เรียกว่า Quality Check สำหรับ Configure Rules ที่ใช้ในการตรวจสอบ Database Changes ที่อันตราย แต่สำหรับ Community Edition เราจะสามารถ Configure ได้สูงสุดเพียง 5 Rules เท่านั้น
  • ความสามารถอื่นๆ ยังมีอีกมากมาย แต่ที่น่าสนใจ ก็เช่น สามารถหาความแตกต่าง (Differentiate) ระหว่าง Databases สองอันได้ และสามารถ Export ข้อมูล Database Changes และ Schema ออกมาเป็น HTMLs เป็นต้น

สำหรับคนที่ไม่รู้จักหรือไม่เคยใช้งาน Liquibase มาก่อน การทำงานเบื้องต้นของ Liquibase ก็จะประมาณนี้ครับ

1. เขียน Database Scripts ในรูปแบบที่ Liquibase เข้าใจและเก็บไว้ใน Git

รูปตัวอย่างไฟล์ Database Changes สำหรับ Liquibase

2. ใช้คำสั่งของ Liquibase ให้นำ Database Scripts ของเราไปรันที่ Database ที่ต้องการ โดยตัว Liquibase จะทำหน้าที่ตรวจสอบเองว่าที่ Database นั้น Scripts ไหนถูกรันไปแล้ว และต้องรัน Scripts ไหนเพิ่ม

รูปการใช้ Liquibase CLI คำสั่ง Liquibase Update

3. เข้าไปตรวจในฐานข้อมูลได้เลย

รูปการตรวจสอบผลลัพธ์ของการใช้คำสั่ง Liquibase Update

หลักการก็จะประมาณนี้ครับ แต่พอเรามี Command Line แบบนี้แล้ว เราจะสามารถนำไป Integrate เพื่อช่วยงาน CI/CD ได้ประโยชน์มากมายเลยครับ ถ้าใครติดตามบทความในซีรีย์นี้ต่อไป ผมกะว่าจะทำเนื้อหาในรูปแบบของ Code Lab ที่ช่วยแนะนำการใช้เครื่องมือตัวนี้ผ่านทางการฝึกภาคปฏิบัติประกอบไปกับรูปแบบของบทความ ใครสนใจก็รอติดตามกันได้ครับ

Things you must not forget

เครื่องมือทุกชนิดมีประโยชน์ ถ้าเราใช้ผิดวิธี มันจะให้โทษเราครับ ก่อนที่เราจะใช้เครื่องมือที่เรียกว่า Liquibase ผมอยากให้เราตระหนักในสิ่งต่อไปนี้กันก่อน

Automation != Safety

แม้ว่าเราจะสามารถ Deploy Database Changes ได้แบบ Automated แล้ว และได้ผ่านการทดสอบการ Deploy มาแล้วหลายครั้งใน Test Environment ก็ตาม นั่นไม่ได้หมายความว่าเวลาเราไป Deploy บน Production แล้วจะปลอดภัย 100% ประเด็นสำคัญคือการทดสอบที่เราทำมามากมายนั้นอยู่บนสภาพแวดล้อมที่มีความเหมือนกับ Production มากเพียงใดต่างหาก ถ้ามองเฉพาะเรื่องของ Database Changes เรามักมองข้ามความแตกต่างในด้านปริมาณของ Data และ Disk Spaces ระหว่าง Test Environment กับ Production Environment รวมไปถึงการวางแผนและการจัดการ Downtime ที่อาจจะเกิดขึ้นขณะทำการ Deploy อีกด้วย

Automation != DBA

แม้ว่าเราจะสามารถ Deploy Database Changes ผ่าน CI/CD Pipelines ได้โดยไม่ต้องเปิด Service Requests ให้กับ DBA เพื่อรัน Scripts แล้วก็ตาม แต่ไม่ได้หมายถึงว่า DBA หรือ DBA จะตกงานนะครับ ในทางกลับกัน Automation นั้นช่วยให้ Developers และ DBAs มีเวลามาช่วยกันโฟกัสที่คุณภาพของงานกันมากขึ้น แทนที่จะไปเสียเวลาทำกระบวนการต่างๆ ซ้ำไปซ้ำมาเพื่อรัน Scripts เดิมๆ บน Environment ที่มีมากมาย

ที่ผมอยากจะเน้นคือ Developers และ DBAs เราจะมีเวลาในการทำ Code Review กันอย่างมีคุณภาพมากขึ้น และกระบวนการ Code Review (โค้ดในที่นี้หมายถึง Database Scripts เพราะตั้งแต่นี้ต่อไป Database Scripts ของคุณจะอยู่บน Git แล้ว) จะต้องไม่ถูก Bypassed อีกต่อไป อย่าลืมว่า Developers นั้นมีความรู้เกี่ยวกับการทำงานของฟังก์ชันของแอปพลิเคชันที่พัฒนา แต่ DBAs นั้นมีความรู้เกี่ยวกับ Data ที่อยู่ในแอปพลิเคชันของเรา ตลอดจนถึงสภาพแวดล้อมของ Data ของเรา ผมเคยเจอสุดยอด DBA บางคนที่รู้แม้กระทั่งความเชื่อมโยงของข้อมูลของระบบเรากับระบบเพื่อนบ้านรอบๆ อีกด้วย ดังนั้นอย่าลืม Code Review กันนะครับ

A database consists of schema and data

แม้ว่าส่วนใหญ่ของ Database Changes ที่มาจาก Developers นั้นจะเกี่ยวกับ Database Schema (NoSQL Database ก็มี Implicit Schema นะครับ) แต่อย่าลืมว่าสิ่งที่สำคัญบน Production ก็คือ Data หรือข้อมูลที่มักจะมาจากลูกค้าหรือผู้ใช้งานระบบ นอกจากเราจะทำงานร่วมกับ DBAs ที่เป็นคนให้คำปรึกษาเรื่อง Data ที่ดีแล้ว เราที่เป็น Developers จะต้องระวังสิ่งที่เรียกว่า Destructive Statements ที่มีผลกระทบกับ Data ด้วย ตัวอย่างที่เห็นได้ชัดที่สุด เช่น การ Drop Table ที่จะทำให้ Data ของ Table หายไปทั้งหมด และไม่สามารถที่จะ Roll Back ด้วย Statements ที่เราเตรียมไว้ในเฟสก่อนหน้าได้ ในกรณีนี้เราจะต้องปรึกษาและทำงานร่วมกับ DBA เพื่อหาทางป้องกันความผิดพลาดที่อาจจะเกิดขึ้นได้ เช่น อาจจะ Back up Data ไว้ก่อน เป็นต้น

Build your team’s convention and discipline

เมื่อเราไม่ได้ทำงานคนเดียว สมาชิกในทีมทุกคนควรจะมีแนวทางในการทำงานไปในทิศทางเดียวกัน เมื่อ Database Changes ของเรามาอยู่บน Git ซึ่งก็เหมือนกับ Source Codes ที่เราต้องบริหารจัดการและทำงานร่วมกัน เราควรจะออกแบบแนวทางการจัดเก็บ Database Changes ภายในทีม และยึดถือเป็นหลักปฏิบัติร่วมกัน เช่น วิธีการตั้งชื่อไฟล์ (Naming Conventions) การกำหนดเลขเวอร์ชัน (Structured Version Number) การสร้าง Branch ใหม่ (Branching Strategy) เป็นต้น และที่สำคัญคือทุกคนต้องมีวินัยในการ Maintain Database Scripts as Codes นั่นคือต้องไม่มีคนไปแก้ไข Database แบบ Manual โดยไม่มีข้อมูลหรือ Script อยู่ใน Git ซึ่งจะทำให้เสียขบวนกันหมด

References

Happy Automation!

สำหรับชาวเทคคนไหนที่สนใจเรื่องราวดีๆแบบนี้ หรืออยากเรียนรู้เกี่ยวกับ Product ใหม่ๆ ของ KBTG สามารถติดตามรายละเอียดกันได้ที่เว็บไซต์ www.kbtg.tech

--

--

jo@sabotender
KBTG Life

principal DEVelopment eXcellence engineer — DEVX@KBTG / Full-time Daddy / Console Gamer & Gunpla Collector