تحليل ومنع حالات التوقف التام في Azure SQL Database

ينطبق على: قاعدة بيانات Azure SQL

في هذه المقالة تتعرف على كيفية تحديد حالات التوقف التام في Azure SQL Database، واستخدام الرسوم البيانية للتوقف التام وQuery Store لتحديد الاستعلامات في حالة التوقف التام، وتخطيط التغييرات واختبارها لمنع تكرار حدوث حالات التوقف التام.

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

كيف تحدث حالات التوقف التام في Azure SQL Database

تحتوي كل قاعدة بيانات جديدة في Azure SQL Database على تمكين إعداد قاعدة البيانات للقراءة الملتزمة (RCSI) افتراضياً. يتم تقليل المنع بين جلسات قراءة البيانات وبيانات كتابة الجلسات إلى أدنى حد في إطار RCSI، والذي يستخدم إصدار الصفوف لزيادة التزامن. ومع ذلك، قد يستمر حدوث المنع وحالات التوقف التام في قواعد البيانات في Azure SQL Database للأسباب التالية:

  • الاستعلامات التي تقوم بتعديل البيانات قد يمنع بعضها بعضاً.
  • قد تعمل الاستعلامات ضمن مستويات العزل التي تزيد من المنع. يمكن تحديد مستويات العزل من خلال أساليب مكتبة العميل، أو تلميحات الاستعلام، أو عبارات SET في Transact-SQL.
  • قد يتم تعطيل RCSI، ما يتسبب في استخدام قاعدة البيانات لأقفال (S) مشتركة لحماية عبارات SELECT التي يتم تشغيلها ضمن مستوى العزل الملتزم بالقراءة. قد يؤدي هذا إلى زيادة المنع وحالات التوقف التام.

مثال على التوقف التام

تحدث حالة التوقف التام عندما تقوم مهمتان أو أكثر بمنع بعضهما بشكل دائم لأن كل مهمة لها تأمين على مورد تحاول المهمة الأخرى تأمينه. يسمى التوقف التام أيضاً بالتبعية الدورية: في حالة التوقف التام في مهمتين، تعتمد المعاملة A على المعاملة B، وتغلق المعاملة B الدائرة من خلال الاعتماد على المعاملة A.

على سبيل المثال:

  1. الجلسة A تبدأ معاملة صريحة وتقوم بتشغيل بيان تحديث يكتسب تأمين تحديث (U) على صف واحد في الجدول SalesLT.Product والذي تم تحويله إلى تأمين (X) حصري.
  2. الجلسة B تقوم بتشغيل عبارة تحديث تقوم بتعديل جدول SalesLT.ProductDescription. بيان التحديث ينضم إلى الجدول SalesLT.Product للعثور على الصفوف الصحيحة لتحديثها.
    • تحصل الجلسة B على تأمين (U) التحديث على 72 صفاً على جدول SalesLT.ProductDescription.
    • تحتاج الجلسة B إلى تأمين مشترك للصفوف في الجدول SalesLT.Product، بما في ذلك الصف الذي تم تأمينه بواسطة الجلسة A. تم منع الجلسة B في SalesLT.Product.
  3. تواصل الجلسة A معاملتها، وتقوم الآن بتشغيل تحديث في مقابل الجدول SalesLT.ProductDescription. تم منع الجلسة A بواسطة الجلسة B في SalesLT.ProductDescription.

A diagram showing two sessions in a deadlock. Each session owns a resource that the other process needs in order to continue.

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

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

ملاحظة

تعرف على المزيد حول معايير اختيار ضحية توقف تام في قسم قائمة عمليات التوقف التام من هذه المقالة.

Overview of a deadlock between two sessions. One session has been chosen as the deadlock victim.

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

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

مستوى العزل الافتراضي في Azure SQL Database

تمكّن قواعد البيانات الجديدة في Azure SQL Database قراءة اللقطة الملتزمة (RCSI) افتراضياً. يغير RCSI سلوك قراءة مستوى العزل الملتزم لاستخدام إصدار الصفوف لتوفير تناسق على مستوى العبارة دون استخدام تأمينات مشتركة (S) لعبارات SELECT.

مع تمكين RCSI:

  • لا تمنع البيانات التي تقرأ البيانات عبارات تعديل البيانات.
  • العبارات المعدلة للبيانات لا تمنع عبارات قراءة البيانات.

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

يمكنك تحديد ما إذا كان يتم تمكين عزل اللقطة و/ أو RCSI باستخدام Transact-SQL. اتصل بقاعدة البيانات في Azure SQL Database وقم بتشغيل الاستعلام التالي:

SELECT name, is_read_committed_snapshot_on, snapshot_isolation_state_desc
FROM sys.databases
WHERE name = DB_NAME();
GO

إذا تم تمكين RCSI، فسيرجع العمود is_read_committed_snapshot_on القيمة 1. إذا تم تمكين عزل اللقطة، فسيرجع العمود snapshot_isolation_state_desc القيمة تشغيل.

