قصة الحذف المادي لـ 300 مليون سجل في MySQL

مقدمة

مرحبًا. أنا ningenMe، مطور الويب.

كما يقول العنوان، قصتي هي قصة حذف 300 مليون سجل فعليًا في MySQL.

لقد أصبحت مهتمًا بهذا، لذلك قررت أن أقدم تذكيرًا (تعليمات).

الصفحة الرئيسية - تنبيه

يحتوي خادم الدُفعات الذي أستخدمه وأحافظ عليه على عملية منتظمة تجمع بيانات الشهر الماضي من MySQL مرة واحدة يوميًا.

عادة تكتمل هذه العملية خلال حوالي ساعة واحدة، لكن هذه المرة لم تكتمل لمدة 1 أو 7 ساعات، ولم يتوقف التنبيه عن الظهور...

العثور على السبب

حاولت إعادة تشغيل العملية وإلقاء نظرة على السجلات، لكنني لم أر أي خطأ.
تمت فهرسة الاستعلام بشكل صحيح. ولكن عندما فكرت في الخطأ الذي حدث، أدركت أن حجم قاعدة البيانات كبير جدًا.

hoge_table | 350'000'000 |

350 مليون سجل. يبدو أن الفهرسة تعمل بشكل صحيح، ولكنها بطيئة جدًا.

وكان جمع البيانات المطلوبة شهريا حوالي 12 سجل. يبدو أن أمر التحديد استغرق وقتًا طويلاً ولم يتم تنفيذ المعاملة لفترة طويلة.

DB

إنه في الأساس جدول ينمو بحوالي 400 إدخال كل يوم. كان من المفترض أن تقوم قاعدة البيانات بجمع بيانات الشهر الماضي فقط، لذلك كان من المتوقع أن تتحمل هذا الكم من البيانات بالضبط، ولكن للأسف لم يتم تضمين عملية التدوير.

قاعدة البيانات هذه لم يتم تطويرها بواسطتي. لقد استحوذت عليها من مطور آخر، لذلك لا يزال الأمر يبدو وكأنه دين فني.

لقد جاءت لحظة أصبح فيها حجم البيانات المُدخلة يوميًا كبيرًا ووصل أخيرًا إلى الحد الأقصى. ومن المفترض أنه عند العمل مع مثل هذه الكمية الكبيرة من البيانات، سيكون من الضروري فصلها، ولكن هذا للأسف لم يتم.

وبعد ذلك بدأت العمل.

تصحيح

كان من الأكثر عقلانية تقليل حجم قاعدة البيانات نفسها وتقليل وقت معالجتها بدلاً من تغيير المنطق نفسه.

يجب أن يتغير الوضع بشكل كبير إذا قمت بمسح 300 مليون سجل، لذلك قررت أن أفعل ذلك... إيه، اعتقدت أن هذا سينجح بالتأكيد.

الإجراء 1

وبعد إعداد نسخة احتياطية موثوقة، بدأت أخيرًا في إرسال الطلبات.

「إرسال الطلب」

DELETE FROM hoge_table WHERE create_time <= 'YYYY-MM-DD HH:MM:SS';

"..."

"..."

"همم... لا إجابة. ربما تستغرق العملية وقتًا طويلاً؟" — اعتقدت، ولكن فقط في حالة نظرت إلى Grafana ورأيت أن تحميل القرص ينمو بسرعة كبيرة.
"خطير"، فكرت مرة أخرى وأوقفت الطلب على الفور.

الإجراء 2

بعد تحليل كل شيء، أدركت أن حجم البيانات كان كبيرًا جدًا بحيث لا يمكن حذف كل شيء مرة واحدة.

قررت أن أكتب نصًا يمكنه حذف حوالي مليون سجل وأطلقته.

「أنا أنفذ السيناريو」

اعتقدت: "الآن سيعمل هذا بالتأكيد".

الإجراء 3

