هجرات قاعدة البيانات: تحويل اليرقات إلى فراشات
نشرت: 2022-03-11لا يهتم المستخدمون بما يوجد داخل البرنامج الذي يستخدمونه ؛ فقط لأنه يعمل بسلاسة وأمان وبدون تمييز. يسعى المطورون لتحقيق ذلك ، وإحدى المشكلات التي يحاولون حلها هي كيفية التأكد من أن مخزن البيانات في حالة مناسبة للإصدار الحالي من المنتج. يتطور البرنامج ، وقد يتغير نموذج البيانات الخاص به أيضًا بمرور الوقت ، على سبيل المثال ، لإصلاح أخطاء التصميم. لزيادة تعقيد المشكلة ، قد يكون لديك عدد من بيئات الاختبار أو العملاء الذين ينتقلون إلى الإصدارات الأحدث من المنتج في خطوات مختلفة. لا يمكنك فقط توثيق بنية المتجر وما هي المعالجات اللازمة لاستخدام الإصدار الجديد اللامع من منظور واحد.
انضممت ذات مرة إلى مشروع يحتوي على عدد قليل من قواعد البيانات بهياكل تم تحديثها عند الطلب ، مباشرة من قبل المطورين. هذا يعني أنه لا توجد طريقة واضحة لمعرفة التغييرات التي يجب تطبيقها لترحيل البنية إلى أحدث إصدار ولم يكن هناك مفهوم للإصدار على الإطلاق! كان هذا خلال حقبة ما قبل DevOps وسيعتبر فوضى تامة في الوقت الحاضر. قررنا تطوير أداة يمكن استخدامها لتطبيق كل تغيير على قاعدة البيانات المحددة. كان لديه هجرات وسيوثق تغييرات المخطط. جعلنا هذا واثقين من أنه لن تكون هناك تغييرات عرضية وأن حالة المخطط ستكون متوقعة.
في هذه المقالة ، سنلقي نظرة على كيفية تطبيق عمليات ترحيل مخطط قاعدة البيانات العلائقية وكيفية التغلب على المشكلات المصاحبة.
بادئ ذي بدء ، ما هي عمليات ترحيل قاعدة البيانات؟ في سياق هذه المقالة ، الترحيل عبارة عن مجموعة من التغييرات التي يجب تطبيقها على قاعدة البيانات. يعد إنشاء أو إسقاط جدول أو عمود أو فهرس أمثلة شائعة على عمليات الترحيل. قد يتغير شكل مخططك بشكل كبير بمرور الوقت ، خاصةً إذا بدأ التطوير عندما كانت المتطلبات لا تزال غامضة. لذلك ، على مدار العديد من المعالم الرئيسية في الطريق إلى الإصدار ، سيكون نموذج البيانات الخاص بك قد تطور وربما أصبح مختلفًا تمامًا عما كان عليه في البداية. الهجرات هي مجرد خطوات إلى الحالة المستهدفة.
للبدء ، دعنا نستكشف ما لدينا في صندوق الأدوات الخاص بنا لتجنب إعادة اختراع ما تم إنجازه جيدًا بالفعل.
أدوات
في كل لغة مستخدمة على نطاق واسع ، توجد مكتبات تساعد في تسهيل عمليات ترحيل قاعدة البيانات. على سبيل المثال ، في حالة Java ، فإن الخيارات الشائعة هي Liquibase و Flyway. سنستخدم Liquibase أكثر في الأمثلة ، لكن المفاهيم تنطبق على حلول أخرى ولا ترتبط بـ Liquibase.
لماذا تهتم باستخدام مكتبة منفصلة لترحيل المخطط إذا كانت بعض ORM توفر بالفعل خيارًا لترقية المخطط تلقائيًا وجعله يتطابق مع بنية الفئات المعينة؟ من الناحية العملية ، لا تقوم عمليات الترحيل التلقائية هذه إلا بتغييرات بسيطة في المخطط ، على سبيل المثال ، إنشاء جداول وأعمدة ، ولا يمكنها القيام بأشياء قد تكون مدمرة مثل إفلات كائنات قاعدة البيانات أو إعادة تسميتها. لذا ، فإن الحلول غير التلقائية (ولكن لا تزال مؤتمتة) عادة ما تكون خيارًا أفضل لأنك مجبر على وصف منطق الترحيل بنفسك ، وأنت تعرف بالضبط ما سيحدث لقاعدة البيانات الخاصة بك.
إنها أيضًا فكرة سيئة للغاية أن تقوم بخلط تعديلات المخطط الآلي واليدوية لأنك قد تنتج مخططات فريدة وغير متوقعة إذا تم تطبيق التغييرات اليدوية بترتيب خاطئ أو لم يتم تطبيقها على الإطلاق ، حتى لو كانت مطلوبة. بمجرد اختيار الأداة ، استخدمها لتطبيق جميع عمليات ترحيل المخطط.
عمليات ترحيل قاعدة البيانات النموذجية
تتضمن عمليات الترحيل النموذجية إنشاء تسلسلات وجداول وأعمدة ومفاتيح أساسية وخارجية وفهارس وكائنات قاعدة بيانات أخرى. بالنسبة لمعظم أنواع التغييرات الشائعة ، يوفر Liquibase عناصر تعريفية مميزة لوصف ما يجب القيام به. سيكون من الممل جدًا أن تقرأ عن كل تغيير تافه تدعمه Liquibase أو أدوات أخرى مماثلة. للحصول على فكرة عن شكل التغييرات ، ضع في اعتبارك المثال التالي حيث نقوم بإنشاء جدول (تم حذف إعلانات مساحة اسم XML للإيجاز):
<?xml version="1.0" encoding="UTF-8"?> <databaseChangeLog> <changeSet author="demo"> <createTable tableName="PRODUCT"> <column name="ID" type="BIGINT"> <constraints primaryKey="true" primaryKeyName="PK_PRODUCT"/> </column> <column name="CODE" type="VARCHAR(50)"> <constraints nullable="false" unique="true" uniqueConstraintName="UC_PRODUCT_CODE"/> </column> </createTable> </changeSet> </databaseChangeLog>
كما ترى ، فإن التغيير عبارة عن مجموعة من التغييرات ، وتتكون مجموعات التغييرات من التغييرات. يمكن دمج تغييرات بسيطة مثل createTable
لتنفيذ عمليات ترحيل أكثر تعقيدًا ؛ على سبيل المثال ، لنفترض أنك بحاجة إلى تحديث رمز المنتج لجميع المنتجات. يمكن تحقيقه بسهولة من خلال التغيير التالي:
<sql>UPDATE product SET code = 'new_' || code</sql>
سوف يتأثر الأداء إذا كان لديك عدد لا يحصى من المنتجات. لتسريع الترحيل ، يمكننا إعادة كتابته في الخطوات التالية:
- قم بإنشاء جدول جديد للمنتجات باستخدام
createTable
، تمامًا كما رأينا سابقًا. في هذه المرحلة ، من الأفضل إنشاء أقل عدد ممكن من القيود. دعنا نسمي الجدول الجديدPRODUCT_TMP
. - قم بملء
PRODUCT_TMP
بـ SQL على شكلINSERT INTO ... SELECT ...
باستخدام تغييرsql
. - قم بإنشاء جميع القيود (
addNotNullConstraint
وaddUniqueConstraint
وaddForeignKeyConstraint
) والفهارس (createIndex
) التي تحتاجها. - أعد تسمية جدول
PRODUCT
إلى شيء مثلPRODUCT_BAK
. يمكن لـ Liquibase القيام بذلك باستخدامrenameTable
. - أعد تسمية
PRODUCT_TMP
إلىPRODUCT
(مرة أخرى ، باستخدامrenameTable
). - اختياريًا ، قم بإزالة
PRODUCT_BAK
باستخدامdropTable
.
بالطبع ، من الأفضل تجنب مثل هذه الهجرات ، لكن من الجيد معرفة كيفية تنفيذها في حال واجهتك إحدى تلك الحالات النادرة التي تحتاج إليها.
إذا كنت تعتبر XML أو JSON أو YAML غريبًا جدًا بالنسبة لمهمة وصف التغييرات ، فما عليك سوى استخدام SQL العادي واستخدام جميع الميزات الخاصة ببائعي قواعد البيانات. أيضا ، يمكنك تنفيذ أي منطق مخصص في عادي جافا.
قد تؤدي الطريقة التي يعفيك بها Liquibase من كتابة SQL الخاصة بقاعدة البيانات الفعلية إلى الثقة المفرطة ، ولكن يجب ألا تنسى المراوغات في قاعدة البيانات المستهدفة ؛ على سبيل المثال ، عند إنشاء مفتاح خارجي ، قد يتم إنشاء فهرس أو لا يتم إنشاؤه ، اعتمادًا على نظام إدارة قاعدة البيانات المحدد المستخدم. نتيجة لذلك ، قد تجد نفسك في موقف حرج. يسمح لك Liquibase بتحديد وجوب تشغيل مجموعة التغييرات فقط لنوع معين من قواعد البيانات ، على سبيل المثال ، PostgreSQL أو Oracle أو MySQL. يجعل ذلك ممكنًا باستخدام نفس مجموعات التغييرات غير المحددة للبائع لقواعد بيانات مختلفة ، وللمجموعات الأخرى ، باستخدام بنية وميزات خاصة بالبائع. لن يتم تنفيذ التغييرات التالية إلا في حالة استخدام قاعدة بيانات Oracle:
<changeSet dbms="oracle" author="..."> ... </changeSet>
إلى جانب Oracle ، يدعم Liquibase بعض قواعد البيانات الأخرى خارج الصندوق.
تسمية كائنات قاعدة البيانات
يجب تسمية كل كائن قاعدة بيانات تقوم بإنشائه. لا يلزمك تقديم اسم صريح لبعض أنواع الكائنات ، على سبيل المثال ، للقيود والفهارس. لكن هذا لا يعني أن هذه الكائنات لن تحمل أسماء ؛ سيتم إنشاء أسمائهم بواسطة قاعدة البيانات على أي حال. تظهر المشكلة عندما تحتاج إلى الرجوع إلى هذا الكائن لإسقاطه أو تغييره. لذلك من الأفضل منحهم أسماء صريحة. لكن هل هناك أي قواعد بشأن الأسماء التي يجب ذكرها؟ الجواب قصير: كن متسقا. على سبيل المثال ، إذا قررت تسمية فهارس مثل هذا: IDX_<table>_<columns>
، فيجب تسمية فهرس لعمود CODE
المذكور أعلاه IDX_PRODUCT_CODE
.
اصطلاحات التسمية مثيرة للجدل بشكل لا يصدق ، لذلك لن نفترض أن نعطي تعليمات شاملة هنا. كن متسقًا ، واحترم فريقك أو اتفاقيات المشروع ، أو اخترعها فقط إذا لم تكن موجودة.
تنظيم التغييرات
أول شيء يجب أن تقرره هو مكان تخزين التغييرات. هناك طريقتان أساسيتان:
- حافظ على مجموعات التغييرات مع رمز التطبيق. من الملائم القيام بذلك لأنه يمكنك الالتزام بمجموعات التغييرات وكود التطبيق ومراجعتها معًا.
- احتفظ بالتغييرات ورمز التطبيق منفصلين ، على سبيل المثال ، في مستودعات VCS منفصلة. يعد هذا الأسلوب مناسبًا عندما يتم مشاركة نموذج البيانات عبر العديد من التطبيقات ويكون من الملائم تخزين جميع مجموعات التغييرات في مستودع مخصص وليس تشتيتها عبر مستودعات متعددة حيث توجد كود التطبيق.
أينما قمت بتخزين التغييرات ، فمن المعقول عمومًا تقسيمها إلى الفئات التالية:
- عمليات الترحيل المستقلة التي لا تؤثر على النظام قيد التشغيل. عادةً ما يكون من الآمن إنشاء جداول وتسلسلات جديدة وما إلى ذلك ، إذا لم يكن التطبيق المنشور حاليًا على علم بها بعد.
- تعديلات المخطط التي تغير هيكل المتجر ، على سبيل المثال ، إضافة أو إسقاط الأعمدة والفهارس. لا ينبغي تطبيق هذه التغييرات أثناء استخدام إصدار أقدم من التطبيق لأن القيام بذلك قد يؤدي إلى أقفال أو سلوك غريب بسبب التغييرات في المخطط.
- عمليات الترحيل السريعة التي تقوم بإدراج أو تحديث كميات ضئيلة من البيانات. في حالة نشر تطبيقات متعددة ، يمكن تنفيذ التغييرات من هذه الفئة بشكل متزامن دون التقليل من أداء قاعدة البيانات.
- من المحتمل أن تكون عمليات الترحيل بطيئة تقوم بإدراج الكثير من البيانات أو تحديثها. من الأفضل تطبيق هذه التغييرات في حالة عدم تنفيذ عمليات ترحيل أخرى مماثلة.
يجب تشغيل مجموعات الترحيل هذه على التوالي قبل نشر إصدار أحدث من التطبيق. يصبح هذا النهج أكثر عملية إذا كان النظام يتكون من عدة تطبيقات منفصلة ويستخدم بعضها نفس قاعدة البيانات. بخلاف ذلك ، يجدر فصل مجموعات التغييرات التي يمكن تطبيقها فقط دون التأثير على التطبيقات قيد التشغيل ، ويمكن تطبيق مجموعات التغييرات المتبقية معًا.

