دراسة حالة
لماذا تتوقف شاشتك الرئيسية للقائمة عن الفتح فجأة
توقفت القائمة الرئيسية عند أحد العملاء عن الفتح بينما عملت كل الصفحات الأخرى. كان السبب سجلاً واحداً أكبر بكثير من البقية، والعيب نفسه كان يفشل بصمت في مهمة خلفية.
أهم النقاط
- القائمة التي تتوقف فجأة عن الفتح غالباً يقف خلفها سجل واحد كبير، لا تغيير فعله أحد.
- ترتب قواعد البيانات الصفوف كاملة، فسجل واحد أكبر من الذاكرة المسموح بها للترتيب يُفشل الصفحة كلها.
- ينبغي أن تحمّل القائمة ما تعرضه فقط؛ أما المستندات الطويلة والملفات فمكانها الصفحة التي تفتح عنصراً واحداً.
- السبب نفسه غالباً يفشل بصمت في مهمة خلفية مجدولة لا يُنبَّه أحد إليها.
- رفع حد الذاكرة ينقل المشكلة إلى السجل التالي الأكبر بدلاً من إزالتها.
فتح فريق أحد العملاء القائمة الرئيسية في نظامهم الداخلي فظهرت الصفحة بخطأ بدلاً منها. لم يكن أحد قد غيّر تلك الشاشة، وكانت كل الصفحات الأخرى تعمل. كان السبب سجلاً واحداً كبر كثيراً عن بقية السجلات.
ماذا تكلف القائمة التي لا تفتح الفريق
القائمة الرئيسية هي المكان الذي يجد فيه الفريق عمله ويفتحه وينهيه، فحين تتوقف عن الفتح يتوقف الفريق كله معها. عند هذا العميل تحمل تلك القائمة العناصر التي يعمل منها الفريق، والأحدث في الأعلى. الصفحة التي كانوا يستخدمونها دون تفكير صارت تعرض خطأً ولا شيء غيره، بينما تصرفت كل شاشة أخرى كالمعتاد.
هذا المزيج، شاشة واحدة معطلة ولا شيء تغيّر، هو ما يجعل هذه الأعطال تبدو غامضة. ومن خبرتنا أنها تعود، لأن العيب ينمو مع البيانات لا مع أي شيء فعله إنسان. وتظهر العلامة نفسها في أي نظام ينمو: قائمة أداة داخلية معطلة، أو قائمة CRM لا تفتح، أو شاشة يعتمد عليها الفريق طوال اليوم.
لماذا ترجع صفحة قائمة إدارية لا تُحمّل غالباً إلى سجل واحد كبير
لعرض أحدث العناصر أولاً، ترتب قاعدة البيانات الصفوف، وترتبها كاملة. وقاعدة البيانات هي المخزن الذي يحفظ فيه النظام الداخلي سجلاته، والترتيب يحدث كلما طلبت سجلات بترتيب معين. وفي ترتيب من هذا النوع تخصص قاعدة البيانات مقداراً ثابتاً من الذاكرة مساحةً للعمل، ولا تزن كل صف قبل أن تبدأ: بل يدخل كل صف إلى الترتيب كاملاً بكل ما يحمله. وصف واحد أكبر من ذلك المقدار يُفشل القائمة كلها، مهما كانت الصفوف الأخرى صغيرة.
ولهذا فإن نمو حجم السجلات يعطّل الأشياء كما يعطلها نمو عددها. فإضافة سجلات تبطئ القائمة، وإضافة سجل واحد كبير على غير المعتاد قد تمنعها من الفتح تماماً.
ما وجده مهندسنا
جاء الخطأ من قاعدة البيانات وقال إنها نفدت منها الذاكرة المخصصة للترتيب. ولأن أحدث العناصر كانت تُعرض أولاً، كانت الصفوف تُرتب، وكان كل صف يحمل حقلاً ثقيلاً مع العنوان والتاريخ. وكان ذلك الحقل كتلة نصية طويلة لا تعرضها القائمة أبداً.
هذه الحقول صغيرة عادة. لكن الفريق كان قد بدأ حديثاً بإنشاء نوع جديد من العناصر، وحمل أحدها حقلاً أطول بكثير من أي شيء قبله. وتخصص قاعدة البيانات مقداراً ثابتاً من ذاكرة العمل لترتيب من هذا النوع، فلم يعد ذلك الصف الواحد يتسع له، ففشلت القائمة كلها. ورفع ذاكرة قاعدة البيانات كان سينقل الحد فقط إلى السجل التالي الأكبر.
كانت نقطة التحول سؤالاً بسيطاً: هل تحتاج القائمة ذلك الحقل أصلاً؟ إنها تعرض عنواناً وحالة وتاريخاً، لا أكثر.
والبحث عن الخطأ نفسه في مكان آخر روى بقية القصة. كان العيب نفسه يفشل بصمت في مهمة خلفية، عمل يعمل بمؤقت دون أن يراقبه أحد. لم يكن أحد قد رآه. لم يعرف الفريق إلا الشاشة التي أمامه.
ما غيّرناه
جعلنا القائمة تقرأ كل عنصر دون الحقل الثقيل، فتحمّل الصفحة العنوان والحالة والتاريخ فقط. ويُقرأ الحقل حين يفتح أحدهم ذلك العنصر، وعندها فقط. وأضفنا أيضاً فهرساً، وهو بنية بحث تحفظ العناصر بترتيب آخر تغيير لها، فلم يعد عرض الأحدث أولاً يحتاج إلى ترتيب أصلاً.
وبعد ذلك بقليل شمل التفكير نفسه النظام كله: فما لم تُطلب حقول محددة، صار طلب هذه العناصر يستبعد الحقل الثقيل افتراضياً، بما في ذلك طلبات المهمة الخلفية. وما زال فتح عنصر واحد يقرأ الحقل كاملاً. وصار فحص تلقائي جديد يلتقط الأمر إذا بدأت القائمة أو المهمة تطلب الحقل مرة أخرى.
ما صار لدى العمل
نُشرت التغييرات على نظام العميل في اليوم نفسه. عادت القائمة تفتح وعادت المهمة الخلفية تعمل. ولم يعد عنصر بأي طول قادراً على تعطيل أي منهما، وفتح عنصر واحد يعمل كما كان.
ما يمكنك فحصه بنفسك
- اسأل مطورك عمّا تحمّله أكثر شاشات قائمتك انشغالاً لكل صف، وهل تحمّل شيئاً لا تعرضه الشاشة أبداً.
- اسأل هل يُبلَّغ أحد عندما تفشل مهمة خلفية، وكيف كنت ستعرف اليوم لو كانت إحداها تفشل بصمت.
- إذا اقترح أحدهم رفع حد الذاكرة ليزول خطأ ما، فاسأل أولاً عمّا تحتاجه الشاشة فعلاً؛ فالحد الأعلى لا ينتظر إلا السجل التالي الأكبر.
- حين تبدأ نوعاً جديداً من العمل في نظامك، مثل مستندات أو ملفات أطول بكثير، فاسأل هل يمكن أن تختنق شاشة ما بحجم عنصر واحد.
- لا تتوقف عند الشاشة التي شكا منها أحدهم. اسأل هل يوجد العيب نفسه في مهام لا ينظر إليها أحد.
ما تفعله بعد ذلك
خذ القائمة التي يستخدمها فريقك أكثر من غيرها واسأل السؤال الذي فتح هذا الباب: ماذا تحتاج هذه الشاشة لكل صف، وماذا تحمّله على أي حال. ثم اطلب طريقة لتعرف بها عندما تفشل مهمة خلفية، بدلاً من أن تعرف من شاشة معطلة. وتتبع عيب كهذا إلى سببه هو نوع العمل الذي يقوم به مهندسونا للعملاء، وهو يبدأ عادة بسؤال بسيط واحد عمّا تطلبه الصفحة فعلاً.
أسئلة شائعة
كيف أعرف أن مهمة خلفية كانت تفشل بصمت؟
اسأل من يعتني بنظامك هل تُسجَّل أعطال المهام المجدولة في مكان ما وهل يُنبَّه أحد. وإذا كان الجواب أن لا أحد سيعرف، فذلك جدير بالإصلاح أولاً، لأن المهمة الفاشلة لا تُنتج علامة ظاهرة حتى يعتمد أحد على نتيجتها.
لماذا تعطلت شاشة قائمتنا ولم يغيّر أحد شيئاً؟
لأن البيانات تغيّرت، لا الشاشة. فالقائمة التي ترتب صفوفها تجعل قاعدة البيانات تحفظ كل صف في ذاكرة العمل، ويكفي سجل واحد يكبر عن المساحة المسموح بها ليتوقف الصفحة. ويمكن أن تبقى الشاشة نفسها دون تغيير وقتاً طويلاً قبل أن يحدث ذلك.
كيف يمكن لسجل واحد أن يمنع صفحة كاملة من التحميل؟
ترتب قاعدة البيانات كل الصفوف معاً، ولا تتجاوز الأجزاء الكبيرة من السجل أثناء الترتيب. فإذا كان صف واحد أكبر من الذاكرة المخصصة لذلك الترتيب، فشلت العملية كلها، فلا يبقى للصفحة ما تعرضه. وكون السجلات الأخرى صغيرة لا يساعد.
هل نرفع حد ذاكرة قاعدة البيانات فقط؟
رفع الحد قد يجعل الخطأ يختفي الآن، لكنه لا يجيب عن سبب تحميل الصفحة لكل هذا. فالسجل التالي الأطول قد يتجاوز الحد الجديد، ويعود العطل نفسه. والأفضل أن تسأل عمّا تحتاجه الشاشة فعلاً وأن تحمّل ذلك فقط.
ماذا ينبغي أن تحمّله شاشة القائمة لكل صف؟
ينبغي أن تحمّل القائمة الحقول التي تعرضها فقط، مثل عنوان وحالة وتاريخ. أما النصوص الطويلة والملفات وتفاصيل الإنتاج فمكانها الصفحة التي تفتح عنصراً واحداً. وهذا يبقي القائمة سريعة ويمنع سجلاً كبيراً من تعطيلها.