إذا تم تعطيل RCSI لقاعدة بيانات في Azure SQL Database، فابحث عن سبب تعطيل RCSI قبل إعادة تمكينها. ربما تمت كتابة تعليمة التطبيق البرمجية متوقعاً أن الاستعلامات التي تقرأ البيانات سيتم منعها بواسطة الاستعلامات التي تكتب البيانات، ما يؤدي إلى نتائج غير صحيحة من ظروف السباق عند تمكين RCSI.

تفسير أحداث التوقف التام

يتم إصدار حدث توقف تام بعد أن يكتشف مدير حالة توقف تام في Azure SQL Database حالة توقف تام ويحدد معاملة باعتبارها الضحية. بمعنى آخر، إذا قمت بإعداد تنبيهات لحالات التوقف التام، فسيتم إطلاق الإشعار بعد حل حالة التوقف التام الفردية. لا يوجد أي إجراء للمستخدم يجب أن يتم اتخاذه من أجل هذا التوقف التام. يجب كتابة التطبيقات لتتضمن منطق إعادة المحاولة بحيث تستمر تلقائياً بعد تلقي الخطأ 1205، "تم إيقاف المعاملة (معرّف العملية N) على موارد التأمين مع عملية أخرى وتم اختيارها على أنها ضحية التوقف التام. أعد تشغيل المعاملة."

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

أفضل الطرق لمنع حالات التوقف التام

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

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

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

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

  • في حالة حدوث حالة التوقف التام فقط عند اختيار خطة معينة لأحد الاستعلامات المتضمنة في حالة التوقف التام، فإن فرض خطة استعلام باستخدام Query Store قد يمنع تكرار حدوث حالات التوقف التام.
  • إعادة كتابة Transact-SQL لواحدة أو أكثر من العمليات المتضمنة في حالة التوقف التام يمكن أن تساعد أيضاً في منع حالات التوقف التام. يتطلب تقسيم العمليات الصريحة إلى عمليات أصغر تشفيراً دقيقاً واختباراً لضمان صلاحية البيانات عند حدوث تعديلات متزامنة.

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

المراقبة والتنبيه في حالات التوقف التام

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

سنستخدم عميل SQL Server Management Studio (SSMS) في هذه المقالة، لأنه يحتوي على وظائف لعرض الرسوم البيانية لحالات التوقف التام في وضع مرئي تفاعلي. يمكنك استخدام عملاء آخرين مثل Azure Data Studio لمتابعة الأمثلة، ولكن قد تتمكن فقط من عرض الرسوم البيانية لحالة التوقف التام بتنسيق XML.

قم بإنشاء قاعدة بيانات AdventureWorksLT

للمتابعة مع الأمثلة، أنشئ قاعدة بيانات جديدة في Azure SQL Database وحدد Sample البيانات على أنها مصدر البيانات.

للحصول على إرشادات تفصيلية حول كيفية إنشاء AdventureWorksLT باستخدام مدخل Microsoft Azure أو Azure CLI أو PowerShell، حدد الأسلوب الذي تختاره في Quickstart: إنشاء قاعدة بيانات واحدة لAzure SQL Database.

قم بإعداد تنبيهات حالة التوقف التام في مدخل Microsoft Azure

لإعداد التنبيهات لأحداث التوقف التام، اتبع الخطوات الواردة في المقالة إنشاء تنبيهات لـAzure SQL Database وAzure Synapse Analytics باستخدام مدخل Microsoft Azure.

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

اجمع الرسوم البيانية في حالة التوقف التام في Azure SQL Database باستخدام الأحداث الممتدة

تعد الرسوم البيانية لحالة التوقف التام Deadlock مصدراً غنياً للمعلومات المتعلقة بالعمليات والأقفال المتضمنة في حالة التوقف التام. لتجميع الرسوم البيانية لحالة التوقف التام باستخدام الأحداث الممتدة (XEvents) في Azure SQL Database، التقط الحدث sqlserver.database_xml_deadlock_report.

يمكنك جمع الرسوم البيانية لحالة التوقف التام مع XEvents باستخدام إما هدف المخزن المؤقت الدائري أو هدف ملف الحدث. تم تلخيص اعتبارات اختيار نوع الهدف المناسب في الجدول التالي:

النهج المزايا الاعتبارات سيناريوهات الاستخدام
هدف المخزن المؤقت الدائري
  • إعداد بسيط باستخدام Transact-SQL فقط.
  • يتم مسح بيانات الحدث عند إيقاف جلسة XEvents لأي سبب، مثل إيقاف تشغيل قاعدة البيانات أو تجاوز فشل قاعدة البيانات.
  • تُستخدم موارد قاعدة البيانات للحفاظ على البيانات في المخزن المؤقت الحلقي والاستعلام عن بيانات الجلسة.
  • جمع بيانات تتبع عينة للاختبار والتعلم.
  • أنشئ للاحتياجات قصيرة المدى إذا لم تتمكن من إعداد جلسة باستخدام هدف ملف الحدث على الفور.
  • استخدمها كـ "منصة هبوط" لبيانات التتبع، عندما تقوم بإعداد عملية آلية لاستمرار تتبع البيانات في جدول.
