हम स्टैक ओवरफ्लो SQL सर्वर 2005 डेटाबेस में कुछ खतरनाक, लेकिन दुर्लभ, गतिरोध की स्थिति देख रहे हैं।
मैंने प्रोफाइलर को संलग्न किया, गतिरोध समस्या निवारण पर इस उत्कृष्ट लेख का उपयोग करके एक ट्रेस प्रोफ़ाइल स्थापित की , और उदाहरणों का एक गुच्छा पकड़ा। अजीब बात यह है कि गतिरोध लेखन हमेशा एक ही है :
UPDATE [dbo].[Posts]
SET [AnswerCount] = @p1, [LastActivityDate] = @p2, [LastActivityUserId] = @p3
WHERE [Id] = @p0
अन्य deadlocking बयान बदलता रहता है, लेकिन आमतौर पर तुच्छ, सरल किसी तरह का है पढ़ने पदों तालिका के। यह हमेशा गतिरोध में मारा जाता है। यहाँ एक उदाहरण है
SELECT
[t0].[Id], [t0].[PostTypeId], [t0].[Score], [t0].[Views], [t0].[AnswerCount],
[t0].[AcceptedAnswerId], [t0].[IsLocked], [t0].[IsLockedEdit], [t0].[ParentId],
[t0].[CurrentRevisionId], [t0].[FirstRevisionId], [t0].[LockedReason],
[t0].[LastActivityDate], [t0].[LastActivityUserId]
FROM [dbo].[Posts] AS [t0]
WHERE [t0].[ParentId] = @p0
पूरी तरह से स्पष्ट होने के लिए, हम लेखन / गतिरोध नहीं देख रहे हैं, लेकिन पढ़ें / लिखें।
हमारे पास इस समय LINQ का मिश्रण है और SQL क्वेरी को पैरामीटरित किया गया है। हमने with (nolock)
सभी एसक्यूएल प्रश्नों को जोड़ा है। इससे कुछ मदद मिली होगी। हमारे पास एक एकल (बहुत) खराब-लिखित बैज क्वेरी थी जिसे मैंने कल तय किया था, जो हर बार चलाने के लिए 20 सेकंड से ऊपर ले जा रहा था, और उसके शीर्ष पर हर मिनट चल रहा था। मैं उम्मीद कर रहा था कि यह लॉकिंग की कुछ समस्याओं का स्रोत था!
दुर्भाग्य से, मुझे लगभग 2 घंटे पहले एक और गतिरोध त्रुटि मिली। समान सटीक लक्षण, वही सटीक अपराधी लिखते हैं।
वास्तव में अजीब बात यह है कि लॉकिंग एसक्यूएल स्टेटमेंट जिसे आप ऊपर देखते हैं, एक बहुत विशिष्ट कोड पथ का हिस्सा है। इसे केवल तब निष्पादित किया जाता है जब किसी प्रश्न में एक नया उत्तर जोड़ा जाता है - यह नई उत्तर गणना और अंतिम तिथि / उपयोगकर्ता के साथ मूल प्रश्न को अद्यतन करता है। यह, जाहिर है, नहीं है कि हम पढ़ रहे हैं की विशाल संख्या के लिए आम रिश्तेदार! जहां तक मैं बता सकता हूं, हम ऐप में कहीं भी बड़ी संख्या में राइट्स नहीं कर रहे हैं।
मुझे पता है कि NOLOCK एक विशालकाय हथौड़े की तरह है, लेकिन हमारे द्वारा यहां चलाए जाने वाले अधिकांश प्रश्नों को सटीक होने की आवश्यकता नहीं है। यदि आपका उपयोगकर्ता प्रोफ़ाइल कुछ सेकंड पुराना है तो क्या आप ध्यान रखेंगे?
Linq के साथ NOLOCK का उपयोग करना थोड़ा अधिक कठिन है क्योंकि स्कॉट हंसेलमैन ने यहां चर्चा की है ।
हम उपयोग करने के विचार के साथ छेड़खानी कर रहे हैं
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
आधार डेटाबेस संदर्भ पर ताकि हमारे सभी LINQ प्रश्नों में यह सेट हो। इसके बिना, हम 3-4 लाइन ट्रांजेक्शन कोड ब्लॉक में प्रत्येक लाइनक्यू कॉल जिसे हम बनाते हैं (अच्छी तरह से, सरल रीडिंग वाले, जो कि उनमें से अधिकांश बहुमत है) लपेटना होगा, जो कि बदसूरत है।
मुझे लगता है कि मैं थोड़ा निराश हूं कि SQL 2005 में तुच्छ पढ़ता है लिखने पर गतिरोध कर सकता है। मैं देख सकता हूँ / लिखना गतिरोध एक बहुत बड़ा मुद्दा है, लेकिन पढ़ता है? हम यहां बैंकिंग साइट नहीं चला रहे हैं, हमें हर बार सही सटीकता की आवश्यकता नहीं है।
विचार? विचार?
क्या आप हर ऑपरेशन के लिए SQL DataContext ऑब्जेक्ट के लिए एक नया LINQ इंस्टेंट कर रहे हैं या आप शायद सभी कॉल के लिए एक ही स्थिर संदर्भ साझा कर रहे हैं?
जेरेमी, हम सबसे अधिक भाग के लिए आधार नियंत्रक में एक स्थैतिक डेटाकोटेक्स्ट साझा कर रहे हैं:
private DBContext _db;
/// <summary>
/// Gets the DataContext to be used by a Request's controllers.
/// </summary>
public DBContext DB
{
get
{
if (_db == null)
{
_db = new DBContext() { SessionName = GetType().Name };
//_db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
}
return _db;
}
}
क्या आप अनुशंसा करते हैं कि हम प्रत्येक नियंत्रक, या प्रति पृष्ठ, या .. के लिए एक नया संदर्भ बनाएं?