วิธีการเรียกใช้การย้ายฐานข้อมูลอย่างปลอดภัยด้วยอินสแตนซ์หลายแอป


10

เรามีแอปพลิเคชั่นที่ผสมผสานทั้งความรวดเร็ว (<1 วินาที) และการย้ายฐานข้อมูลที่ช้า (> 30 วินาที) ตอนนี้เรากำลังเรียกใช้การย้ายฐานข้อมูลเป็นส่วนหนึ่งของ CI แต่จากนั้นเครื่องมือ CI ของเราต้องรู้สตริงการเชื่อมต่อฐานข้อมูลทั้งหมดสำหรับแอปของเรา (ในหลาย ๆ สภาพแวดล้อม) ซึ่งไม่เหมาะ เราต้องการเปลี่ยนกระบวนการนี้เพื่อให้แอปพลิเคชันรันการย้ายฐานข้อมูลของตัวเองเมื่อเริ่มต้น

นี่คือสถานการณ์:

เรามีแอพพลิเคชั่นนี้หลายตัว - ประมาณ 5 ตัวในการผลิต มาเรียกพวกเขาnode1, ..., node5กัน แต่ละแอปเชื่อมต่อกับอินสแตนซ์ของ SQL Server เดียวและเราไม่ได้ใช้การปรับใช้แบบหมุนเวียน (แอพทั้งหมดจะถูกปรับใช้พร้อมกันเท่าที่ฉันรู้)

ปัญหา: ว่าเรามีการโยกย้ายที่ใช้เวลานาน ในกรณีนี้node1เริ่มต้นจากนั้นเริ่มดำเนินการโยกย้าย ตอนนี้node4เริ่มและการโยกย้ายที่ใช้เวลานานยังไม่เสร็จดังนั้นจึงnode4เริ่มการโยกย้าย -> ความเสียหายของข้อมูลที่เป็นไปได้หรือไม่ คุณจะป้องกันปัญหานี้อย่างไรหรือเป็นปัญหาที่สำคัญพอที่จะกังวลได้อย่างไร

ฉันกำลังคิดที่จะแก้ปัญหานี้ด้วยการล็อคแบบกระจาย AA (ใช้etcdหรืออะไรก็ได้ตามบรรทัดเหล่านั้น) โดยพื้นฐานแล้วแอพทั้งหมดพยายามที่จะได้รับการล็อคโดยมีเพียงหนึ่งในนั้นเท่านั้นที่ได้รับมันและเรียกใช้การย้ายข้อมูลจากนั้นปลดล็อค เมื่อแอปที่เหลือเริ่มต้นและเข้าสู่ส่วนที่สำคัญการโยกย้ายทั้งหมดจะถูกเรียกใช้แล้วสคริปต์การโยกย้ายก็จะออก

อย่างไรก็ตามลำไส้ของฉันกำลังพูดว่า "นี่มันเกินจะต้องมีวิธีแก้ปัญหาที่ง่ายกว่า" ดังนั้นฉันจึงคิดว่าฉันจะขอให้ที่นี่เพื่อดูว่าใครมีความคิดที่ดีกว่านี้อีก


1
วิธีการเกี่ยวกับการใช้ตาราง "สถานะการย้ายข้อมูล" เป็นล็อคส่วนกลาง / กระจายของคุณ แถวเดียวจะระบุว่าการโยกย้ายนั้นใช้งานอยู่ในปัจจุบันและอาจเป็นไปได้ว่าการโยกย้ายใดที่ถูกดำเนินการครั้งสุดท้าย
Bart van Ingen Schenau

คุณต้องการปรับใช้แอพแบบอะซิงโครนัสไหม
Ben

คำตอบ:


4