هدف ملف الحدث
  • تستمر بيانات الحدث في blob في Azure Storage بحيث تكون البيانات متاحة حتى بعد إيقاف الجلسة.
  • يمكن تنزيل ملفات الأحداث من مدخل Microsoft Azure أو Azure Storage Explorer وتحليلها محلياً، الأمر الذي لا يتطلب استخدام موارد قاعدة البيانات للاستعلام عن بيانات الجلسة.
  • يعد الإعداد أكثر تعقيداً ويتطلب تكوين حاوية تخزين Azure وبيانات اعتماد محددة النطاق.
  • الاستخدام العام عندما تريد أن تستمر بيانات الحدث حتى بعد توقف جلسة الحدث.
  • تريد تشغيل التتبع الذي يولد كميات أكبر من بيانات الأحداث مما ترغب في الاحتفاظ به في الذاكرة.

حدد نوع الهدف الذي ترغب في استخدامه:

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

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

لإنشاء جلسة XEvents ثم بدؤها للحدث sqlserver.database_xml_deadlock_report الذي يكتب إلى هدف المخزن المؤقت الحلقي، اتصل بقاعدة البيانات الخاصة بك وقم بتشغيل Transact-SQL التالي:

CREATE EVENT SESSION [deadlocks] ON DATABASE 
ADD EVENT sqlserver.database_xml_deadlock_report
ADD TARGET package0.ring_buffer 
WITH (STARTUP_STATE=ON, MAX_MEMORY=4 MB)
GO

ALTER EVENT SESSION [deadlocks] ON DATABASE
    STATE = START;
GO

تسبب في توقف تام في AdventureWorksLT

ملاحظة

يعمل هذا المثال في قاعدة بيانات AdventureWorksLT مع المخطط والبيانات الافتراضية عند تمكين RCSI. راجع إنشاء قاعدة بيانات AdventureWorksLT للحصول على إرشادات حول إنشاء قاعدة البيانات.

للتسبب في توقف تام، ستحتاج إلى ربط جلستين بقاعدة بيانات AdventureWorksLT. سنشير إلى هذه الجلسات باسم Session A وSession B.

في Session A، قم بتشغيل Transact-SQL التالي. تبدأ هذه التعليمة البرمجية معاملة صريحة and runs a single statement that updates the SalesLT.Product. للقيام بذلك، تحصل المعاملة على تأمين تحديث (U) على صف واحد في الجدول SalesLT.Product والذي يتم تحويله إلى تأمين (X) حصري. نترك الصفقة مفتوحة.

BEGIN TRAN

    UPDATE SalesLT.Product SET SellEndDate = SellEndDate + 1
        WHERE Color = 'Red';

الآن، في الجلسة B، قم بتشغيل Transact-SQL التالي. هذا التعليمة البرمجية لا يبدأ صراحةً أي معاملة. بدلاً من ذلك، فهي تعمل في وضع معاملة الالتزام التلقائي. هذا البيان تحديث الجدول SalesLT.ProductDescription. سيأخذ التحديث تأمين تحديث (U) على 72 صفاً في الجدول SalesLT.ProductDescription. ينضم الاستعلام إلى الجداول الأخرى، بما في ذلك جدول SalesLT.Product.

UPDATE SalesLT.ProductDescription SET Description = Description
    FROM SalesLT.ProductDescription as pd
    JOIN SalesLT.ProductModelProductDescription as pmpd on
        pd.ProductDescriptionID = pmpd.ProductDescriptionID
    JOIN SalesLT.ProductModel as pm on
        pmpd.ProductModelID = pm.ProductModelID
    JOIN SalesLT.Product as p on
        pm.ProductModelID=p.ProductModelID
    WHERE p.Color = 'Silver';

لإكمال هذا التحديث، تحتاج الجلسة B إلى تأمين (S) مشترك على صفوف في الجدول SalesLT.Product، بما في ذلك الصف الذي تم تأمينه بواسطة الجلسة A. سيتم منع الجلسة B في SalesLT.Product.

ارجع إلى الجلسة A. قم بتشغيل عبارة Transact-SQL التالية. يؤدي هذا إلى تشغيل عبارة UPDATE ثانية كجزء من المعاملة المفتوحة.

	UPDATE SalesLT.ProductDescription SET Description = Description
		FROM SalesLT.ProductDescription as pd
		JOIN SalesLT.ProductModelProductDescription as pmpd on
			pd.ProductDescriptionID = pmpd.ProductDescriptionID
		JOIN SalesLT.ProductModel as pm on
			pmpd.ProductModelID = pm.ProductModelID
		JOIN SalesLT.Product as p on
			pm.ProductModelID=p.ProductModelID
		WHERE p.Color = 'Red';

سيتم منع بيان التحديث الثاني في الجلسة A بواسطة الجلسة B في SalesLT.ProductDescription.

تعمل الجلسة A والجلسة B على منع بعضهما بشكل متبادل. لا يمكن متابعة أي من العمليات، حيث يحتاج كل منهما إلى مورد مغلق من قِبل الآخر.