بالنسبة للتطبيقات الأكثر بساطة ، يمكن تطبيق المجموعة الكاملة من عمليات الترحيل الضرورية عند بدء تشغيل التطبيق. في هذه الحالة ، تندرج جميع مجموعات التغييرات في فئة واحدة ويتم تشغيلها كلما تمت تهيئة التطبيق.
مهما كانت المرحلة التي يتم اختيارها لتطبيق عمليات الترحيل ، فمن الجدير بالذكر أن استخدام نفس قاعدة البيانات لتطبيقات متعددة قد يتسبب في حدوث أقفال عند تطبيق عمليات الترحيل. يستخدم Liquibase (مثل العديد من الحلول المماثلة الأخرى) جدولين خاصين لتسجيل البيانات الوصفية: DATABASECHANGELOG
و DATABASECHANGELOGLOCK
. يتم استخدام الأول لتخزين المعلومات حول مجموعات التغييرات المطبقة ، والأخير لمنع عمليات الترحيل المتزامنة داخل مخطط قاعدة البيانات نفسه. لذلك ، إذا كان لابد من استخدام تطبيقات متعددة نفس مخطط قاعدة البيانات لسبب ما ، فمن الأفضل استخدام الأسماء غير الافتراضية لجداول بيانات التعريف لتجنب عمليات التأمين.
الآن بعد أن أصبح الهيكل عالي المستوى واضحًا ، عليك أن تقرر كيفية تنظيم التغييرات داخل كل فئة.
يعتمد ذلك بشكل كبير على متطلبات التطبيق المحددة ، ولكن النقاط التالية عادة ما تكون معقولة:
- احتفظ بسجلات التغيير مجمعة حسب إصدارات منتجك. قم بإنشاء دليل جديد لكل إصدار ووضع ملفات سجل التغيير المقابلة فيه. احصل على سجل تغيير جذري وقم بتضمين سجلات التغيير التي تتوافق مع الإصدارات. في سجلات التغيير للإصدار ، قم بتضمين سجلات التغيير الأخرى التي تشتمل على هذا الإصدار.
- احصل على اصطلاح تسمية لملفات التغيير ومعرفات مجموعة التغييرات - واتبعها بالطبع.
- تجنب التغييرات مع الكثير من التغييرات. قم بتفضيل عدة تغييرات على مجموعة تغييرات واحدة طويلة.
- إذا كنت تستخدم الإجراءات المخزنة وتحتاج إلى تحديثها ، ففكر في استخدام
runOnChange="true"
لمجموعة التغييرات التي تمت إضافة الإجراء المخزن فيها. بخلاف ذلك ، في كل مرة يتم تحديثها ، ستحتاج إلى إنشاء مجموعة تغييرات جديدة بإصدار جديد من الإجراء المخزن. تختلف المتطلبات ، ولكن غالبًا ما يكون من المقبول عدم تتبع هذا السجل. - ضع في اعتبارك سحق التغييرات الزائدة عن الحاجة قبل دمج فروع الميزات. في بعض الأحيان ، يحدث أنه في فرع الميزة (خاصة في فرع طويل العمر) تقوم التغييرات اللاحقة بتحسين التغييرات التي تم إجراؤها في مجموعات التغييرات السابقة. على سبيل المثال ، يمكنك إنشاء جدول ثم تقرر إضافة المزيد من الأعمدة إليه. يجدر إضافة هذه الأعمدة إلى تغيير
createTable
الأولي إذا لم يتم دمج فرع الميزة هذا في الفرع الرئيسي بعد. - استخدم نفس سجلات التغيير لإنشاء قاعدة بيانات اختبار. إذا حاولت القيام بذلك ، فقد تكتشف قريبًا أنه ليست كل مجموعة تغييرات قابلة للتطبيق على بيئة الاختبار ، أو أن هناك حاجة إلى مجموعات تغييرات إضافية لبيئة الاختبار المحددة هذه. باستخدام Liquibase ، يتم حل هذه المشكلة بسهولة باستخدام السياقات . ما عليك سوى إضافة
context="test"
السمة إلى التغييرات التي يجب تنفيذها فقط مع الاختبارات ، ثم قم بتهيئة Liquibase مع تمكين سياقtest
.
التراجع
مثل الحلول المماثلة الأخرى ، يدعم Liquibase مخطط الترحيل "لأعلى" و "لأسفل". لكن كن حذرًا: قد لا يكون التراجع عن عمليات الترحيل أمرًا سهلاً ، ولا يستحق دائمًا الجهد المبذول. إذا قررت دعم التراجع عن عمليات الترحيل لتطبيقك ، فكن متسقًا وافعل ذلك مع كل مجموعة تغييرات قد تحتاج إلى التراجع عنها. باستخدام Liquibase ، يتم التراجع عن مجموعة التغييرات عن طريق إضافة علامة rollback
تحتوي على التغييرات المطلوبة لإجراء التراجع. ضع في اعتبارك المثال التالي:
<changeSet author="..."> <createTable tableName="PRODUCT"> <column name="ID" type="BIGINT"> <constraints primaryKey="true" primaryKeyName="PK_PRODUCT"/> </column> <column name="CODE" type="VARCHAR(50)"> <constraints nullable="false" unique="true" uniqueConstraintName="UC_PRODUCT_CODE"/> </column> </createTable> <rollback> <dropTable tableName="PRODUCT"/> </rollback> </changeSet>
يعد التراجع الصريح زائداً عن الحاجة هنا لأن Liquibase سينفذ نفس إجراءات التراجع. Liquibase قادر على التراجع تلقائيًا عن معظم أنواع التغييرات المدعومة ، على سبيل المثال ، createTable
أو addColumn
أو createIndex
.
إصلاح الماضي
لا يوجد أحد كامل ، وكلنا نرتكب أخطاء. قد يتم اكتشاف بعضها بعد فوات الأوان عند تطبيق التغييرات التالفة بالفعل. دعنا نستكشف ما يمكن فعله لإنقاذ اليوم.
قم بتحديث قاعدة البيانات يدويًا
يتضمن العبث مع DATABASECHANGELOG
وقاعدة البيانات الخاصة بك بالطرق التالية:
- إذا كنت تريد تصحيح التغييرات السيئة وتنفيذها مرة أخرى:
- قم بإزالة الصفوف من
DATABASECHANGELOG
التي تتوافق مع التغييرات. - إزالة جميع الآثار الجانبية التي أدخلتها التغييرات ؛ على سبيل المثال ، استعادة الجدول إذا تم إسقاطه.
- إصلاح التغييرات السيئة.
- قم بتشغيل عمليات الترحيل مرة أخرى.
- قم بإزالة الصفوف من
- إذا كنت تريد تصحيح التغييرات السيئة ولكن تخطي تطبيقها مرة أخرى:
- قم بتحديث
DATABASECHANGELOG
عن طريق تعيين قيمة الحقلMD5SUM
إلىNULL
لتلك الصفوف التي تتوافق مع التغييرات السيئة. - إصلاح الأخطاء في قاعدة البيانات يدويًا. على سبيل المثال ، إذا تمت إضافة عمود بنوع خاطئ ، فقم بإصدار استعلام لتعديل نوعه.
- إصلاح التغييرات السيئة.
- قم بتشغيل عمليات الترحيل مرة أخرى. سيقوم Liquibase بحساب المجموع الاختباري الجديد وحفظه في
MD5SUM
. لن يتم تشغيل مجموعات التغييرات المصححة مرة أخرى.
- قم بتحديث
من الواضح أنه من السهل القيام بهذه الحيل أثناء التطوير ، ولكن يصبح الأمر أكثر صعوبة إذا تم تطبيق التغييرات على قواعد بيانات متعددة.
اكتب تغييرات تصحيحية
في الممارسة العملية ، عادة ما يكون هذا النهج أكثر ملاءمة. قد تتساءل ، لماذا لا تقوم فقط بتحرير مجموعة التغييرات الأصلية؟ الحقيقة هي أنه يعتمد على ما يجب تغييره. يحسب Liquibase مجموع اختباري لكل مجموعة تغييرات ويرفض تطبيق تغييرات جديدة إذا كان المجموع الاختباري جديدًا لواحد على الأقل من مجموعات التغييرات المطبقة مسبقًا. يمكن تخصيص هذا السلوك على أساس كل تغيير عن طريق تحديد runOnChange="true"
. لا يتأثر المجموع الاختباري إذا قمت بتعديل الشروط المسبقة أو سمات مجموعة التغييرات الاختيارية ( context
، runOnChange
، إلخ).
الآن ، قد تتساءل ، كيف يمكنك في النهاية تصحيح التغييرات بالأخطاء؟
- إذا كنت ترغب في استمرار تطبيق هذه التغييرات على المخططات الجديدة ، فما عليك سوى إضافة مجموعات التغييرات التصحيحية. على سبيل المثال ، إذا تمت إضافة عمود بنوع خاطئ ، فقم بتعديل نوعه في مجموعة التغييرات الجديدة.
- إذا كنت ترغب في التظاهر بأن هذه التغييرات السيئة لم تكن موجودة أبدًا ، فقم بما يلي:
- قم بإزالة مجموعات التغييرات أو أضف سمة
context
بقيمة تضمن أنك لن تحاول أبدًا تطبيق عمليات الترحيل مع مثل هذا السياق مرة أخرى ، على سبيل المثال ،context="graveyard-changesets-never-run"
. - أضف مجموعات تغييرات جديدة إما أن ترجع ما تم القيام به بشكل خاطئ أو تعمل على إصلاحه. يجب تطبيق هذه التغييرات فقط إذا تم تطبيق تغييرات سيئة. يمكن تحقيقه بشروط مسبقة ، مثل
changeSetExecuted
. لا تنس إضافة تعليق يشرح سبب قيامك بذلك. - أضف مجموعات تغييرات جديدة تعدل مخطط قاعدة البيانات بالطريقة الصحيحة.
- قم بإزالة مجموعات التغييرات أو أضف سمة
كما ترى ، فإن إصلاح الماضي ممكن ، على الرغم من أنه قد لا يكون دائمًا مباشرًا.
تخفيف الآلام المتزايدة
مع تقدم التطبيق الخاص بك ، يزداد أيضًا سجل التغيير الخاص به ، مما يؤدي إلى تراكم كل تغيير في المخطط على طول المسار. إنه حسب التصميم ، ولا يوجد خطأ بطبيعته في هذا. يمكن جعل سجلات التغيير الطويلة أقصر عن طريق سحق عمليات الترحيل بانتظام ، على سبيل المثال ، بعد إصدار كل إصدار من المنتج. في بعض الحالات ، قد يجعل تهيئة مخطط قاعدة البيانات الجديد أسرع.
لا يعد الاسكواش أمرًا تافهًا دائمًا وقد يتسبب في حدوث تراجع دون تحقيق العديد من الفوائد. هناك خيار آخر رائع وهو استخدام قاعدة بيانات أولية لتجنب تنفيذ جميع التغييرات. إنه مناسب تمامًا لاختبار البيئات إذا كنت بحاجة إلى قاعدة بيانات جاهزة بأسرع ما يمكن ، وربما حتى مع بعض بيانات الاختبار. قد تفكر في الأمر على أنه شكل من أشكال الضغط لمجموعات التغييرات: في مرحلة ما (على سبيل المثال ، بعد إصدار نسخة أخرى) ، تقوم بعمل تفريغ للمخطط. بعد استعادة ملف التفريغ ، يمكنك تطبيق عمليات الترحيل كالمعتاد. سيتم تطبيق التغييرات الجديدة فقط لأنه تم تطبيق التغييرات القديمة بالفعل قبل إجراء التفريغ ؛ لذلك ، تمت استعادتهم من المكب.
خاتمة
لقد تجنبنا عمدًا الغوص بشكل أعمق في ميزات Liquibase لتقديم مقال قصير ومباشر يركز على المخططات المتطورة بشكل عام. نأمل أن يكون من الواضح ما هي الفوائد والمشكلات التي تحدث عن طريق التطبيق الآلي لترحيل مخطط قاعدة البيانات ومدى ملاءمتها لثقافة DevOps. من المهم عدم تحويل الأفكار الجيدة إلى عقيدة. تختلف المتطلبات ، وبصفتنا مهندسي قواعد بيانات ، يجب أن تعزز قراراتنا دفع المنتج إلى الأمام وليس مجرد الالتزام بالتوصيات من شخص ما على الإنترنت.