ไม่เคยเกิดขึ้นมาก่อน และเราจะไปอีกครั้ง!
ในโครงการต่อไปของเรา เราตัดสินใจใช้ Liquibase ตั้งแต่ต้นเพื่อหลีกเลี่ยงปัญหาในอนาคต ปรากฎว่าไม่ใช่สมาชิกในทีมรุ่นใหม่ทุกคนจะรู้วิธีใช้อย่างถูกต้อง ฉันจัดเวิร์กช็อปภายในซึ่งฉันตัดสินใจทำเป็นบทความ
บทความนี้ประกอบด้วยเคล็ดลับที่เป็นประโยชน์และคำอธิบายข้อผิดพลาดสามประการที่ชัดเจนที่สุดที่คุณอาจพบเมื่อทำงานกับเครื่องมือการย้ายฐานข้อมูลเชิงสัมพันธ์ โดยเฉพาะ Liquibase ออกแบบมาสำหรับนักพัฒนา Java ในระดับจูเนียร์และกลาง สำหรับนักพัฒนาที่มีประสบการณ์มากขึ้น อาจเป็นที่สนใจสำหรับการจัดโครงสร้างและทำซ้ำสิ่งที่น่าจะทราบอยู่แล้ว
Liquibase และ Flyway เป็นเทคโนโลยีการแข่งขันหลักสำหรับการแก้ปัญหาการควบคุมเวอร์ชันของโครงสร้างเชิงสัมพันธ์ในโลก Java อันแรกนั้นฟรีโดยสมบูรณ์ ในทางปฏิบัติมักถูกเลือกใช้บ่อยที่สุดซึ่งเป็นสาเหตุที่ Liquibase ได้รับเลือกให้เป็นฮีโร่ของสิ่งพิมพ์ อย่างไรก็ตาม แนวทางปฏิบัติบางอย่างที่อธิบายไว้อาจเป็นสากล ขึ้นอยู่กับสถาปัตยกรรมแอปพลิเคชันของคุณ
การย้ายโครงสร้างเชิงสัมพันธ์เป็นวิธีการบังคับในการจัดการกับความยืดหยุ่นที่อ่อนแอของการจัดเก็บข้อมูลเชิงสัมพันธ์ ในยุคของแฟชั่น OOP รูปแบบการทำงานกับฐานข้อมูลหมายความว่าเราจะอธิบายสคีมาเพียงครั้งเดียวและไม่ต้องแตะต้องมันอีก แต่ความจริงก็คือสิ่งต่าง ๆ เปลี่ยนแปลงอยู่เสมอ และจำเป็นต้องเปลี่ยนแปลงโครงสร้างตารางค่อนข้างบ่อย โดยธรรมชาติแล้ว กระบวนการนี้อาจเจ็บปวดและไม่เป็นที่พอใจได้
ฉันจะไม่ลงลึกเข้าไปในคำอธิบายของเทคโนโลยีและคำแนะนำในการเพิ่มไลบรารีในโครงการของคุณ มีการเขียนบทความบางส่วนในหัวข้อนี้:
การใช้ Liquibase เพื่อจัดการโครงสร้างฐานข้อมูลในแอปพลิเคชัน Spring Boot ส่วนที่ 1 การใช้ Liquibase เพื่อจัดการโครงสร้างฐานข้อมูลในแอปพลิเคชัน Spring Boot ส่วนที่ 2 Liquibase และ Maven แนวทางการเปลี่ยนแปลงฐานข้อมูลเวอร์ชัน เราเปิดตัว Spring MVC/Security, REST, Hibernate, Liquibase ในสองบรรทัด
นอกจากนี้ยังมีบทความดีๆ ในหัวข้อเคล็ดลับที่เป็นประโยชน์อยู่แล้ว:
Советы
ฉันต้องการแบ่งปันคำแนะนำและความคิดเห็นของฉันซึ่งเกิดจากหยาดเหงื่อ เลือด และความเจ็บปวดในการแก้ปัญหาการย้ายถิ่นฐาน
1. ก่อนเริ่มงาน คุณควรทำความคุ้นเคยกับส่วนแนวทางปฏิบัติที่ดีที่สุด เว็บไซต์ ลิควิเบส
2. หากคุณเริ่มใช้เครื่องมือการโยกย้าย อย่าอนุญาตการแก้ไขด้วยตนเองในโครงสร้างฐานข้อมูล
ดังคำกล่าวที่ว่า: “เมื่อ Persil, Persil เสมอ” หากฐานของแอปพลิเคชันของคุณเริ่มได้รับการจัดการโดย Liquibase การเปลี่ยนแปลงด้วยตนเองจะนำไปสู่สถานะที่ไม่สอดคล้องกันทันที และระดับความน่าเชื่อถือในชุดการแก้ไขจะกลายเป็นศูนย์ ความเสี่ยงที่อาจเกิดขึ้น ได้แก่ การใช้เวลาหลายชั่วโมงในการกู้คืนฐานข้อมูล ในกรณีที่เลวร้ายที่สุด นั่นก็คือเซิร์ฟเวอร์ที่ไม่ทำงาน หากคุณมีสถาปนิก DBA “แบบเก่า” ในทีมของคุณ ให้อธิบายให้เขาฟังอย่างอดทนและรอบคอบว่าสิ่งที่เลวร้ายจะเป็นอย่างไรหากเขาเพียงแค่แก้ไขฐานข้อมูลตามความเข้าใจของเขาเองจากนักพัฒนา SQL แบบมีเงื่อนไข
3. หากชุดการแก้ไขได้ถูกพุชไปยังพื้นที่เก็บข้อมูลแล้ว ให้หลีกเลี่ยงการแก้ไข
หากนักพัฒนารายอื่นทำการดึงและใช้ชุดการแก้ไขซึ่งจะได้รับการแก้ไขในภายหลัง เขาจะจดจำคุณด้วยคำพูดที่ใจดีอย่างแน่นอนเมื่อได้รับข้อผิดพลาดเมื่อเริ่มแอปพลิเคชัน หากการแก้ไขชุดการแก้ไขเกิดการรั่วไหลไปสู่การพัฒนา คุณจะต้องปฏิบัติตามขั้นตอนที่ลื่นไหลของโปรแกรมแก้ไขด่วน สาระสำคัญของปัญหาอยู่ที่การตรวจสอบความถูกต้องของการเปลี่ยนแปลงด้วยผลรวมแฮชซึ่งเป็นกลไกหลักของ Liquibase เมื่อแก้ไขโค้ดเซ็ตการแก้ไข จำนวนแฮชจะเปลี่ยนไป การแก้ไขชุดการแก้ไขจะทำได้ก็ต่อเมื่อเป็นไปได้ที่จะปรับใช้ฐานข้อมูลทั้งหมดตั้งแต่ต้นโดยไม่สูญเสียข้อมูล ในกรณีนี้ การปรับโครงสร้างโค้ด SQL หรือ XML จะทำให้ชีวิตง่ายขึ้นและทำให้การโยกย้ายอ่านง่ายขึ้น ตัวอย่างจะเป็นสถานการณ์ที่เมื่อเริ่มต้นแอปพลิเคชัน มีการตกลงสคีมาของฐานข้อมูลต้นทางภายในทีม
4. ตรวจสอบการสำรองฐานข้อมูลหากเป็นไปได้
ที่นี่ฉันคิดว่าทุกอย่างชัดเจน หากจู่ๆ การโยกย้ายไม่สำเร็จ ทุกอย่างก็สามารถคืนกลับมาได้ Liquibase มีเครื่องมือสำหรับการย้อนกลับการเปลี่ยนแปลง แต่สคริปต์การย้อนกลับนั้นถูกเขียนโดยนักพัฒนาเอง และอาจมีปัญหากับความน่าจะเป็นเช่นเดียวกับสคริปต์ของชุดการแก้ไขหลัก ซึ่งหมายความว่าการเล่นอย่างปลอดภัยด้วยการสำรองข้อมูลจะเป็นประโยชน์ในทุกกรณี
5. ใช้การสำรองฐานข้อมูลที่ได้รับการพิสูจน์แล้วในการพัฒนาหากเป็นไปได้
หากสิ่งนี้ไม่ขัดแย้งกับสัญญาและความเป็นส่วนตัว ไม่มีข้อมูลส่วนบุคคลในฐานข้อมูล และไม่มีน้ำหนักมากเท่ากับดวงอาทิตย์สองดวง - ก่อนที่จะใช้งานบนเซิร์ฟเวอร์การย้ายข้อมูลแบบสด คุณสามารถตรวจสอบว่ามันจะทำงานอย่างไรบนเครื่องของนักพัฒนาและคำนวณ เกือบ 100% ของปัญหาที่อาจเกิดขึ้นระหว่างการย้ายถิ่น
6. สื่อสารกับ Developer คนอื่นๆ ในทีม
ในกระบวนการพัฒนาที่มีการจัดการอย่างดี ทุกคนในทีมรู้ว่าใครกำลังทำอะไร ในความเป็นจริง มักจะไม่เป็นเช่นนั้น ดังนั้น หากคุณกำลังเตรียมการเปลี่ยนแปลงโครงสร้างฐานข้อมูลซึ่งเป็นส่วนหนึ่งของงานของคุณ ขอแนะนำให้แจ้งให้ทีมทั้งหมดทราบเพิ่มเติมเกี่ยวกับเรื่องนี้ หากมีใครทำการเปลี่ยนแปลงควบคู่กัน คุณควรจัดระเบียบอย่างรอบคอบ การสื่อสารกับเพื่อนร่วมงานหลังเลิกงานเป็นสิ่งที่คุ้มค่า ไม่ใช่แค่ตั้งแต่เริ่มต้นเท่านั้น ปัญหาที่อาจเกิดขึ้นกับชุดการแก้ไขสามารถแก้ไขได้ในขั้นตอนการตรวจสอบโค้ด
7. คิดถึงสิ่งที่คุณกำลังทำอยู่!
ดูเหมือนคำแนะนำที่ชัดเจนในตัวเองซึ่งใช้ได้กับทุกสถานการณ์ อย่างไรก็ตาม ปัญหาหลายอย่างสามารถหลีกเลี่ยงได้หากนักพัฒนาวิเคราะห์อีกครั้งว่าเขากำลังทำอะไรอยู่ และสิ่งที่อาจส่งผลกระทบ การทำงานกับการย้ายข้อมูลต้องอาศัยความใส่ใจและความแม่นยำเพิ่มเติมเสมอ
กับดัก
ตอนนี้เรามาดูกับดักทั่วไปที่คุณอาจตกอยู่ในได้หากคุณไม่ปฏิบัติตามคำแนะนำข้างต้น และคุณควรทำอย่างไร?
สถานการณ์ที่ 1: นักพัฒนาสองคนพยายามเพิ่มชุดการแก้ไขใหม่ในเวลาเดียวกัน
Vasya และ Petya ต้องการสร้างเซ็ตการแก้ไขเวอร์ชัน 4 โดยที่ไม่รู้จักกัน พวกเขาทำการเปลี่ยนแปลงโครงสร้างฐานข้อมูลและออกคำขอดึงข้อมูลด้วยไฟล์เซ็ตการแก้ไขที่แตกต่างกัน เสนอกลไกการดำเนินการดังต่อไปนี้:
ตัดสินใจอย่างไร
- เพื่อนร่วมงานจะต้องตกลงตามลำดับที่เซ็ตการแก้ไขควรจะไป เช่น Petin ควรจะถูกนำมาใช้ก่อน
- บางคนควรเพิ่มอันที่สองให้กับตัวเองและทำเครื่องหมายเซ็ตการแก้ไขของ Vasya ด้วยเวอร์ชัน 5 ซึ่งสามารถทำได้ผ่าน Cherry Pick หรือการผสานเรียบร้อย
- หลังจากการเปลี่ยนแปลง คุณควรตรวจสอบความถูกต้องของการดำเนินการอย่างแน่นอน
ในความเป็นจริง กลไก Liquibase จะช่วยให้คุณมีชุดการแก้ไขเวอร์ชัน 4 สองชุดในที่เก็บ ดังนั้นคุณจึงสามารถปล่อยทุกอย่างไว้เหมือนเดิมได้ นั่นคือคุณจะมีการเปลี่ยนแปลงสองครั้งในเวอร์ชัน 4 ที่มีชื่อต่างกัน ด้วยวิธีนี้ การนำทางเวอร์ชันฐานข้อมูลจะกลายเป็นเรื่องยากมากในภายหลัง
นอกจากนี้ Liquibase ก็เหมือนกับบ้านของฮอบบิทที่เก็บความลับมากมาย หนึ่งในนั้นคือคีย์ validCheckSum ซึ่งปรากฏในเวอร์ชัน 1.7 และอนุญาตให้คุณระบุค่าแฮชที่ถูกต้องสำหรับชุดการแก้ไขเฉพาะ โดยไม่คำนึงถึงสิ่งที่เก็บไว้ในฐานข้อมูล เอกสารประกอบ
เพิ่มเช็คซัมที่ถือว่าถูกต้องสำหรับชุดการเปลี่ยนแปลงนี้ โดยไม่คำนึงถึงสิ่งที่เก็บไว้ในฐานข้อมูล ใช้เป็นหลักเมื่อคุณต้องการเปลี่ยนชุดการเปลี่ยนแปลง และไม่ต้องการให้เกิดข้อผิดพลาดในฐานข้อมูลที่ชุดการเปลี่ยนแปลงนั้นรันอยู่แล้ว (ไม่ใช่ขั้นตอนที่แนะนำ)
ใช่ ใช่ ไม่แนะนำขั้นตอนนี้ แต่บางครั้งนักมายากลแสงที่แข็งแกร่งก็สามารถเชี่ยวชาญเทคนิคด้านมืดได้เช่นกัน
สถานการณ์ที่ 2: การย้ายที่ขึ้นอยู่กับข้อมูล
สมมติว่าคุณไม่มีความสามารถในการใช้การสำรองฐานข้อมูลจากเซิร์ฟเวอร์ที่ใช้งานจริง Petya สร้างเซ็ตการแก้ไข ทดสอบในเครื่อง และด้วยความมั่นใจว่าเขาพูดถูก จึงได้ส่งคำขอดึงไปยังนักพัฒนา ในกรณีที่หัวหน้าโครงการชี้แจงว่า Petya ได้ตรวจสอบแล้วจึงกล่าวเสริม แต่การปรับใช้บนเซิร์ฟเวอร์การพัฒนาล้มเหลว
ในความเป็นจริงสิ่งนี้เป็นไปได้และไม่มีใครรอดพ้นจากสิ่งนี้ สิ่งนี้จะเกิดขึ้นหากการปรับเปลี่ยนโครงสร้างตารางเชื่อมโยงกับข้อมูลเฉพาะจากฐานข้อมูล แน่นอนว่าหากฐานข้อมูลของ Petya เต็มไปด้วยข้อมูลทดสอบเท่านั้น ก็อาจไม่ครอบคลุมทุกกรณีที่เกิดปัญหา ตัวอย่างเช่น เมื่อลบตาราง ปรากฎว่ามีบันทึกในตารางอื่นโดย Foreign Key ที่เกี่ยวข้องกับบันทึกในตารางที่ถูกลบ หรือเมื่อเปลี่ยนประเภทคอลัมน์ปรากฎว่าข้อมูลไม่สามารถแปลงเป็นประเภทใหม่ได้ 100%
ตัดสินใจอย่างไร
- เขียนสคริปต์พิเศษที่จะใช้ครั้งเดียวพร้อมกับการย้ายข้อมูลและนำข้อมูลมาอยู่ในรูปแบบที่เหมาะสม นี่เป็นวิธีทั่วไปในการแก้ปัญหาการถ่ายโอนข้อมูลไปยังโครงสร้างใหม่หลังจากใช้การย้ายข้อมูล แต่สิ่งที่คล้ายกันสามารถนำไปใช้ก่อนได้ ในกรณีพิเศษ แน่นอนว่าเส้นทางนี้ไม่สามารถใช้ได้เสมอไป เนื่องจากการแก้ไขข้อมูลบนเซิร์ฟเวอร์ที่ใช้งานจริงอาจเป็นอันตรายและอาจเป็นอันตรายได้
- วิธีที่ยากอีกวิธีหนึ่งคือการแก้ไขชุดการแก้ไขที่มีอยู่ ปัญหาคือฐานข้อมูลทั้งหมดที่ถูกนำไปใช้ในรูปแบบที่มีอยู่แล้วจะต้องถูกกู้คืน ค่อนข้างเป็นไปได้ที่ทีมงานแบ็กเอนด์ทั้งหมดจะถูกบังคับให้เปิดตัวฐานข้อมูลภายในเครื่องตั้งแต่เริ่มต้น
- และวิธีที่เป็นสากลที่สุดคือการถ่ายโอนปัญหาด้วยข้อมูลไปยังสภาพแวดล้อมของนักพัฒนา สร้างสถานการณ์เดิมขึ้นใหม่ และเพิ่มชุดการแก้ไขใหม่ไปยังชุดการแก้ไขที่เสียหาย ซึ่งจะหลีกเลี่ยงปัญหา
โดยทั่วไป ยิ่งฐานข้อมูลมีความคล้ายคลึงกับองค์ประกอบของฐานข้อมูลเซิร์ฟเวอร์ที่ใช้งานจริงมากเท่าใด โอกาสที่ปัญหาเกี่ยวกับการโยกย้ายก็จะน้อยลงเท่านั้น และแน่นอน ก่อนที่คุณจะส่งเซ็ตการแก้ไขไปยังที่เก็บ คุณควรคิดหลายๆ ครั้งว่ามันจะเสียหายหรือไม่
สถานการณ์ที่ 3 Liquibase เริ่มใช้หลังจากเข้าสู่การผลิต
สมมติว่าหัวหน้าทีมขอให้ Petya รวม Liquibase ไว้ในโปรเจ็กต์ แต่โปรเจ็กต์อยู่ระหว่างการผลิตแล้วและมีโครงสร้างฐานข้อมูลอยู่แล้ว
ด้วยเหตุนี้ ปัญหาก็คือบนเซิร์ฟเวอร์หรือเครื่องสำหรับนักพัฒนาใหม่ ตารางเหล่านี้จะต้องถูกสร้างขึ้นใหม่ตั้งแต่ต้น และสภาพแวดล้อมที่มีอยู่จะต้องคงอยู่ในสถานะที่สอดคล้องกัน พร้อมที่จะยอมรับชุดการแก้ไขใหม่
ตัดสินใจอย่างไร
นอกจากนี้ยังมีหลายวิธี:
- สิ่งแรกและชัดเจนที่สุดคือการมีสคริปต์แยกต่างหากที่ต้องใช้ด้วยตนเองเมื่อเริ่มต้นสภาพแวดล้อมใหม่
- อย่างที่สองไม่ชัดเจนนัก ให้มีการโยกย้าย Liquibase ที่อยู่ในบริบท Liquibase อื่นแล้วนำไปใช้ คุณสามารถอ่านเพิ่มเติมเกี่ยวกับบริบท Liquibase ได้ที่นี่:
https://www.liquibase.org/documentation/contexts.html . โดยทั่วไปนี่เป็นกลไกที่น่าสนใจที่สามารถนำไปใช้ได้สำเร็จเช่นในการทดสอบ - เส้นทางที่สามประกอบด้วยหลายขั้นตอน ขั้นแรก ต้องสร้างการโยกย้ายสำหรับตารางที่มีอยู่ จากนั้นจะต้องนำไปใช้กับสภาพแวดล้อมบางอย่างและจะได้ผลรวมแฮชของมัน ขั้นตอนต่อไปคือการเริ่มต้นตาราง Liquibase ที่ว่างเปล่าบนเซิร์ฟเวอร์ที่ไม่ว่างเปล่าของเรา และในตารางที่มีประวัติการใช้ชุดการแก้ไข คุณสามารถใส่บันทึกเกี่ยวกับชุดการแก้ไข "ราวกับว่านำไปใช้" ด้วยตนเองพร้อมการเปลี่ยนแปลงที่มีอยู่แล้วในฐานข้อมูล . ดังนั้น บนเซิร์ฟเวอร์ที่มีอยู่ การนับถอยหลังประวัติจะเริ่มจากเวอร์ชัน 2 และสภาพแวดล้อมใหม่ทั้งหมดจะทำงานเหมือนกัน
สถานการณ์ที่ 4 การโยกย้ายกลายเป็นเรื่องใหญ่และไม่มีเวลาดำเนินการให้เสร็จสิ้น
ตามกฎแล้วในช่วงเริ่มต้นของการพัฒนาบริการ Liquibase จะถูกใช้เป็นการพึ่งพาภายนอก และการย้ายข้อมูลทั้งหมดจะถูกประมวลผลเมื่อแอปพลิเคชันเริ่มทำงาน อย่างไรก็ตาม เมื่อเวลาผ่านไป คุณอาจสะดุดกับกรณีต่อไปนี้:
- การโยกย้ายกลายเป็นเรื่องใหญ่และใช้เวลานานจึงจะเสร็จสมบูรณ์
- จำเป็นต้องมีการย้ายในสภาพแวดล้อมแบบกระจาย เช่น บนอินสแตนซ์เซิร์ฟเวอร์ฐานข้อมูลหลายอินสแตนซ์พร้อมกัน
ในกรณีนี้ การใช้การย้ายข้อมูลนานเกินไปจะส่งผลให้หมดเวลาเมื่อแอปพลิเคชันเริ่มทำงาน นอกจากนี้ การใช้การย้ายข้อมูลกับแต่ละอินสแตนซ์ของแอปพลิเคชันแยกกันอาจทำให้เซิร์ฟเวอร์ที่แตกต่างกันไม่ซิงค์กัน
ตัดสินใจอย่างไร
ในกรณีเช่นนี้ โปรเจ็กต์ของคุณมีขนาดใหญ่อยู่แล้ว หรือแม้แต่ผู้ใหญ่ด้วยซ้ำ และ Liquibase เริ่มทำหน้าที่เป็นเครื่องมือภายนอกที่แยกต่างหาก ความจริงก็คือ Liquibase ในฐานะไลบรารีถูกคอมไพล์เป็นไฟล์ jar และสามารถทำงานเป็นการพึ่งพาภายในโปรเจ็กต์หรือทำงานอิสระก็ได้
ในโหมดสแตนด์อโลน คุณสามารถปล่อยให้การดำเนินการโยกย้ายไปยังสภาพแวดล้อม CI/CD ของคุณ หรือปล่อยให้ผู้ดูแลระบบและผู้เชี่ยวชาญด้านการปรับใช้งานของคุณเป็นผู้มีอำนาจ ในการดำเนินการนี้คุณจะต้องมีบรรทัดคำสั่ง Liquibase
เอาท์พุต
ในความเป็นจริง อาจมีข้อผิดพลาดอีกมากมายเมื่อทำงานกับการย้ายฐานข้อมูล และหลายข้อผิดพลาดต้องใช้แนวทางที่สร้างสรรค์ สิ่งสำคัญคือต้องเข้าใจว่าหากคุณใช้เครื่องมืออย่างถูกต้อง ข้อผิดพลาดเหล่านี้ส่วนใหญ่ก็สามารถหลีกเลี่ยงได้ โดยเฉพาะอย่างยิ่ง ฉันต้องจัดการกับปัญหาที่ระบุไว้ทั้งหมดในรูปแบบที่แตกต่างกัน และบางปัญหาก็เป็นผลมาจากความผิดพลาดของฉัน แน่นอนว่าสิ่งนี้ส่วนใหญ่เกิดขึ้นเนื่องจากการไม่ตั้งใจ แต่บางครั้งเกิดจากการไม่สามารถใช้เครื่องมือทางอาญาได้
ที่มา: will.com