بعد بضع ثوانٍ، سيحدد جهاز مراقبة حالة التوقف التام أن العمليات في الجلسة A والجلسة B تمنع بعضها بشكل متبادل، ولا يمكن لأي منهما إحراز تقدم. يجب أن تلاحظ حدوث توقف تام، مع اختيار الجلسة A لتكون ضحية توقف تام. ستظهر رسالة خطأ في الجلسة A بنص مشابه لما يلي:

وصلت معاملة Msg 1205، المستوى 13، الحالة 51، السطر 7 (معرّف العملية 91) إلى توقف تام على موارد التأمين مع عملية أخرى وتم اختيارها كضحية توقف تام. أعد تشغيل المعاملة.

سوف تتم الجلسة B بنجاح.

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

عرض الرسوم البيانية للتوقف التام من جلسة XEvents

إذا كنت قد أعددت جلسة XEvents لجمع حالات التوقف التام وحدث توقف تام بعد بدء الجلسة، يمكنك تقديم عرض رسومي تفاعلي للرسم البياني لحالة التوقف التام بالإضافة إلى XML للرسم البياني لحالة التوقف التام.

تتوفر طرق مختلفة للحصول على معلومات حالة التوقف التام لهدف المخزن المؤقت الحلقي وأهداف ملف الحدث. حدد الهدف الذي استخدمته لجلسة XEvents الخاصة بك:

إذا قمت بإعداد جلسة XEvents للكتابة إلى المخزن المؤقت الحلقي، فيمكنك الاستعلام عن معلومات حالة التوقف التام باستخدام Transact-SQL التالي. قبل تشغيل الاستعلام، استبدل قيمة @tracename باسم جلسة xEvents الخاصة بك.

DECLARE @tracename sysname = N'deadlocks';

WITH ring_buffer AS (
	SELECT CAST(target_data AS XML) as rb
	FROM sys.dm_xe_database_sessions AS s 
	JOIN sys.dm_xe_database_session_targets AS t 
		ON CAST(t.event_session_address AS BINARY(8)) = CAST(s.address AS BINARY(8))
	WHERE s.name = @tracename and
	t.target_name = N'ring_buffer'
), dx AS (
	SELECT 
		dxdr.evtdata.query('.') as deadlock_xml_deadlock_report
	FROM ring_buffer
	CROSS APPLY rb.nodes('/RingBufferTarget/event[@name=''database_xml_deadlock_report'']') AS dxdr(evtdata)
) 
SELECT 
	d.query('/event/data[@name=''deadlock_cycle_id'']/value').value('(/value)[1]', 'int') AS [deadlock_cycle_id],
	d.value('(/event/@timestamp)[1]', 'DateTime2') AS [deadlock_timestamp],
	d.query('/event/data[@name=''database_name'']/value').value('(/value)[1]', 'nvarchar(256)') AS [database_name],
	d.query('/event/data[@name=''xml_report'']/value/deadlock') AS deadlock_xml,
	LTRIM(RTRIM(REPLACE(REPLACE(d.value('.', 'nvarchar(2000)'),CHAR(10),' '),CHAR(13),' '))) as query_text
FROM dx
CROSS APPLY deadlock_xml_deadlock_report.nodes('(/event/data/value/deadlock/process-list/process/inputbuf)') AS ib(d)
ORDER BY [deadlock_timestamp] DESC;
GO

عرض وحفظ رسم بياني حالة توقف تام في XML

يتيح لك عرض مخطط حالة توقف تام بتنسيق XML نسخ inputbuffer عبارات Transact-SQL المتضمنة في حالة التوقف التام. قد تفضل أيضاً تحليل حالات التوقف التام بتنسيق نصي.

إذا كنت قد استخدمت استعلام Transact-SQL لإرجاع معلومات الرسم البياني لحالة التوقف التام، لعرض XML للرسم البياني لحالة التوقف التام، حدد القيمة في العمود deadlock_xml من أي صف لفتح XML الخاص بمخطط التوقف التام في نافذة جديدة في Management Studio.

XML لهذا المثال الرسم البياني لحالة توقف تام هو:

