سؤال

أنا أبحث عن استراتيجية جيدة للتعامل مع Deadlocks قاعدة البيانات من داخل تطبيق Java 6؛ يمكن أن تكتمل العديد من المواضيع الموازية، والكتابة في نفس الجدول في نفس الوقت. ستقتل قاعدة البيانات (Ingres RDMBS) بشكل عشوائي إحدى الجلسات إذا اكتشفت حالة توقف تام.

ماذا ستكون تقنية مقبولة للتعامل مع الوضع الجمود، بالنظر إلى المتطلبات التالية؟

  • يجب أن يبقى الوقت المنقضي الإجمالي صغيرا قدر الإمكان
  • ستحمل قتل جلسة لاستعادة كبيرة (قابلة للقياس)
  • مواضيع الوقت ليس لها أي طريقة ل
    التواصل مع بعضها البعض، أي يجب أن تكون الاستراتيجية مستقلة

حتى الآن، فإن الاستراتيجية التي توصلت إليها هي شيء على طول هذه الخطوط:

short attempts = 0;
boolean success = false;
long delayMs = 0;

Random random = new Random();
do {
    try {
        //insert loads of records in table 'x'
        success = true;
    } catch (ConcurrencyFailureException e) {
        attempts++;
        success = false;
        delayMs = 1000*attempts+random.nextInt(1000*attempts);

        try {
                Thread.sleep(delayMs);
            } catch (InterruptedException ie) {
        }
    }
} while (!success);

هل يمكن تحسينه بأي شكل من الأشكال؟ على سبيل المثال في انتظار مبلغ ثابت (رقم سحري) ثواني. هل هناك استراتيجية مختلفة ستنتج نتائج أفضل؟

ملحوظة: سيتم استخدام العديد من تقنيات مستوى قاعدة البيانات لضمان وجود الجمود، في الممارسة العملية، نادرة جدا. أيضا، سيحاول التطبيق تجنب جدولة الخيوط التي تكتب في نفس الجدول في نفس الوقت. الوضع أعلاه سيكون مجرد "سيناريو حالة أسوأ".

ملحوظة: يتم تنظيم الجدول الذي يتم فيه إدراج السجلات كجدول مقسمة كومة ولديه فهارس؛ سيقوم كل مؤشر ترابط بإدراج سجلات في قسمه الخاص.

هل كانت مفيدة؟

المحلول

نهج شائع الاستخدام هو شكل من أشكال الظهر الأسية. بدلا من الخاص بك 1000*attempts+random Aproch، اجعل التأخير وظيفة أسية لعدد المحاولات. يضمن هذا الحد الأدنى من الكمون في أول واحد أو محاولتين، حيث كان قد يكون حظا سيئا للغاية، لكنك تمنحك تأخير أكبر بكثير في وقت لاحق، عندما يكون من الواضح أن الاتصال مبدع حقا.

بطبيعة الحال، سيكون نهج آخر هو محاولة ترتيب الوصول إلى قاعدة البيانات الخاصة بك بحيث تكون السحب الجمود أقل عرضة للحدوث. ولكن دون معرفة ما تفعله استفساراتك (وكيف، وعندما يتم تنفيذها)، من المستحيل القول إذا كان ذلك يمكن القيام به

نصائح أخرى

هذه هي الطريقة التي فعلناها. حلقة وإعادة محاولة المعاملة حتى تنتهي.

لم ننسق مع تأخير عشوائي.

أيضا، فعلنا الالتزام داخل try كتلة واستعادة في معالج الاستثناء.

عندما يكون لديك العديد من الموارد القابلة للقفل والمعاملات المتزامنة المتعددة، فإن الجمود أمر لا مفر منه. إنها نتيجة منطقية للتنافس للأقفال.

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

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

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

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

إذا لم تكن بحاجة إلى الوصول المتزامن إلى قاعدة البيانات قد يكون حل بسيط لإزالته واستخدام قائمة انتظار معالجة المهام لتحديث قاعدة البيانات بدلا من ذلك، فإن الوصول إلى قاعدة البيانات إلى قاعدة البيانات عبر قائمة الانتظار. أدرك أن هذا سيقدم عنصر غير متزامن في طلبك، ولذا لن يكون مناسبا لمعظم التطبيقات التي بدأت المستخدمين أو تطبيقات الويب عبر الإنترنت، ولكن قد تستحق النظر في تطبيق نوع دفعة / غير متصل (أدرك ربما الإجابة الخاصة بك لأنه).

مع قاعدة بيانات مثل Ingres، ستحصل دائما على بعض الجمود، لذلك عليك أن تفترض أن أي إدراج أو تحديث أو حذف سيفشل ولديه استراتيجية محتجزة في مكانها (كما في مثالك). يجب أن تقوم بتصميم قاعدة البيانات الخاصة بك بحيث يتم تقليل التنافس ويحدث الجمود فقط نادرا. إذا كنت تحصل باستمرار على المعاملات التي تفشل حتى بعد إعادة المحاولة العديدة، فهذه علامة على أنه عليك القيام ببعض إعادة تصميم قاعدة البيانات الرئيسية (أو الانتقال إلى نظام مثل Oracle حيث عادة ما يكون من الممكن تصميم التطبيقات لتجنب الجمود عن طريق الاستخدام المناسب من قفل مستوى الصف).

كيف هذا ؟

short attempts = 0;
boolean success = false;
long delayMs = 0;

Random random = new Random();
do {
try {
     synchronized(ClassName.class) {
         //insert loads of records in table 'x'
      }

    success = true;
} catch (ConcurrencyFailureException e) {
    attempts++;
    success = false;
    delayMs = 1000*attempts+random.nextInt(1000*attempts);

    try {
                    Thread.sleep(delayMs);
            } catch (InterruptedException ie) {
    }
  }
} while (!success);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top