سؤال

ولدي تطبيق يستخدم أرقام الحادث (من بين أنواع أخرى من الأرقام). يتم تخزين هذه الأرقام في جدول يسمى "Number_Setup"، الذي يحتوي على القيمة الحالية للعداد.

عند يولد التطبيق حادث جديد، number_setup الطاولة ويحصل الصف مكافحة العدد المطلوب (عدادات يمكن أن يكون إعادة اليومية والأسبوعية، وغيرها، ويتم تخزينها ك int و). ثم incremenets العداد وتحديث الصف مع القيمة الجديدة.

والتطبيق هو متعددة (حوالي 100 مستخدم في وقت واحد، فضلا عن وظائف SQL التي تديرها والاستيلاء على 100 لسجلات الحوادث وأرقام طلب حادث لكل منها). الجدول الحادث لديه بعض الأرقام الحادث مكررة حيث ينبغي أن لا تكون مكررة.

ويتم استخدام بروك المخزنة لاسترداد العداد المقبلة.

SELECT @Counter = counter, @ShareId=share_id, @Id=id
FROM Number_Setup
WHERE LinkTo_ID=@LinkToId
AND Counter_Type='I'

IF isnull(@ShareId,0) > 0
BEGIN 
    -- use parent counter
    SELECT @Counter = counter, @ID=id
    FROM Number_Setup
    WHERE Id=@ShareID
END

SELECT @NewCounter = @Counter + 1

UPDATE Number_Setup SET Counter = @NewCounter
WHERE id=@Id

ولقد حاصر الآن أن كتلة مع الصفقة، ولكن أنا لست تماما من أنه "سوف 100٪ الإصلاح المشكلة، كما أعتقد أن هناك أقفال لا يزال المشتركة، وبالتالي فإن مواجهة يمكن قراءتها على أي حال.

وربما يمكنني التأكد من أن العداد لم يتم تحديث، في بيان تحديث

UPDATE Number_Setup SET Counter = @NewCounter
WHERE Counter = @Counter
IF @@ERROR = 0 AND @@ROWCOUNT > 0 
    COMMIT TRANSACTION
ELSE
    ROLLBACK TRANSACTION

وأنا متأكد من أن هذا هو مشكلة مشتركة مع أرقام الفواتير المالية التطبيقات الخ
لا يمكنني وضع منطق في التعليمات البرمجية وإما استخدام قفل على هذا المستوى. لقد مقفل أيضا في HOLDLOCK ولكن لست متأكدا من انها التطبيق. يجب وضعه على اثنين من عبارات SELECT؟

يتم إنشاء

وكيف يمكنني ضمان عدم التكرار؟

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

المحلول

والحيلة هي أن تفعل التحديث العداد وقراءة في عملية ذرية واحدة:

UPDATE Number_Setup SET Counter = Counter+1
OUTPUT INSERTED.Counter 
WHERE id=@Id;

وهذا على الرغم من عدم تعيين العداد جديدة لNewCounter، ولكن بدلا من ذلك يعود على أنها مجموعة النتائج إلى العميل. إذا كان لديك لتعيين ذلك، استخدام متغير جدول المتوسطة لإخراج مكافحة INTO الجديد:

declare @NewCounter int;
declare @tabCounter table (NewCounter int);
UPDATE Number_Setup SET Counter = Counter+1
OUTPUT INSERTED.Counter INTO @tabCounter (NewCounter)
WHERE id=@Id
SELECT @NewCounter = NewCounter FROM @tabCounter;

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

وبالمناسبة يجب أن ندخل في habbit بلدي من اسم الحقول مع حالة مماثلة. إذا كانت هي اسمه ثم باستمرار لك <م> يجب استخدام حالة تطابق تام في التعليمات البرمجية T-SQL. البرامج النصية تشغيل غرامة الآن فقط لأن لديك الخادم قضية حساسة الترتيب، إذا قمت بنشر على حالة الخادم الترتيب حساسة والبرامج النصية لا تتطابق مع الحالة بالضبط الحقل / الجداول أسماء الأخطاء سوف تتبع وافر.

نصائح أخرى

هل حاولت استخدام المعرفات الفريدة العمومية بدلا من autoincrements كما المعرف الفريد الخاص بك؟

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

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

وبدلا من قراءة وتحديث من العمود "عداد" في جدول Number_Setup، لماذا لا يمكنك فقط استخدام المفتاح الأساسي autoincrementing لمكافحة الخاص بك؟ عليك أبدا أن تكون قيمة مكررة مفتاح أساسي.

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