<deadlock>
  <victim-list>
    <victimProcess id="process24756e75088" />
  </victim-list>
  <process-list>
    <process id="process24756e75088" taskpriority="0" logused="6528" waitresource="KEY: 8:72057594045202432 (98ec012aa510)" waittime="192" ownerId="1011123" transactionname="user_transaction" lasttranstarted="2022-03-08T15:44:43.490" XDES="0x2475c980428" lockMode="U" schedulerid="3" kpid="30192" status="suspended" spid="89" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2022-03-08T15:44:49.250" lastbatchcompleted="2022-03-08T15:44:49.210" lastattention="1900-01-01T00:00:00.210" clientapp="Microsoft SQL Server Management Studio - Query" hostname="LAPTOP-CHRISQ" hostpid="16716" loginname="chrisqpublic" isolationlevel="read committed (2)" xactid="1011123" currentdb="8" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671096864" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0xef52b103e8b9b8ca" queryplanhash="0x02b0f58d7730f798" line="1" stmtstart="2" stmtend="792" sqlhandle="0x02000000c58b8f1e24e8f104a930776e21254b1771f92a520000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
	UPDATE SalesLT.ProductDescription SET Description = Description
		FROM SalesLT.ProductDescription as pd
		JOIN SalesLT.ProductModelProductDescription as pmpd on
			pd.ProductDescriptionID = pmpd.ProductDescriptionID
		JOIN SalesLT.ProductModel as pm on
			pmpd.ProductModelID = pm.ProductModelID
		JOIN SalesLT.Product as p on
			pm.ProductModelID=p.ProductModelID
		WHERE p.Color = 'Red'   </inputbuf>
    </process>
    <process id="process2476d07d088" taskpriority="0" logused="11360" waitresource="KEY: 8:72057594045267968 (39e18040972e)" waittime="2641" ownerId="1013536" transactionname="UPDATE" lasttranstarted="2022-03-08T15:44:46.807" XDES="0x2475ca80428" lockMode="S" schedulerid="2" kpid="94040" status="suspended" spid="95" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2022-03-08T15:44:46.807" lastbatchcompleted="2022-03-08T15:44:46.760" lastattention="1900-01-01T00:00:00.760" clientapp="Microsoft SQL Server Management Studio - Query" hostname="LAPTOP-CHRISQ" hostpid="16716" loginname="chrisqpublic" isolationlevel="read committed (2)" xactid="1013536" currentdb="8" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0xef52b103e8b9b8ca" queryplanhash="0x02b0f58d7730f798" line="1" stmtstart="2" stmtend="798" sqlhandle="0x020000002c85bb06327c0852c0be840fc1e30efce2b7c8090000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
	UPDATE SalesLT.ProductDescription SET Description = Description
		FROM SalesLT.ProductDescription as pd
		JOIN SalesLT.ProductModelProductDescription as pmpd on
			pd.ProductDescriptionID = pmpd.ProductDescriptionID
		JOIN SalesLT.ProductModel as pm on
			pmpd.ProductModelID = pm.ProductModelID
		JOIN SalesLT.Product as p on
			pm.ProductModelID=p.ProductModelID
		WHERE p.Color = 'Silver';   </inputbuf>
    </process>
  </process-list>
  <resource-list>
    <keylock hobtid="72057594045202432" dbid="8" objectname="9e011567-2446-4213-9617-bad2624ccc30.SalesLT.ProductDescription" indexname="PK_ProductDescription_ProductDescriptionID" id="lock2474df12080" mode="U" associatedObjectId="72057594045202432">
      <owner-list>
        <owner id="process2476d07d088" mode="U" />
      </owner-list>
      <waiter-list>
        <waiter id="process24756e75088" mode="U" requestType="wait" />
      </waiter-list>
    </keylock>
    <keylock hobtid="72057594045267968" dbid="8" objectname="9e011567-2446-4213-9617-bad2624ccc30.SalesLT.Product" indexname="PK_Product_ProductID" id="lock2474b588580" mode="X" associatedObjectId="72057594045267968">
      <owner-list>
        <owner id="process24756e75088" mode="X" />
      </owner-list>
      <waiter-list>
        <waiter id="process2476d07d088" mode="S" requestType="wait" />
      </waiter-list>
    </keylock>
  </resource-list>
</deadlock>

لحفظ الرسم البياني للتوقف التام عن العمل كملف XML:

  1. حدد File و...Save As.
  2. اترك القيمة Save as type على أنها القيمة الافتراضية XML Files (*.xml)
  3. قم بتعيين File name على الاسم الذي تختاره.
  4. حدد ⁧⁩حفظ⁧⁩.

احفظ رسماً بيانياً لحالة التوقف التام كملف XDL يمكن عرضه بشكل تفاعلي في Management Studio

يمكن أن يكون عرض التمثيل التفاعلي للرسم البياني لحالة التوقف التام مفيداً للحصول على نظرة عامة سريعة على العمليات والموارد المتضمنة في حالة التوقف التام، والتعرف بسرعة على ضحية توقف تام.

لحفظ رسم بياني حالة توقف تام كملف يمكن عرضه بيانياً بواسطة Management Studio:

  1. حدد القيمة الموجودة في العمود deadlock_xml من أي صف لفتح XML الخاص برسم حالة توقف تام في نافذة جديدة في Management Studio.

  2. حدد File و...Save As.

  3. عيّن Save as type على All Files.

  4. قم بتعيين File name على الاسم الذي تختاره، مع تعيين الملحق على .xdl.

  5. حدد ⁧⁩حفظ⁧⁩.

    A screenshot in SSMS of saving a deadlock graph XML file to a file with the xsd extension.

  6. أغلق الملف بتحديد X في علامة التبويب أعلى النافذة، أو بتحديد File، ثم Close.

  7. أعد فتح الملف في Management Studio بتحديد File، ثم Open، ثم File. حدد الملف الذي حفظته بالملحق .xdl.

    سيتم عرض الرسم البياني لحالة التوقف التام الآن في Management Studio مع تمثيل مرئي للعمليات والموارد المتضمنة في حالة التوقف التام.

    Screenshot of an xdl file opened in SSMS. The deadlock graph is displayed graphically, with processes indicated by ovals and lock resources as rectangles.

