2009-04-27 15 views
15

हम एक लेनदेन तालिका रखने की कोशिश कर रहे हैं जो नियमित आधार पर केवल नए रिकॉर्ड डाले जाते हैं।SQL सर्वर 2008 लंबे लेनदेन INSERT पर SELECT को अवरुद्ध क्यों कर रहा है?

इस साधारण तालिका के लिए हमें समय के साथ लगातार नए रिकॉर्ड जोड़ने की आवश्यकता है। इस तालिका में लेनदेन की मात्रा काफी अधिक होने की उम्मीद है, और लेनदेन (> 1000) के आवधिक बैच आयात भी हो सकते हैं जो पूर्ण होने में कई सेकंड लग सकते हैं।

इस डेटा से हम आवश्यक मानों को वापस करने के लिए अलग-अलग स्तंभों को समूहीकृत चुनिंदा बयानों का एक सेट करते हैं।

हमारे शुरुआती परीक्षण से हमें SQL सर्वर से संबंधित होने के लिए एक बाधा मिली है जो हमारे चयन को अवरुद्ध करता है जब INSERTS के लेनदेन के बीच में होता है।

नीचे एक साधारण उदाहरण है जिसे समस्या को दर्शाने के लिए चलाया जा सकता है।

- सरल डीबी तालिका

create table LOCK_TEST (
LOCK_TEST_ID int identity , 
AMOUNT int); 

- 1 क्वेरी खिड़की

begin tran 
insert into LOCK_TEST (AMOUNT) values (1); 
WAITFOR DELAY '00:00:15' ---- 15 Second Delay 
insert into LOCK_TEST (AMOUNT) values (1); 
commit 

में इस भागो - क्वेरी में 2 रन इस समानांतर

select SUM(AMOUNT) 
from LOCK_TEST; 
में

मैं उम्मीद करेंगे प्रश्न 2 सीधे वापस लौटने के लिए, 0 तक क्वेरी 1 पूरा होने तक, और फिर दिखाएं 2. हम दूसरी क्वेरी से 1 वापस नहीं देखना चाहते हैं।

उत्तर हमने चयनित कथन पर (NOLOCK) से संबंधित देखा है। लेकिन यह लेनदेन की सीमाओं का उल्लंघन करता है, और लौटाई गई जानकारी प्रकृति में वित्तीय हो सकती है और हम अपने प्रश्नों में कोई असामान्य विवरण नहीं देखना चाहते हैं।

मेरे समस्या सम्मिलित तरफ हो रहा है ...
क्यों सम्मिलित करें SELECT कथन भले ही यह किसी भी मौजूदा डेटा को संशोधित नहीं कर रहा है ब्लॉक करता है?

बोनस अंक प्रश्न: क्या यह SQL सर्वर का "फीचर" है, या क्या हम इसे अन्य डेटाबेस स्वादों पर भी पाएंगे?

अद्यतन मेरे पास अब स्थानीय ऑरैकल डेटाबेस खोजने और एक ही सरल परीक्षण चलाने का समय है। यह परीक्षण पास जैसा कि मैं उम्मीद करता हूं।

Ie मैं जितनी बार मैं चाहता हूँ क्वेरी चला सकते हैं, और यह शून्य वापस आ जाएगी जब तक 1 लेन-देन, करता है तो रिटर्न 2.

वहाँ इस तरह एसक्यूएल सर्वर काम करने के लिए कोई तरीका है? या क्या हमें ओरेकल में जाने की जरूरत है?

+0

इन तालिकाओं पर आपके पास कौन से इंडेक्स हैं? क्या आपके पास नियमित इंडेक्स रखरखाव है? –

+0

इस समय कोई अनुक्रमणिका नहीं है। इस पोस्ट में सूचीबद्ध सरल उदाहरण देखें, सरल 2 कॉलम तालिका से अधिक कुछ नहीं, बुनियादी सम्मिलन और चयन इस समस्या को फिर से बनाने के लिए उपयोग किया जाता है। – stevemac

उत्तर

12

यह लॉकिंग व्यवहार SQL सर्वर की एक विशेषता है। 2005 और उससे ऊपर के साथ, आप row level versioning (जो ओरेकल पर डिफ़ॉल्ट रूप से उपयोग किया जाता है) का उपयोग कर सकते हैं ताकि परिणाम & आपके चयन को अवरुद्ध न करें। यह tempdb पर अतिरिक्त तनाव डालता है क्योंकि tempdb पंक्ति स्तर संस्करण को बनाए रखता है, इसलिए सुनिश्चित करें कि आप इसके लिए समायोजित करें। एसक्यूएल जिस तरह से आप के लिए यह चाहते व्यवहार करते हैं बनाने के लिए, यह चलाएँ:

ALTER DATABASE MyDatabase 
SET ALLOW_SNAPSHOT_ISOLATION ON 

ALTER DATABASE MyDatabase 
SET READ_COMMITTED_SNAPSHOT ON 
+0

http://stackoverflow.com/a/4118803/2319909 –

4

यह SQL सर्वर और Sybase (कम से कम) में पूरी तरह से मानक व्यवहार है।

