تواجه كل مؤسسة تقريبًا السؤال نفسه في مرحلة ما: كيف نوصل البيانات الموجودة في قواعد بياناتنا التشغيلية إلى الأماكن الأخرى التي تحتاجها؟ فمحركات البحث تحتاج إلى تحديثات المنتجات، ومستودعات التحليلات تحتاج إلى الطلبات، والذاكرة المؤقتة تحتاج إلى إبطال المحتوى القديم، والخدمات الأخرى تحتاج أن تعرف أن عميلًا غيّر عنوانه. وعلى مدى عقود كان الحل مهمة دفعية ليلية، أي استعلامات مجدولة تنسخ الصفوف من نظام إلى آخر. المهام الدفعية بسيطة، لكنها بطيئة، وتحمّل قاعدة البيانات المصدر عبئًا، وتفوّتها عمليات الحذف ما لم تُصمَّم بعناية.
يقدم التقاط تغييرات البيانات (Change Data Capture أو CDC) نهجًا مختلفًا. فبدلًا من سؤال قاعدة البيانات مرارًا عن شكل البيانات الآن، يستمع CDC إلى سجل قاعدة البيانات نفسه لما تغيّر ويحوّل كل تغيير إلى حدث. والنتيجة تدفق مرتب منخفض التأخير من الإدراجات والتحديثات والحذوف تستهلكه الأنظمة اللاحقة فور حدوثها.
يشرح هذا المقال كيف يعمل CDC، ويقارن أساليب تنفيذه الرئيسية، ويصف أكثر حالات الاستخدام شيوعًا، ويستعرض التحديات التشغيلية التي تظهر في الإنتاج. ويختتم بمثال تطبيقي لمزامنة قاعدة بيانات الطلبات مع فهرس بحث ومستودع بيانات.
كل قاعدة بيانات جادة تسجّل التغييرات أصلًا. فالمحركات العلائقية تكتب كل تعديل مثبَّت في سجل المعاملات قبل تطبيقه على ملفات البيانات، لأن السجل هو وسيلتها لضمان الديمومة ولإبقاء النسخ المتماثلة متزامنة. وهو في PostgreSQL سجل الكتابة المسبقة، وفي MySQL السجل الثنائي، وفي SQL Server سجل المعاملات، وفي Oracle سجل الإعادة. وتقرأ أدوات CDC هذا السجل وتترجم مدخلاته منخفضة المستوى إلى أحداث تغيير منظمة.
يحتوي حدث التغيير النموذجي على اسم الجدول ونوع العملية وقيم الصف قبل التغيير وبعده وختمًا زمنيًا وموضع السجل الذي حدث فيه التغيير. ولأن السجل مرتب، تصل أحداث الصف الواحد بترتيب تثبيتها. ولأنه لا يحتوي إلا على المعاملات المثبَّتة، لا يرى المستهلكون أبدًا بيانات جرى التراجع عنها لاحقًا.
الفكرة الأساسية أن سجل قاعدة البيانات هو أدق وأكمل وصف لتطور البيانات. وCDC يكشفه ببساطة بوصفه تدفقًا، فيحوّل قاعدة البيانات من مخزن سلبي إلى مصدر فاعل للأحداث.
ليس كل التقاط للتغييرات قائمًا على السجل، ومن المفيد فهم البدائل.
الالتقاط بالطابع الزمني أو بالاستعلام يضيف عمودًا مثل updated_at إلى كل جدول ويختار دوريًا الصفوف المعدّلة منذ آخر تشغيل. وهو سهل التنفيذ ولا يحتاج صلاحيات خاصة، لكن له قيودًا جدية: لا يكتشف الحذف الفعلي، ويفوّته الحالات الوسيطة إذا تغير الصف عدة مرات بين الاستعلامين، ويعتمد على أن يحدّث كل كاتب الطابع الزمني بشكل صحيح، ويضيف حمل استعلامات على النظام المصدر.
الالتقاط بالمحفّزات (Triggers) يستخدم محفزات قاعدة البيانات لنسخ كل تغيير إلى جدول تدقيق. فيلتقط كل العمليات بما فيها الحذف، لكن المحفزات تعمل داخل المعاملة الأصلية وتضيف زمن استجابة إلى كل كتابة، ويصعب صيانتها عند تغير المخطط، وقد تصبح عنق زجاجة في الجداول المزدحمة.
الالتقاط القائم على السجل يقرأ سجل المعاملات مباشرة. وأثره على قاعدة المصدر ضئيل لأنه لا ينفذ استعلامات على جداول التطبيق، ويلتقط كل تغيير مثبَّت بما فيه الحذف، ويحافظ على الترتيب، ويقدم تأخيرًا منخفضًا يقاس غالبًا بالميلي ثانية. وتكلفته تشغيلية: يحتاج إلى إعداد على مستوى قاعدة البيانات وصلاحيات مناسبة وفهم دقيق لكيفية الاحتفاظ بالسجل. ولمعظم أنظمة الإنتاج ذات الأحجام المعتبرة، يكون CDC القائم على السجل هو النهج المفضل.
Debezium هي أشهر منصة CDC مفتوحة المصدر. تعمل موصّلات فوق Kafka Connect وتدعم PostgreSQL وMySQL وSQL Server وOracle وMongoDB وغيرها، وتنشر أحداث التغيير إلى موضوعات Apache Kafka. ويمكنها العمل أيضًا في وضع مضمَّن داخل التطبيق، أو بصيغة Debezium Server التي ترسل الأحداث إلى وجهات أخرى مثل Pulsar وKinesis وGoogle Pub/Sub.
وتقدم الخدمات السحابية المُدارة قدرات مشابهة بجهد تشغيلي أقل. فخدمة AWS Database Migration Service تنفذ نسخًا متواصلًا باستخدام CDC، وGoogle Datastream تبث التغييرات من عدة قواعد إلى BigQuery وCloud Storage، وتقدم Azure ميزات تغذية التغييرات في Cosmos DB ودعم CDC في SQL Server. كما تتضمن منصات تكامل البيانات مثل Fivetran وAirbyte وStriim موصلات CDC لتحميل المستودعات.
وبعض قواعد البيانات تعرض تدفقات تغيير خاصة بها: لدى MongoDB تدفقات التغيير، ولدى DynamoDB تدفقات DynamoDB، وتوفر PostgreSQL فك التشفير المنطقي الذي تبني عليه الأدوات. ويعتمد الاختيار على قاعدة المصدر والأنظمة المستهدفة وحجم التغييرات ونضج الفريق التشغيلي وما إذا كانت منصة بث مثل Kafka جزءًا من المعمارية أصلًا.
أولى الحالات وأكثرها شيوعًا هي نسخ البيانات إلى الأنظمة التحليلية. فبث التغييرات إلى مستودع أو بحيرة بيانات يُبقي التقارير ولوحات المعلومات ضمن ثوانٍ أو دقائق من المصدر، دون العبء الثقيل للاستخراج الكامل. ويمكن للتدفق نفسه أن يغذي خصائص التعلم الآلي التي تحتاج إلى بيانات حديثة.
الثانية هي إبقاء مخازن البيانات المشتقة متسقة. فيمكن تحديث فهرس البحث في Elasticsearch أو OpenSearch، أو ذاكرة Redis المؤقتة، أو نموذج قراءة مجسَّد في تصميم CQRS، كلها انطلاقًا من تدفق التغييرات. وبدلًا من أن يكتب كود التطبيق إلى عدة أنظمة ويخاطر بعدم الاتساق، يكتب التطبيق مرة واحدة إلى قاعدته الرئيسية وينشر CDC الأثر.
الثالثة هي تكامل الخدمات المصغّرة. يمكن للخدمات نشر أحداث ذات صلة بمجالها مشتقة من تغييرات قاعدة بياناتها دون أن يضيف كل مطور استدعاءات نشر داخل منطق الأعمال. ومع نمط صندوق الصادر المعاملاتي، يوفر CDC نشرًا موثوقًا للأحداث: تكتب الخدمة حدثًا في جدول صندوق الصادر ضمن المعاملة نفسها التي تكتب تغييرها التجاري، وينقل موصل CDC هذا الصف إلى وسيط الرسائل. وهذا يتجنب مشكلة الكتابة المزدوجة تمامًا.
الرابعة هي التدقيق والامتثال. فلأن CDC يلتقط صور ما قبل التغيير وما بعده مع الأختام الزمنية، فإنه يوفر تاريخًا دائمًا لتغير البيانات، يدعم التحقيقات والتقارير التنظيمية وإعادة بناء الحالة في لحظة معينة.
والخامسة هي الترحيل دون توقف. عند الانتقال من قاعدة بيانات إلى أخرى، أو من مخطط نظام أحادي إلى مخطط خدمة، يستطيع CDC إبقاء النظام الجديد متزامنًا مع القديم بينما تُحوَّل الحركة تدريجيًا، فيصبح التحويل النهائي حدثًا منخفض المخاطر.
لخط المعالجة القائم على السجل أربع مراحل. في الأولى يأخذ الموصل لقطة أولية من محتويات الجداول الموجودة ليبدأ المستهلكون بخط أساس كامل. وفي الثانية ينتقل إلى وضع البث ويقرأ من موضع السجل المسجَّل لحظة بدء اللقطة كي لا يفوته أي تغيير بين اللقطة والبث. وفي الثالثة يحوّل كل مدخل سجل إلى حدث منظم، غالبًا بصيغة غلاف موحدة، وينشره إلى وسيط أو وجهة. وفي الرابعة يسجّل تقدمه دوريًا، ويسمى الإزاحة، كي يستأنف بعد إعادة التشغيل من حيث توقف.
وعلى جانب الاستهلاك، يشترك كل تطبيق في الموضوعات التي تهمه ويطبّق التغييرات. فقد يُحدِّث المستهلك فهرس بحث، أو يحذف مفتاحًا من الذاكرة المؤقتة، أو يضيف إلى جدول في المستودع. ولأن التسليم عادةً مرة واحدة على الأقل، يجب أن يتعامل المستهلكون مع التكرار بلباقة، إما بكتابات متساوية الأثر معتمدة على المفتاح الأساسي وموضع السجل، أو بمنطق إزالة التكرار.
تتغير قواعد البيانات. تُضاف الأعمدة وتُعاد تسميتها وتُحذف، وكل تغيير من هذا القبيل يتدفق إلى تيار الأحداث. وإذا لم يكن المستهلكون مستعدين، فقد يكسر ترحيل يبدو بريئًا عشرات خطوط المعالجة.
الدفاع العملي هو سجل مخططات مع قواعد توافق. تُسلسَل الأحداث بصيغة مثل Avro أو Protobuf، ويفرض السجل أن تبقى إصدارات المخطط الجديدة متوافقة مع القديمة، مثلًا بإضافة حقول اختيارية فقط. وينبغي كذلك معاملة تدفق التغييرات واجهةً منشورة لا تفصيلًا داخليًا. فكشف بنى الجداول الخام لكل الشركة يربط كل مستهلك بالتصميم الداخلي لقاعدة المصدر.
والنهج الأنظف للتكامل بين الفرق هو نشر أحداث منسقة بدلًا من تغييرات الجداول الخام. يتيح نمط صندوق الصادر للخدمة تعريف عقد حدث مستقر مصمم عن قصد، بينما تبقى الجداول الداخلية حرة في التطور. ويظل CDC الخام ممتازًا للنسخ إلى المستودعات، حيث الهدف فعلًا هو عكس الجدول.
خطوط CDC قوية، لكنها تفرض مسؤوليات تشغيلية يسهل التقليل من شأنها.
الاحتفاظ بالسجل وفتحات النسخ مصدر كلاسيكي للحوادث. ففي PostgreSQL، تجبر فتحة النسخ المنطقي الخادم على الاحتفاظ بملفات السجل حتى يقرأها المستهلك. وإذا توقف الموصل ينمو السجل بلا حدود وقد يملأ قرص قاعدة الإنتاج. راقب تأخر الفتحة، واضبط التنبيهات، وحدد إجراءً لإزالة الفتحات المهجورة.
المعاملات الكبيرة والتحديثات الجماعية تنتج دفعات من الأحداث. فمهمة تحدّث عشرة ملايين صف تنتج عشرة ملايين حدث قد تغمر المستهلكين وتزيد التأخر. خطط للضغط الراجع، وفكر في تقنين العمليات الجماعية، وحدد أحجام الوسطاء وفقًا لذلك.
ضمانات الترتيب مجزأة. يحفظ Kafka الترتيب داخل الشريحة الواحدة، لذا يجب أن تقع أحداث المفتاح نفسه في الشريحة نفسها، عادةً باستخدام المفتاح الأساسي مفتاحًا للرسالة. أما الترتيب بين الجداول فغير مضمون، فعلى المستهلك الذي يجمع بيانات جدولين أن يتسامح مع رؤية صف تابع قبل أصله.
اللقطات الأولية للجداول الكبيرة قد تكون بطيئة وقد تقفل الجداول في بعض الإعدادات. وتتيح ميزات اللقطات التدريجية، المتوفرة في أدوات مثل Debezium، لقطات مجزأة تعمل بجانب البث دون أقفال طويلة.
الأمن والخصوصية يستحقان اهتمامًا صريحًا. يحتوي تدفق التغييرات على كل عمود من كل جدول ملتقط، بما في ذلك البيانات الشخصية. قيّد الجداول والأعمدة الملتقطة، وأخفِ الحقول الحساسة أو استبدلها برموز، وطبّق ضوابط وصول على الموضوعات، وتأكد من تنفيذ طلبات الحذف في الأنظمة اللاحقة، وإلا قد يصبح سجل الأحداث نسخة غير مقصودة من بيانات خاضعة للتنظيم.
وأخيرًا، راقب التأخير الشامل. تتبّع الفرق بين وقت التثبيت في المصدر ووقت تطبيق التغيير في كل هدف، ونبّه عند نموه. فالتأخر أول عَرَض ظاهر لمعظم مشكلات CDC.
تكمّل عدة أنماط CDC. فصندوق الصادر المعاملاتي يحوّله إلى ناشر أحداث موثوق. ونمط «التينة الخانقة» يستخدمه لمزامنة الأنظمة القديمة والجديدة أثناء الاستبدال التدريجي. أما تخزين الأحداث (Event Sourcing) فيحفظ الحالة أحداثًا منذ البداية، بينما يستخلص CDC الأحداث من الحالة لاحقًا، فهما يخدمان حاجتين مختلفتين ولا ينبغي الخلط بينهما. ونماذج القراءة في CQRS تُبنى بشكل طبيعي من تدفقات التغيير. وتتيح ميزة ضغط السجل في Kafka أن يحتفظ الموضوع بآخر حدث لكل مفتاح فقط، فيصبح نسخة مدمجة قابلة لإعادة التشغيل من الجدول يمكن للمستهلكين الجدد الانطلاق منها.
تخيل شركة تجارة إلكترونية تحتفظ بطلباتها في PostgreSQL. يريد دعم العملاء البحث في الطلبات بالاسم أو البريد أو المنتج خلال ثوانٍ من الشراء. ويريد فريق المالية عرضًا كل ساعة في المستودع، وتريد خدمة التنفيذ أن تتفاعل عند تغير حالة الطلب. اليوم ينسخ نص برمجي ليلي الطلبات إلى المستودع، ويُحدَّث فهرس البحث بكود التطبيق الذي يفشل أحيانًا بصمت، فيصبح الاثنان غير متزامنين.
يعتمد الفريق Debezium على Kafka Connect. يهيئون أولًا PostgreSQL للنسخ المنطقي، وينشئون مستخدم نسخ مخصصًا بصلاحيات قراءة فقط على جداول مختارة، ويضبطون الموصل لالتقاط جدولي الطلبات وبنود الطلب فقط. استُبعد جدول العملاء لأنه يحتوي حقولًا حساسة لا يحتاجها الدعم، والتُقط بدلًا منه عرض ضيق يستثني بيانات الدفع.
يبدأ الموصل بلقطة أولية ينشر فيها الصفوف الموجودة إلى موضوع، ثم يواصل بث التغييرات الجديدة. تُفتَّح الرسائل بمعرّف الطلب، فتبقى كل تغييرات الطلب الواحد مرتبة داخل شريحة واحدة. وتُسلسَل الأحداث بصيغة Avro وتُسجَّل في سجل مخططات مهيأ للتوافق الرجعي.
تقرأ ثلاثة مستهلكين الموضوع. فمفهرس البحث يطبق كل حدث على أنه تحديث أو إدراج لوثيقة OpenSearch بالمعرّف نفسه، ويعالج أحداث الحذف بإزالة الوثيقة، ولأن عمليات الإدراج/التحديث متساوية الأثر عند التكرار فلا ضرر من التسليم المكرر. ومحمِّل المستودع يكتب دفعات من الأحداث إلى جدول مرحلي كل دقيقة ويدمجها في الجدول النهائي باستخدام المفتاح الأساسي ورقم تسلسل السجل ليحتفظ بأحدث نسخة فقط. وتصفّي خدمة التنفيذ الأحداث التي تغيرت فيها الحالة من «مدفوع» إلى «جاهز»، وتطلق التعبئة.
ثم يعالج الفريق التشغيل. ينبّهون عند تجاوز تأخر فتحة النسخ خمس دقائق وعند ارتفاع استخدام قرص السجل. ويضيفون لوحة تعرض التأخير الشامل من التثبيت إلى تحديث الفهرس، ويستقر عند نحو 400 ميلي ثانية. وفي اختبار ينشرون ترحيلًا يضيف عمودًا يقبل القيمة الفارغة، ويتأكدون من أن سجل المخططات يقبله وأن المستهلكين يواصلون العمل. كما يختبرون عطلًا: إيقاف الموصل ساعة ثم إعادة تشغيله، والتحقق من أنه يستأنف من الإزاحة المخزنة دون صفوف مفقودة أو مكررة بعد إزالة التكرار لدى المستهلكين.
الفوائد ملموسة. تعكس نتائج البحث الطلبات الجديدة في أقل من ثانية، ويصبح المستودع حديثًا خلال دقيقة، ويُحال النص الليلي إلى التقاعد، ولا يعود كود التطبيق يكتب إلى ثلاثة أنظمة. والتكلفة قطعة بنية تحتية إضافية للتشغيل، ويقبل الفريق هذه المقايضة لأن النهج السابق كان أبطأ وأقل موثوقية.
CDC ليس مناسبًا دائمًا. ففي نظام صغير بحجم بيانات متواضع واحتياجات حداثة متساهلة، قد يكون التصدير المجدول أبسط وكافيًا تمامًا. وإذا كانت الوجهة تحتاج بضعة أحداث تجارية فقط لا كل تغيير في صف، فقد يكون نشر أحداث المجال مباشرة أوضح. وإذا كانت قاعدة المصدر لا توفر سجلًا قابلًا للاستخدام أو لا تستطيع المؤسسة منح الصلاحيات اللازمة، فقد تكون الأساليب القائمة على الاستعلام الخيار الوحيد بقيودها المعروفة. ويجب أن يوازن القرار بين متطلبات الحداثة وحجم البيانات ومهارات الفريق والعبء التشغيلي الذي تستعد المؤسسة لتحمله.
يعيد التقاط تغييرات البيانات تصوّر قاعدة البيانات بوصفها مصدر الحقيقة ومصدرًا للأحداث في آن. فبقراءة سجل المعاملات، يقدم تدفقات تغيير مرتبة ومنخفضة التأخير وكاملة دون إرهاق التطبيق أو قاعدة البيانات باستعلامات دورية. وهو يشغّل التحليلات الفورية، ويُبقي فهارس البحث والذاكرة المؤقتة متسقة، ويتيح نشر الأحداث بموثوقية عبر نمط صندوق الصادر، ويجعل الترحيلات أكثر أمانًا.
يعتمد النجاح مع CDC على معاملته بوصفه بنية تحتية إنتاجية: أدِر المخططات بسجل مخططات، وصمّم المستهلكين بحيث يكونون متساويي الأثر عند التكرار، وراقب التأخر والاحتفاظ بالسجل، واحمِ البيانات الحساسة، وقرّر عن قصد بين تدفقات الجداول الخام والأحداث المنسقة. والمؤسسات التي تفعل ذلك تستبدل المهام الدفعية الهشة والكتابات المزدوجة الضعيفة بتدفق بيانات واضح قابل للرصد، وتكسب أساسًا يمكن بناء قدرات فورية كثيرة عليه.