- เครื่องมือแบบ CLI สำหรับจัดการการย้ายข้อมูลฐานข้อมูลโดยเปรียบเทียบ ความแตกต่าง (diff) ระหว่าง SQL schema
- สามารถจัดการสคีมาของ RDBMS ได้ด้วย ไวยากรณ์ SQL DDL แบบทั่วไป
- รองรับฐานข้อมูลหลักอย่าง MySQL, MariaDB, TiDB, PostgreSQL, SQL Server, SQLite3
- บนเว็บไซต์มีเดโมออนไลน์ที่ใช้ WebAssembly build ให้ทดลองฟังก์ชันเปรียบเทียบสคีมาและสร้าง DDL ได้
- สามารถจัดการงานเปลี่ยนแปลงฐานข้อมูลแบบ idempotent ได้ จึงมีประโยชน์ต่อการซิงก์สคีมาอย่างเสถียร
ภาพรวมของ sqldef
- sqldef เป็นเครื่องมือ CLI ที่เปรียบเทียบความแตกต่าง (diff) ของ SQL schema สองชุด วิเคราะห์ความต่าง และ สร้างคำสั่ง DDL จากผลลัพธ์
- ผู้ใช้สามารถเปรียบเทียบสคีมาปัจจุบันกับสคีมาเป้าหมายเพื่อหาการเปลี่ยนแปลงที่จำเป็นได้โดยอัตโนมัติ
- สามารถทำ migration ได้โดยใช้ไวยากรณ์ SQL DDL ทั่วไปตามเดิม
- ระบุฐานข้อมูลที่รองรับไว้คือ MySQL, MariaDB, TiDB, PostgreSQL, SQL Server, SQLite3
ฟีเจอร์เดโมออนไลน์
- บนเว็บไซต์มี Online Demo ให้ใช้งาน สามารถดูการเปลี่ยนแปลงของสคีมาได้แบบเห็นภาพ
- ใช้ตัวเลือก “Enable DROP” เพื่อควบคุมว่าจะรวมคำสั่งลบหรือไม่
- ในส่วน “Up (current → desired)” จะแสดงตัวอย่าง DDL เช่น การเพิ่มคอลัมน์ใหม่ การสร้างดัชนี และการเพิ่มข้อกำหนด
- ในส่วน “Down (desired → current)” มีตัวอย่างการเปลี่ยนแปลงย้อนกลับ เช่น การลบข้อกำหนด
วิธีการทำงาน
- เดโมออนไลน์ใช้ WebAssembly build ของ sqldef เพื่อเปรียบเทียบความแตกต่าง (diff) ของ SQL schema ภายในเบราว์เซอร์
- คำนวณความต่างระหว่างสคีมาสองชุด และสร้างคำสั่ง DDL ที่จำเป็นโดยอัตโนมัติจากผลลัพธ์
- สามารถดูซอร์สของ WebAssembly build ได้ผ่านลิงก์ไปยังที่เก็บบน GitHub
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ถ้าต้องการการรองรับที่ครอบคลุมกว่าสำหรับ Postgres ลองดู pgschema ที่ผมทำไว้ได้
ตอนแรกเมื่อหน้าร้อนปีที่แล้วผมคิดว่ามันเสร็จค่อนข้างสมบูรณ์แล้ว แต่หลังจากแก้ ปัญหากว่า 100 รายการ ที่ผู้ใช้รายงานเข้ามาในช่วง 6 เดือน ผมก็ได้รู้ว่าตัวเองมองโลกสวยแค่ไหน
อยากรู้ว่ารองรับการตรวจหาความไม่สอดคล้องกันข้ามหลายคลัสเตอร์ฐานข้อมูลด้วยไหม
ลองทดสอบกับ SQLite แล้วพบว่าสำหรับมิเกรชันที่ยากอย่างการเพิ่มข้อจำกัด foreign key ให้ตารางเดิม มันสร้าง SQL ที่ใช้ไม่ได้
ตัวอย่างเช่น ไวยากรณ์แบบ
ALTER TABLE books ADD CONSTRAINT fk_books_author FOREIGN KEY (author_id) REFERENCES authors (id)ไม่ได้รับอนุญาตใน SQLiteดูเอกสารที่เกี่ยวข้องได้ที่ SQLite ALTER TABLE
ผมใช้ Atlas
ทั้งแนวทางแบบอิงมิเกรชันและแบบอิงสคีมาต่างก็มีข้อดีข้อเสีย เลยใช้ทั้งสองแบบควบคู่กันในโปรเจกต์เดียว
แบบอิงสคีมาช่วยให้พัฒนาได้เร็วขึ้น ส่วนแบบอิงมิเกรชันช่วยให้ การปล่อยขึ้นระบบมั่นใจได้มากกว่า
Atlas สร้างมิเกรชันให้อัตโนมัติใน PR ดังนั้นนักพัฒนาส่วนใหญ่จึงไม่ต้องจัดการเวิร์กโฟลว์แบบ versioned เองโดยตรง
เอกสารที่เกี่ยวข้อง: Declarative vs Versioned Workflows, Atlas Action
ผมชอบที่มันรองรับ migration flow แบบชัดเจน อยากรู้ให้แน่ชัดว่าจะมีการเปลี่ยนแปลงอะไรถูกนำไปใช้ก่อน deploy จริง
สงสัยว่ามีเครื่องมือดี ๆ ที่รองรับ background migration ไหม
เช่น เพิ่มคอลัมน์ชั่วคราวที่ nullable ให้กับตารางขนาดใหญ่ จากนั้นให้โค้ดใหม่เริ่มเขียนข้อมูลลงคอลัมน์นั้น แล้วค่อยเติมข้อมูลเดิมเป็นชุด ๆ ในเบื้องหลัง สุดท้ายจึงเปลี่ยนให้เป็น non-nullable
ถ้ามีเครื่องมือที่ทำให้แสดงการเปลี่ยนแปลงเชิงกระบวนการแบบนี้ในรูป declarative และสามารถ รีวิว·ทดสอบ ไปพร้อมกับโค้ดได้ก็น่าจะดีมาก
ตอนนี้ส่วนใหญ่ยังจัดการด้วย สคริปต์ชั่วคราวกับคู่มือ deploy แบบ manual
ตั้งค่าในสภาพแวดล้อมพัฒนาได้ง่าย และมีตัวอย่างอย่าง FastEndpoints-SqlJobQueues
เครื่องมือนี้เจ๋งมาก
มันทำให้ผมเลิกทำ โปรเจกต์งานอดิเรก ที่กำลังจะสร้างฟีเจอร์เดียวกันได้เลย
แทนที่จะทำอันนั้น ผมคงไปเริ่มโปรเจกต์ใหม่อีกอันที่มีคนแก้ไปแล้วราว 100 ครั้ง — อย่างเช่นเครื่องมือง่าย ๆ ที่คอยมอนิเตอร์ log ของ systemd แล้วส่งอีเมลเมื่อเกิด error
ดีใจที่นี่ไม่ใช่ migration manager อีกตัว แต่เป็น เครื่องมือเล็ก ๆ ที่มีประโยชน์
ให้ความรู้สึกเหมือนเข้ามาอุดจุดอ่อนของ SQL ได้ดี ถ้าเป็นแบบ declarative เหมือน Spanner DDL ได้ก็คงดี
บน Postgres ผมพยายามทำให้สคริปต์สคีมาเป็นแบบ idempotent โดยเริ่มด้วย
CREATE TABLE IF NOT EXISTSแล้วแยกALTERไว้ต่างหากเมื่อต้องเพิ่มคอลัมน์ใหม่แต่พอเวลาผ่านไปสคริปต์ก็เริ่มซับซ้อนขึ้น และเมื่อทุกอย่างนิ่งแล้วก็ค่อยเก็บกวาดคำสั่ง ALTER
ถ้าต้อง restore จากแบ็กอัปเก่า เครื่องมือแบบนี้น่าจะช่วยปรับความเข้ากันได้ให้ตรงกันได้เร็ว
อยากรู้ว่าเทียบกับ Entity Framework หรือ sqitch/liquibase แล้วเป็นอย่างไร
ผมเข้าใจแนวทางแบบ declarative แต่สำหรับ DB production ขนาดใหญ่ มิเกรชันไม่ได้เป็นเรื่อง declarative ล้วน ๆ
ตัวจัดการสคีมาที่ดีในอุดมคติควรเข้าใจ ต้นทุนของ query และกลยุทธ์ลด downtime
การเพิ่มคอลัมน์หรือเปลี่ยนดัชนีอาจทำให้เกิดการสแกนทั้งตารางได้
เช่น ถ้าจะแยก Fullname ออกเป็น FirstName และ LastName การทำ diff อย่างเดียวจะแสดงได้แค่ครึ่งเดียว
ใน EF Core จะใช้เมธอด Up/Down เพื่อจัดการ การแปลงที่ย้อนกลับได้
เลยสงสัยว่าถ้าไม่มีแนวคิดแบบนี้จะจัดการการแปลงข้อมูลอย่างไร
พวกเราเคยสร้างเครื่องมือแปลงของตัวเองที่อิง XML
XML แยกวิเคราะห์ได้ง่ายกว่า SQL ดังนั้นเราจึงเปรียบเทียบสคีมาที่นิยามใน XML กับฐานข้อมูล แล้วใช้เฉพาะการเปลี่ยนแปลงที่จำเป็น
เราใช้ Sybase SQLAnywhere และเมื่อต้องเพิ่มหรือลบคอลัมน์ในกรณีที่มี materialized view พัวพันอยู่ ความซับซ้อนจะสูงเพราะต้องสร้าง view และ index ใหม่
เพราะแบบนั้นเราจึงใส่กลไกป้องกันไว้ โดยอนุญาตให้ลบคอลัมน์ได้เฉพาะเมื่อระบุชัดเจนเท่านั้น และเปลี่ยนชนิดข้อมูลได้เฉพาะกรณีที่ปลอดภัย
มันทำให้การมิเกรตในสภาพแวดล้อมติดตั้งแบบ on-premises หลายร้อยแห่ง ง่ายมาก
แค่แก้ XML แล้วเครื่องมือจะจัดการที่เหลือให้เอง และยังเพิ่มความสามารถใหม่ได้เมื่อจำเป็น
ใน SQLite การจัดการการลบคอลัมน์ยังทำได้ไม่ดี
แม้เวอร์ชันใหม่ ๆ จะเพิ่งเพิ่ม DROP COLUMN เข้ามา แต่บนอุปกรณ์ส่วนใหญ่ก็ยังไม่รองรับอยู่ดี
ในตัวอย่างมีการเพิ่ม
x integer not nullแล้วลอง DROP แต่กลับขึ้นแค่ข้อความ “-- Skipped”วิธีมาตรฐานคือ สร้างตารางชั่วคราว คัดลอกข้อมูล แล้วสลับแทนที่ แต่เครื่องมือนี้ไม่ได้ทำให้โดยอัตโนมัติ
ถ้ามี constraint เข้ามาเกี่ยวข้องก็เป็นจุดที่พลาดได้ง่าย เลยค่อนข้างน่าเสียดาย
สุดท้ายถ้าจัดการได้แค่งานง่าย ๆ ก็รู้สึกว่าทำเองด้วยมืออาจดีกว่า
เครื่องมือนี้ดูเหมือนจะมีประโยชน์แค่กับ ฐานข้อมูลว่างเปล่า
มันจัดการ data migration ไม่ได้ และใช้ไม่ได้กับตารางที่มีข้อมูลจริงในกรณีอย่างการเปลี่ยนคอลัมน์ JSONB ให้เป็นรูปแบบที่มีโครงสร้าง หรือกรณีลบคอลัมน์แล้วทำ reverse migration จนสร้าง
ADD COLUMN … NOT NULLเป็นต้น