تحليل حالة التوقف التام لـ Azure SQL Database

عادةً ما يتكون الرسم البياني لحالة التوقف التام من ثلاث نقاط:

  • Victim-list. معرف عملية الضحية التوقف التام.
  • Process-list. معلومات عن جميع العمليات التي ينطوي عليها هذا التوقف التام. تستخدم الرسوم البيانية لـ Deadlock مصطلح "العملية" لتمثيل جلسة تقوم بتشغيل معاملة.
  • Resource-list. معلومات حول الموارد المتضمنة في هذا التوقف التام.

عند تحليل حالة التوقف التام، من المفيد المرور عبر هذه العقد.

قائمة ضحايا التوقف التام

تظهر قائمة ضحايا التوقف التام العملية التي تم اختيارها لتكون ضحية توقف تام. في التمثيل المرئي لرسم بياني حالة التوقف التام، يتم تمثيل العمليات بواسطة أشكال بيضاوية. عملية الضحية في توقف تام لها علامة "X" مرسومة على الشكل البيضاوي.

Screenshot of the visual display of a deadlock. The oval representing the process selected as victim has an X drawn across it.

في عرض XML للرسم البياني لحالة توقف تام، تقدم العقدة victim-list معرفاً للعملية التي كانت ضحية التوقف التام.

في مثال حالة التوقف التام لدينا، معرف عملية الضحية هو process24756e75088. يمكننا استخدام هذا المعرّف عند فحص عقد قائمة العمليات وقائمة الموارد لمعرفة المزيد حول عملية الضحية والموارد التي تم تأمينها أو طلب تأمينها.

قائمة عملية التوقف التام

تعد قائمة عمليات الوصول إلى توقف تام مصدراً غنياً للمعلومات حول العمليات المتضمنة في حالة التوقف التام.

يظهر التمثيل الرسومي للرسم البياني لحالات التوقف التام فقط مجموعة فرعية من المعلومات المضمنة في XML للرسم البياني لحالات التوقف التام. تمثل الأشكال البيضاوية في الرسم البياني حالة التوقف التام العملية، وتعرض المعلومات بما في ذلك:

  • معرف عملية الخادم، المعروف أيضاً باسم معرف الجلسة أو SPID.

  • أولوية حالة التوقف التام للجلسة. في حالة وجود جلستين لهما أولويات مختلفة في حالة التوقف التام، يتم اختيار الجلسة ذات الأولوية الأقل لتكون ضحية توقف تام. في هذا المثال، كلتا الدورتين لهما أولوية التوقف التام.

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

    في مثالنا التوقف التام، استخدم session_id 89 قدراً أقل من سجل العمليات، وتم اختياره ليكون ضحية التوقف التام.

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

Screenshot of a deadlock graph displayed visually in SSMS. Two ovals represent processes. The inputbuff for one process is shown.

تتوفر معلومات إضافية للعمليات في عرض XML لرسم بياني حالة توقف تام، بما في ذلك:

  • تحديد معلومات الجلسة، مثل اسم العميل واسم المضيف واسم تسجيل الدخول.
  • تجزئة خطة الاستعلام لآخر عبارة يتم تشغيلها بواسطة كل جلسة قبل الوصول إلى توقف تام. تعد تجزئة خطة الاستعلام مفيدة لاسترداد المزيد من المعلومات حول الاستعلام من Query Store.

في مثالنا التوقف التام:

  • يمكننا أن نرى أنه تم تشغيل كلتا الجلستين باستخدام عميل Management Studio ضمن تسجيل الدخول إلى chrisqpublic.
  • تجزئة خطة الاستعلام لآخر عبارة تم تشغيلها قبل حالة التوقف التام من قِبل ضحية حالة التوقف التام لدينا هي 0x02b0f58d7730f798. يمكننا رؤية نص هذا البيان في المخزن المؤقت للإدخال.
  • تجزئة خطة الاستعلام للعبارة الأخيرة التي تم تشغيلها بواسطة الجلسة الأخرى في حالة التوقف التام لدينا هي أيضاً 0x02b0f58d7730f798. يمكننا رؤية نص هذا البيان في المخزن المؤقت للإدخال. في هذه الحالة، يكون لكل الاستعلامات نفس تجزئة خطة الاستعلام لأن الاستعلامات متطابقة، باستثناء القيمة الحرفية المستخدمة كمسند مساواة.

سنستخدم هذه القيم لاحقاً في هذه المقالة للعثور على معلومات إضافية في Query Store.

قيود المخزن المؤقت للإدخال في قائمة عملية التوقف التام

هناك بعض القيود التي يجب أن تكون على دراية بها فيما يتعلق بمعلومات المخزن المؤقت للإدخال في قائمة عملية التوقف التام.

قد يتم اقتطاع نص الاستعلام في مخزن الإدخال المؤقت. يقتصر مخزن الإدخال المؤقت على أول 4000 حرف من العبارة التي يتم تنفيذها.

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