الطريقة الثانية نجحت، ولكن تبين أنها كثيفة العمالة.
إن القيام بكل شيء بعناية، دون أعصاب غير ضرورية، سيستغرق حوالي أسبوعين. ولكن لا يزال هذا السيناريو لا يلبي متطلبات الخدمة، لذلك كان علينا الابتعاد عنه.

إذن هذا ما قررت فعله:

انسخ الجدول وأعد تسميته

من الخطوة السابقة، أدركت أن حذف مثل هذه الكمية الكبيرة من البيانات يؤدي إلى تحميل كبير بنفس القدر. لذلك قررت إنشاء جدول جديد من البداية باستخدام إدراج البيانات التي كنت سأحذفها ونقلها إليه.

| hoge_table     | 350'000'000|
| tmp_hoge_table |  50'000'000|

إذا جعلت الجدول الجديد بنفس الحجم كما هو مذكور أعلاه، فيجب أن تصبح سرعة معالجة البيانات أسرع بمقدار 1/7 أيضًا.

بعد إنشاء الجدول وإعادة تسميته، بدأت استخدامه كجدول رئيسي. الآن، إذا قمت بإسقاط الجدول الذي يحتوي على 300 مليون سجل، فسيكون كل شيء على ما يرام.
لقد اكتشفت أن الاقتطاع أو الإفلات ينشئ حملاً أقل من الحذف وقررت استخدام هذه الطريقة.

إعدام

「إرسال الطلب」

INSERT INTO tmp_hoge_table SELECT FROM hoge_table create_time > 'YYYY-MM-DD HH:MM:SS';

"..."
"..."
"م...؟"

الإجراء 4

اعتقدت أن الفكرة السابقة ستنجح، ولكن بعد إرسال طلب الإدراج ظهرت أخطاء متعددة. MySQL ليست متسامحة.

لقد كنت متعبًا جدًا بالفعل لدرجة أنني بدأت أعتقد أنني لا أريد القيام بذلك بعد الآن.

جلست وفكرت وأدركت أنه ربما كان هناك عدد كبير جدًا من استعلامات الإدراج لمرة واحدة ...
لقد حاولت إرسال طلب إدراج لكمية البيانات التي يجب أن تعالجها قاعدة البيانات خلال يوم واحد. حدث!

حسنًا، بعد ذلك نواصل إرسال الطلبات لنفس الكمية من البيانات. وبما أننا بحاجة إلى إزالة بيانات شهر كامل، فإننا نكرر هذه العملية حوالي 35 مرة.

إعادة تسمية جدول

هنا كان الحظ إلى جانبي: كل شيء سار بسلاسة.

ذهب التنبيه في عداد المفقودين

زادت سرعة معالجة الدفعات.

في السابق، كانت هذه العملية تستغرق حوالي ساعة، أما الآن فتستغرق حوالي دقيقتين.

وبعد أن تأكدت من حل جميع المشاكل، قمت بإسقاط 300 مليون سجل. لقد حذفت الجدول وشعرت أنني ولدت من جديد.

ملخص

أدركت أن معالجة التناوب كانت مفقودة في المعالجة المجمعة، وكانت هذه هي المشكلة الرئيسية. هذا النوع من الأخطاء المعمارية يؤدي إلى مضيعة للوقت.

هل تفكر في الحمل أثناء النسخ المتماثل للبيانات عند حذف السجلات من قاعدة البيانات؟ دعونا لا نثقل كاهل MySQL.

أولئك الذين هم على دراية جيدة بقواعد البيانات لن يواجهوا مثل هذه المشكلة بالتأكيد. بالنسبة لبقيةكم، آمل أن يكون هذا المقال مفيدًا.

شكرا للقراءة!

سنكون سعداء للغاية إذا أخبرتنا هل أعجبك هذا المقال، وهل الترجمة واضحة، وهل كانت مفيدة لك؟

المصدر: www.habr.com

إضافة تعليق