เนื่องจากคุณพูดถึงเซิร์ฟเวอร์ SQL: ตามโพสต์ DBA.SE อดีตการเปลี่ยนแปลงแบบแผนสามารถ (และควร) ถูกนำไปใช้ในการทำธุรกรรม สิ่งนี้ให้ความสามารถในการออกแบบการย้ายข้อมูลของคุณเช่นเดียวกับรูปแบบอื่น ๆ ของการเขียนพร้อมกันไปยังฐานข้อมูลของคุณ - คุณเริ่มทำธุรกรรมและเมื่อล้มเหลวคุณจะย้อนกลับ ที่ป้องกันสถานการณ์ความเสียหายฐานข้อมูลอย่างน้อยที่สุด (แม้ว่าธุรกรรมเพียงอย่างเดียวจะไม่ป้องกันการสูญหายของข้อมูลเมื่อมีขั้นตอนการโอนย้ายแบบทำลายล้างเช่นการลบคอลัมน์หรือตาราง)

จนถึงตอนนี้ฉันแน่ใจว่าคุณจะต้องมีmigrationsตารางที่มีการลงทะเบียนการย้ายข้อมูลที่ใช้ไปแล้วดังนั้นกระบวนการแอปพลิเคชันสามารถตรวจสอบว่ามีการใช้การโยกย้ายที่เฉพาะเจาะจงหรือไม่ จากนั้นใช้ "เลือกสำหรับการอัปเดต" เพื่อใช้การย้ายข้อมูลของคุณเช่นนี้ (รหัสเทียม):

  • เริ่มทำธุรกรรม
  • SELECT FROM Migrations FOR UPDATE WHERE MigrationLabel='MyMigration42'
  • หากคำสั่งเดิมส่งคืนค่าให้ยุติการทำธุรกรรม
  • ใช้การโยกย้าย (ย้อนกลับถ้ามันล้มเหลวเข้าสู่ระบบความล้มเหลวและจบการทำธุรกรรม)
  • INSERT 'MyMigration42' INTO Migrations(MigrationLabel)
  • สิ้นสุดการทำธุรกรรม

ที่สร้างกลไกการล็อคโดยตรงใน"คือการโยกย้ายใช้แล้ว"การทดสอบ

โปรดสังเกตว่าการออกแบบนี้จะช่วยให้ขั้นตอนการย้ายข้อมูลของคุณไม่ทราบว่าแอปพลิเคชันใดที่ใช้งานได้จริง - เป็นไปได้ว่าขั้นตอนที่ 1 ถูกนำไปใช้โดย app1, ขั้นตอนที่ 2 โดย app2, ขั้นตอนที่ 3 โดย app3 อีกครั้งและอื่น ๆ อย่างไรก็ตามเป็นความคิดที่ดีที่จะไม่ใช้การย้ายข้อมูลตราบใดที่อินสแตนซ์ของแอปอื่นกำลังใช้งานอยู่ การปรับใช้แบบขนานดังที่กล่าวไว้ในคำถามของคุณอาจสนใจข้อ จำกัด นี้อยู่แล้ว


1

บางทีคุณอาจพบห้องสมุดที่รองรับการย้ายฐานข้อมูลที่มีหลายโหนด

ฉันรู้เกี่ยวกับห้องสมุดสองแห่งในโลก Java ทั้งคู่สนับสนุนสิ่งที่คุณต้องการ:

  • Liquibase : จากคำถามที่พบบ่อยของพวกเขา: Liquibase ใช้ระบบล็อคแบบกระจายเพื่ออนุญาตให้กระบวนการหนึ่งอัพเดตฐานข้อมูลในแต่ละครั้ง กระบวนการอื่น ๆ จะรอจนกว่าการปลดล็อกจะเสร็จสิ้น
  • Flyway : จากหน้าดาวน์โหลดของพวกเขา: ปลอดภัยสำหรับหลายโหนดพร้อมกัน✓

อาจมีเครื่องมืออื่น ๆ สำหรับ Java และภาษาอื่นด้วย


ถ้าคุณไม่สามารถ (หรือไม่ต้องการ) ในการใช้เครื่องมือดังกล่าวตารางสามารถใช้เป็นล็อคหรือแม้กระทั่งเป็นบันทึกการโยกย้ายดูคำตอบของหมอสีน้ำตาลเช่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.