سؤال

لدي برنامجين دفعة واحدة، أحدهما يرسل البريد الإلكتروني والآخر يرسل الفاكس.كلاهما يصل إلى جدول اسمه QUEUE.

في برنامج مرسل البريد الإلكتروني، هذا ما يحدث فيما يتعلق بـ QUEUE.لكل سجل في QUEUE التي تستوفي المعايير:

  1. أقفال سجل 1 في QUEUE طاولة:
    select 1 from QUEUE with (UPDLOCK) where id = 1
  2. عملية الإرسال من البريد الإلكتروني
  3. حذف السجل 1 في جدول QUEUE:
    delete from QUEUE where id = 1
  4. معاملة الالتزام (المعاملة ليست التزامًا تلقائيًا)

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

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

يبدو أن الحذف يحاول الحصول على قفل التحديث (U) على السجلات الأخرى في الجدول على الرغم من حذف سجل واحد فقط.لذلك يحدث الاستثناء عندما يكون للمعاملات الأخرى أقفال على سجلات أخرى في نفس الجدول.

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

بالمناسبة، إليك بعض المعلومات حول قاعدة البيانات (لست متأكدًا مما إذا كانت ستساعدك):

  • تم تشغيل قراءة اللقطة الملتزم بها
  • حالة عزل اللقطة قيد التشغيل
هل كانت مفيدة؟

المحلول

هل حاولت استخدام تلميح مع ROWLOCK أو مع NOLOCK في عبارة الحذف؟

هل قرأت هذا المقال؟يقترح عليك استخدام (UPDLOCK، READPAST) لمنع المشكلة التي تواجهك

نصائح أخرى

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

بدلاً من استخدام معاملة لتأمين السجلات، يمكنك استخدام حقل الحالة لوضع علامة على السجلات التي تتم معالجتها.

مثال:

قم بقفل بعض السجلات، ثم احصل على السجل الذي تم قفله بنجاح:

update queue set status = 'email_processing' where status is null and id = 1
select email, message from queue where status = 'email_processing'

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

عند الانتهاء من الإرسال، احذف السجلات:

delete from queue where status = 'email_processing'

سيستخدم مرسل الفاكس بالطبع حالة مختلفة (مثل 'fax_processing') بحيث يتم عزل السجلات التي تم وضع علامة عليها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top