نسختك الاحتياطية تعيد بهدوء إحياء المستخدمين الذين حذفتهم
كل نسخة احتياطية تزايدية تقوم على الافتراض الهادئ نفسه: لكي تنسخ ما تغيّر، ابحث عن الصفوف التي تغيّرت. في مخزن مفتاح-قيمة مثل Azure Table Storage أو DynamoDB، يعني "ما تغيّر" "الصفوف التي يكون طابع آخر تعديل لها أحدث من علامتي المائية الأخيرة." امسح الجدول، والتقط كل ما هو أحدث، واكتبه. سريع ورخيص وصحيح.
صحيح بالنسبة إلى الكتابات. الآن احذف صفًا.
الصف لا يحصل على علامة "محذوف". ولا يحصل على طابع زمني أحدث. ولا ينتقل إلى سلة محذوفات. إنه ببساطة يكفّ عن الوجود. هذه المخازن لا تملك علامات حذف ولا تدفق تغييرات لعمليات الحذف، فالصف المحذوف لا يترك خلفه شيئًا على الإطلاق. ونسختك الاحتياطية التزايدية، التي تعثر على التغييرات بمسح الطوابع الزمنية الأحدث، تمرّ مباشرة فوق الفراغ الذي كان الصف يشغله ولا تجد شيئًا. فليس هناك ما يُعثر عليه أصلًا. الحذف غير مرئي.
وهذا يعني أن نسختك الاحتياطية ما زالت تحتوي على الصف. وهنا تتحول قصة فقدان بيانات إلى قصة أمنية.
فكّر فيما يعنيه الحذف عادةً في نظام مصادقة. أنت لم تحذف ذلك المستخدم للتسلية. لقد أنهيت خدمة موظف. أزلت حسابًا ظهرت كلمة مروره في تسريب اختراق. ألغيت منحة OAuth بعد تسرّب رمز. سحبت صلاحيات مدير نظام يوم مغادرته. كل واحدة من هذه قرار أمني، ولا ينجو أي منها من نسخة احتياطية لا ترى عمليات الحذف.
ثم تستعيد النسخة. ربما بعد كارثة حقيقية، وربما لمجرد استنساخ بيئة تجريبية. تفعل النسخة الاحتياطية بالضبط ما طلبته: تعيد كل صف تعرفه. الموظف المُنهى صار مستخدمًا من جديد. كلمة المرور المخترقة صارت صالحة من جديد. المنحة الملغاة تعمل من جديد. المدير المحذوف استعاد صلاحياته. استعادتك لم تفقد بيانات. لقد تراجعت عن قراراتك الأمنية، بصمت، وسلّمتك نظامًا يبدو سليمًا وهو مخترق بهدوء. النسخة الاحتياطية التي تنسى الحذف أسوأ من لا نسخة على الإطلاق، لأنك تثق بها.
الحل أن تكفّ عن معاملة الحذف كغياب صف وتبدأ بمعاملته كحدث. عمليات الحذف بيانات.
لذلك نمنح عمليات الحذف جدولها الخاص. كل حذف في النظام يمرّ عبر ITombstoneWriter مُحقَن يسجّل شاهدة قبر: المفتاح، ولحظة موته. لا يوجد مسار في الشيفرة يحذف صفًا دون أن يترك شاهدة، لأن الحذف والشاهدة عملية واحدة. عندئذ تصبح النسخة الاحتياطية التزايدية جزأين يُلتقطان عند علامة مائية واحدة: الإدراجات والتحديثات (الصفوف ذات الطابع الزمني الأحدث) والشواهد (عمليات الحذف منذ العلامة الأخيرة). وتعيد الاستعادة تشغيل كليهما بالترتيب الزمني، فيُطبَّق الحذف تمامًا كما تُطبَّق الكتابة، والمفتاح الذي حُذف ثم أُعيد إنشاؤه لاحقًا يُحسم لصالح ما حدث أخيرًا. الفراغ صار له أخيرًا سجل مرتبط به.
هذه هي الحيلة كلها، وهي صغيرة. أما سبب أهميتها فليس صغيرًا.
هذا النمط يتجاوز Table Storage وDynamoDB. أي نظام يمثّل الحذف بأن "الصف اختفى" لا يستطيع نسخ عمليات الحذف احتياطيًا ولا تكرارها ولا مزامنتها، لأنه لا يوجد شيء يُنقل. يظهر ذلك في إعادة التشغيل الساذجة للأحداث التي تعيد الإنشاءات والتحديثات فقط. ويظهر في الذواكر المؤقتة التي تنتهي صلاحيتها لكنها لا تُبطَل أبدًا. ويظهر في النسخ المتماثلة للقراءة التي تنحرف لأن الحذف لم ينتشر قط. وهو أخطر ما يكون تحديدًا حيث تكون عمليات الحذف وسيلتك لفرض الأمان، وهذا في نظام هوية يعني كل مكان: الإلغاء، وإنهاء الخدمة، والتدوير، والإغلاق. إذا كانت قصة المتانة لديك تتتبع الأشياء الموجودة فقط، فستحافظ بأمانة على الأشياء التي بذلت جهدًا لجعلها غير موجودة.
فافحص نسخك الاحتياطية بسؤال واحد: إذا حذفت مستخدمًا الآن، وأخذت نسخة احتياطية، ثم استعدتها، هل يكون ذلك المستخدم قد اختفى؟ إذا كانت الإجابة الصادقة "لست متأكدًا"، فنسختك الاحتياطية آلة زمن موجّهة في الاتجاه الخاطئ. إنها لا تحميك من أخطائك. بل تعيد إحياءها: كلمة المرور التي دوّرتها، والموظف الذي أنهيت خدمته، والرمز الذي ألغيته.
عمليات الحذف بيانات. انسخها احتياطيًا على هذا الأساس.
وإذا كنت تفضّل أن تحترم نسخك الاحتياطية الحذف من غير أن تضطر لإثبات ذلك بنفسك، فهذا ما وُجدت المنصات لأجله. Authagonal تسجّل شاهدة لكل حذف، فلا تعيد الاستعادة أبدًا بيانات اعتماد ملغاة.