لتحديد Transact-SQL الكامل الذي يتم تشغيله في معاملة متعددة العبارات متضمنة في حالة توقف تام، ستحتاج إما إلى العثور على المعلومات ذات الصلة في الإجراء المخزن أو التعليمة البرمجية لتطبيق الذي قام بتشغيل الاستعلام، أو تشغيل التتبع باستخدام الأحداث الموسعة لالتقاط البيانات الكاملة التي تديرها الجلسات المتورطة في حالة توقف تام أثناء حدوثها. إذا تم اقتطاع عبارة متضمنة في حالة التوقف التام وظهر Transact-SQL جزئياً فقط في مخزن الإدخال المؤقت، يمكنك العثور على Transact-SQL للعبارة في Query Store مع خطة التنفيذ.

قائمة موارد التوقف التام

تعرض قائمة موارد حالة التوقف التام موارد التأمين التي تمتلكها وتنتظرها العمليات في حالة التوقف التام.

يتم تمثيل الموارد بواسطة المستطيلات في التمثيل المرئي للتوقف تام:

Screenshot of a deadlock graph, displayed visually in SSMS. Rectangles show the resources that are involved in the deadlock.

ملاحظة

قد تلاحظ أن أسماء قواعد البيانات يتم تمثيلها كعناصر فريدة في الرسوم البيانية لحالة التوقف التام لقواعد البيانات في Azure SQL Database. هذا هو physical_database_name لقاعدة البيانات المدرجة في sys.databases وsys.dm_user_db_resource_governance طرق عرض الإدارة الديناميكية.

في هذا المثال التوقف التام:

  • ضحية توقف تام، التي أشرنا إليها باسم الجلسة A:

    • يمتلك تأمين (X) حصرياً على مفتاح في الفهرس PK_Product_ProductID في جدول SalesLT.Product.
    • يطلب تأمين (U) تحديث على مفتاح في الفهرس PK_ProductDescription_ProductDescriptionID في جدول SalesLT.ProductDescription.
  • العملية الأخرى، التي أشرنا إليها باسم الجلسة B:

    • يمتلك تأمين (U) تحديث على مفتاح في الفهرس PK_ProductDescription_ProductDescriptionID في جدول SalesLT.ProductDescription.
    • يطلب تأمين (S) مشتركاً على مفتاح في الفهرس PK_ProductDescription_ProductDescriptionID index on the SalesLT.ProductDescription.

يمكننا رؤية نفس المعلومات في XML لرسم بياني حالة توقف تام في عقدة قائمة الموارد.

ابحث عن خطط تنفيذ الاستعلام في Query Store

غالباً ما يكون من المفيد فحص خطط تنفيذ الاستعلام عن العبارات المتضمنة في حالة التوقف التام. غالباً ما يمكن العثور على خطط التنفيذ هذه في Query Store باستخدام تجزئة خطة الاستعلام من عرض XML في قائمة عملياتالرسم البياني لحالة التوقف التام.

يبحث استعلام Transact-SQL هذا عن خطط الاستعلام المطابقة لتجزئة خطة الاستعلام التي وجدناها في مثالنا التوقف التام. اتصل بقاعدة بيانات المستخدم في Azure SQL Database لتشغيل الاستعلام.

DECLARE @query_plan_hash binary(8) = 0x02b0f58d7730f798

SELECT 
	qrsi.end_time as interval_end_time,
	qs.query_id,
	qp.plan_id,
	qt.query_sql_text, 
	TRY_CAST(qp.query_plan as XML) as query_plan,
	qrs.count_executions
FROM sys.query_store_query as qs
JOIN sys.query_store_query_text as qt on qs.query_text_id=qt.query_text_id
JOIN sys.query_store_plan as qp on qs.query_id=qp.query_id
JOIN sys.query_store_runtime_stats qrs on qp.plan_id = qrs.plan_id
JOIN sys.query_store_runtime_stats_interval qrsi on qrs.runtime_stats_interval_id=qrsi.runtime_stats_interval_id
WHERE query_plan_hash =  @query_plan_hash
ORDER BY interval_end_time, query_id;
GO

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

ابحث عن الأنماط التي تزيد من الحجب

عند فحص خطط تنفيذ الاستعلام المتضمنة في حالات التوقف التام، ابحث عن الأنماط التي قد تساهم في الحجب وحالات التوقف التام.

  • عمليات مسح الجدول أو الفهرس. عند تشغيل استعلامات تعديل البيانات ضمن RCSI، يتم تحديد الصفوف المراد تحديثها باستخدام فحص منع حيث يتم أخذ تأمين تحديث (U) على صف البيانات أثناء قراءة قيم البيانات. إذا كان صف البيانات لا يفي بمعايير التحديث، فسيتم تحرير تأمين التحديث ويتم تأمين الصف التالي وفحصه ضوئياً.

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

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

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

  • تلميحات التأمين. ابحث عن تلميحات الجدول التي تحدد مستويات العزل التي تتطلب المزيد من الأقفال. تتضمن هذه التلميحات HOLDLOCK (وهو ما يعادل التسلسل) وSERIALIZABLE وREADCOMMITTEDLOCK (الذي يعطل RCSI) وREPEATABLEREAD. بالإضافة إلى ذلك، يمكن للتلميحات مثل PAGLOCK وTABLOCK وUPDLOCK وXLOCK أن تزيد من مخاطر المنع وحالات التوقف التام.

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

    ملاحظة

    تعرف على المزيد حول السلوك عند تعديل البيانات باستخدام إصدار الصف في دليل تأمين العمليات وإصدار الصفوف.

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

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

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

  • وصول العمليات إلى العناصر في ترتيبات مختلفة. من غير المرجح أن تحدث حالات توقف تام عندما تتبع العمليات متعددة العبارات الصريحة المتزامنة نفس الأنماط وتصل إلى الكائنات بنفس الترتيب.