डेटा परिवर्तन (सम्मिलित करें, अपडेट करें, हटाएं) exclusive locks की आवश्यकता है।इस का कारण बनता है पाठकों अवरुद्ध हो रहे हैं:

एक विशेष (एक्स) ताला के साथ

, कोई अन्य लेनदेन डेटा को संशोधित कर सकते हैं; ऑपरेशन केवल के साथ नोलोक संकेत के उपयोग के साथ हो सकते हैं या असामान्य अलगाव स्तर पढ़ सकते हैं।

SQL सर्वर 2005 और उसके बाद के संस्करण के साथ, उन्होंने स्नैपशॉट अलगाव (उर्फ पंक्ति संस्करण) प्रस्तुत किया। एमएस बीओएल से: Understanding Row Versioning-Based Isolation Levels। इसका मतलब है कि एक पाठक के पास नवीनतम प्रतिबद्ध डेटा है, लेकिन यदि आप फिर लिखना चाहते हैं, तो कहें, तो आप पाएंगे कि डेटा गलत है क्योंकि यह अवरुद्ध लेनदेन में बदल गया है।

अब, सबसे अच्छा अभ्यास लेनदेन को कम रखना है।

लॉक करना इस एसक्यूएल सर्वर में हर समय होता है जैसे: उदाहरण के लिए, केवल क्या आप के बीच शुरू/प्रतिबद्ध करने के लिए की जरूरत है चलाता आदि

संपादित से ईमेल भेजने की प्रक्रिया नहीं है। हालांकि, बहुत लंबे समय तक लॉकिंग अवरुद्ध हो जाती है जो प्रदर्शन को कम करती है। जाहिर है, बहुत लंबा व्यक्तिपरक है।

+0

लेनदेन छोटा है, लेकिन उनमें से वॉल्यूम अवरुद्ध करने का कारण बनता है जिसकी आवश्यकता नहीं होनी चाहिए। ओरेकल के बारे में सवाल पर टिप्पणी देखें। – stevemac

+0

यदि आप चाहें तो ओरेकल में जाएं। यदि आप ओरेकल में जा सकते हैं तो मुझे संदेह है कि आपका एसक्यूएल इष्टतम नहीं है, आप क्लाइंट से सर्वर पर राउंड-ट्रिपिंग कर रहे हैं, या ऐसा कुछ जो बहुत अधिक अवरोध पैदा कर रहा है। – gbn

+1

इस तरह का एक साधारण उदाहरण इष्टतम कैसे हो सकता है? सरल उदाहरण से यह अभी भी ब्लॉक करता है। क्या आप सुझाव दे सकते हैं कि मैं इसे इष्टतम बनाने के लिए प्रदान किए गए उदाहरण को कैसे बदलूं? कृपया ध्यान दें कि इस डेटा के अपडेट कभी भी नहीं होंगे, केवल नए आवेषण। – stevemac

1

यह MySQL में भी मौजूद है। इसके पीछे तर्क यहां दिया गया है: यदि आप कुछ डेटा पर एक चयन करते हैं, तो आप उम्मीद करते हैं कि यह एक अद्यतित डेटासेट पर काम करे। यही कारण है कि INSERT के परिणामस्वरूप टेबल-स्तरीय लॉक होता है (यह तब तक होता है जब तक कि इंजन पंक्ति-स्तर लॉकिंग करने में सक्षम न हो, जैसे innodb कर सकते हैं)। इस व्यवहार को अक्षम करने के तरीके हैं, ताकि आप "गंदा पढ़ सकें" कर सकें, लेकिन वे सभी सॉफ्टवेयर (या यहां तक ​​कि डेटाबेस-इंजन) विशिष्ट हैं।

+1

मैं सहमत हूं, लेकिन मैं यह भी लेनदेन को स्वीकार करना चाहता हूं। मेरे दृष्टिकोण से नए रिकॉर्ड (लेनदेन में जो लोग) मौजूद नहीं हैं, और संभवतः कभी नहीं करेंगे। डेटा पर डेटाबेस ब्लॉक क्यों है (मेरे दृष्टिकोण से) मौजूद नहीं है गलत लगता है। मैं समझता हूं कि अगर मैं एक ही स्थान पर डेटा अपडेट कर रहा था और इसे कहीं और से चुन रहा था, तो मैं अपडेट के लिए इंतजार करना चाहूंगा, लेकिन मुझे इसका नियंत्रण चाहिए ... विशेष रूप से इनर्सिंग के साथ। ऐसा लगता है कि ओरेकल जैसा मैं अपेक्षा करता हूं। एसक्यूएल सर्वर कर सकते हैं तो अभी भी काम करने की कोशिश कर रहा है। – stevemac

1

मैं भी इस मुद्दे का सामना किया। जांच के बाद, ऐसा लगता है कि यह डेटा नहीं था जो प्रति लॉक था, लेकिन क्लस्टर्ड इंडेक्स जो डालने के परिणामस्वरूप संशोधित किया जा रहा था। चूंकि क्लस्टर्ड इंडेक्स डेटा पृष्ठों पर रहता है, इसलिए संबंधित डेटा पंक्तियों को भी लॉक कर दिया जाता है।

संबंधित मुद्दे