سؤال

نحن نستخدم قاعدة بيانات SQL Server 2005 (لا يوجد إصدار للصفوف) مع عبارة تحديد ضخمة، ونراها تمنع تشغيل العبارات الأخرى (يُرى باستخدام sp_who2).لم أكن أدرك أن عبارات SELECT يمكن أن تسبب الحظر - هل هناك أي شيء يمكنني فعله للتخفيف من ذلك؟

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

المحلول

وSELECT يمكن منع التحديثات. وهناك نموذج بيانات مصممة بشكل صحيح والاستعلام يسبب سوى الحد الأدنى من الحجب ولا تكون قضية. و'المعتاد' WITH تلميح NOLOCK هو دائما تقريبا إجابة خاطئة. الإجابة الصحيحة هي أن يوفق الاستعلام الخاص بك حتى لا تتفحص الجداول ضخمة.

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

نصائح أخرى

من توثيق:

Shared (S) تسمح الأقفال بقراءة المعاملات المتزامنة (SELECT) مورد تحت سيطرة التزامن المتشائم.لمزيد من المعلومات، راجع Types of Concurrency Control.لا يمكن لأي معاملات أخرى تعديل البيانات أثناء ذلك shared (S) الأقفال موجودة على المورد. Shared (S) يتم تحرير الأقفال الموجودة على المورد بمجرد اكتمال عملية القراءة، ما لم يتم تعيين مستوى عزل المعاملة على قراءة قابلة للتكرار أو أعلى، أو يتم استخدام تلميح القفل للاحتفاظ بالأقفال الموجودة على المورد. shared (S) أقفال طوال مدة الصفقة.

أ shared lock متوافق مع قفل مشترك آخر أو قفل تحديث، ولكن ليس مع قفل حصري.

وهذا يعني أن الخاص بك SELECT سيتم حظر الاستعلامات UPDATE و INSERT الاستعلامات والعكس.

أ SELECT سيضع الاستعلام قفلًا مشتركًا مؤقتًا عندما يقرأ كتلة من القيم من الجدول، ويزيله عند الانتهاء من القراءة.

أثناء وجود القفل، لن تتمكن من فعل أي شيء بالبيانات الموجودة في المنطقة المقفلة.

اثنين SELECT لن تحظر الاستعلامات بعضها البعض أبدًا (ما لم تكن كذلك SELECT FOR UPDATE)

يمكنك تمكين SNAPSHOT مستوى العزل على قاعدة البيانات الخاصة بك واستخدامها، ولكن لاحظ أنه لن يمنع UPDATE الاستعلامات من أن تكون مقفلة SELECT الاستعلامات (التي يبدو أنها حالتك).

ومع ذلك، فإنه سوف يمنع SELECT الاستعلامات من أن تكون مقفلة UPDATE.

لاحظ ذلك أيضًا SQL Server, على عكس Oracle, ، يستخدم مدير القفل ويبقيه مقفلاً في قائمة مرتبطة بالذاكرة.

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

يقرأ

لأداء القذرة يمكنك إما:

 using (new TransactionScope(TransactionScopeOption.Required, 
 new TransactionOptions { 
 IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
 {
 //Your code here
 }

أو

SelectCommand = "SELECT * FROM Table1 WITH (NOLOCK) INNER JOIN Table2 WITH (NOLOCK) ..."

وتذكر أن عليك أن تكتب مع (NOLOCK) بعد كل الجدول الذي تريد قراءة القذرة

هل يمكن تعيين مستوى المعاملة قراءة غير ملتزم

هل يمكن أيضا الحصول على المآزق:

و"المآزق التي تنطوي على جدول واحد فقط" HTTP: // sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx

ووأو نتائج غير صحيحة:

و"تختار تحت READ المرتكبة وREAD تكرار قد ترجع نتائج غير صحيحة."

<وأ href = "http://www2.sqlblog.com/blogs/alexander_kuznetsov/archive/2009/04/10/selects-under-read-committed-and-repeatable-read-may-return-incorrect- results.aspx "يختلط =" نوفولو noreferrer "> http://www2.sqlblog.com/blogs/alexander_kuznetsov/archive/2009/04/10/selects-under-read-committed-and-repeatable-read-may-return -incorrect-results.aspx

ويمكنك استخدام WITH(READPAST) الجدول التلميح. انها مختلفة من WITH(NOLOCK). وسوف تحصل على البيانات قبل بدأ العملية ولن تمنع أي شخص. تخيل ذلك، قمت بتشغيل بيان قبل بدأ العملية.

SELECT * FROM table1  WITH (READPAST)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top