منع تكرار حدوث حالة توقف تام

هناك العديد من الأساليب المتاحة لمنع تكرار حدوث حالات التوقف التام، بما في ذلك ضبط الفهرس وفرض الخطط باستخدام Query Store وتعديل استعلامات Transact-SQL.

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

    تتمثل إحدى طرق التحقق من وجود فهرس متفاوت في استخدام إجراء النظام المخزن sp_helpindex. على سبيل المثال، يمكننا عرض ملخص الفهارس في جدول SalesLT.Product عن طريق تنفيذ العبارة التالية:

    exec sp_helpindex 'SalesLT.Product';
    GO
    

    راجع العمود index_description. يمكن أن يحتوي الجدول على فهرس مجمع واحد فقط. إذا تم تنفيذ فهرس مجمع للجدول، فسيحتوي index_description على الكلمة "clustered".

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

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

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

    في مثالنا التوقف التام، تحتوي خطة تنفيذ الاستعلام الموجودة في Query Store على فحص فهرس متفاوت مقابل الفهرس PK_Product_ProductID. يشير الرسم البياني لحالة التوقف التام إلى أن انتظار التأمين المشترك (S) على هذا الفهرس هو أحد مكونات حالة التوقف التام.

    Screenshot of a query execution plan. A clustered index scan is being performed against the PK_Product_ProductID index on the Product table.

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

    إذا أنشأنا الفهرس التالي غير المقيد في قاعدة البيانات AdventureWorksLT التي "تغطي" الأعمدة من SalesLT.Product المشار إليها بواسطة طريقة العرض المفهرسة، فإن هذا يساعد الاستعلام في العثور على الصفوف بشكل أكثر كفاءة:

    CREATE INDEX ix_Product_ProductID_Name_ProductModelID on SalesLT.Product (ProductID, Name, ProductModelID);
    GO
    

    بعد إنشاء هذا الفهرس، لم يعد التوقف التام يتكرر.

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

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

  • قم بتقييم قيمة العروض المفهرسة. هناك خيار آخر لمنع تكرار حدوث توقف تام في مثالنا وهو إسقاط العرض المفهرس SalesLT.vProductAndDescription. إذا لم يتم استخدام طريقة العرض المفهرسة هذه، فسيؤدي ذلك إلى تقليل النفقات العامة للحفاظ على طريقة العرض المفهرسة بمرور الوقت.

  • استخدم عزل اللقطة. في بعض الحالات، قد يؤدي تعيين مستوى عزل المعاملة إلى لقطة لواحدة أو أكثر من العمليات المتضمنة في حالة توقف تام إلى منع تكرار حدوث المنع وحالات التوقف التام.

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

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

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

  • تعديل Transact-SQL. قد تحتاج إلى تعديل Transact-SQL لمنع تكرار هذا التوقف التام. يجب إجراء تعديل Transact-SQL بعناية ويجب اختبار التغييرات بدقة للتأكد من صحة البيانات عند تشغيل التعديلات بشكل متزامن. عند إعادة كتابة Transact-SQL، ضع في اعتبارك:

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

اكتشف المزيد من الطرق لتقليل حالات التوقف التام في دليل تأمين العمليات وإصدار الصفوف.

ملاحظة

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

ترك جلسة XEvents

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

عندما ترغب في إزالة جلسة XEvents، فإن Transact-SQL تسقط الجلسة هي نفسها، بغض النظر عن نوع الهدف المحدد.

لإزالة جلسة XEvents، قم بتشغيل Transact-SQL التالي. قبل تشغيل التعليمة البرمجية، استبدل اسم الجلسة بالقيمة المناسبة.

ALTER EVENT SESSION [deadlocks] ON DATABASE
    STATE = STOP;
GO

DROP EVENT SESSION [deadlocks] ON DATABASE;
GO

استخدام Azure Storage Explorer

[Azure Storage Explorer](/azure/vs-azure-tools-storage-manage-with-storage-explorer هو تطبيق مستقل يعمل على تبسيط العمل مع أهداف ملفات الأحداث المُخزَّنة في كائنات ثنائية كبيرة الحجم في Azure Storage. يمكنك استخدام Storage Explorer من أجل:

قم بتنزيل Azure Storage Explorer..

الخطوات التالية

تعرف على المزيد حول الأداء في Azure SQL Database: