मुझे हाल ही में उच्च TRANSACTION_MUTEX
. का सामना करना पड़ा क्लाइंट सिस्टम पर संचित प्रतीक्षा समय। मुझे ऐसा कोई मामला याद नहीं आया जहां मैंने इस प्रतीक्षा प्रकार को "उच्च प्रतीक्षा" सूची में सबसे ऊपर देखा हो और मैं इस बारे में उत्सुक था कि कौन से कारक इस प्रकार के समग्र प्रतीक्षा समय को आगे बढ़ा सकते हैं।
TRANSACTION_MUTEX
. की पुस्तकें ऑनलाइन परिभाषा यह है कि यह "एकाधिक बैचों द्वारा लेनदेन तक पहुंच के सिंक्रनाइज़ेशन के दौरान होता है।" SQL सर्वर इंजन के भीतर बहुत से क्षेत्र इस प्रकार की कार्यक्षमता को उजागर नहीं करते हैं, इसलिए मेरी जाँच निम्न तकनीकों तक सीमित थी:
- बहिष्कृत
sp_getbindtoken
औरsp_bindsession
सिस्टम संग्रहीत कार्यविधियाँ बाध्य कनेक्शन को संभालने के लिए उपयोग की जाती हैं - वितरित लेनदेन
- MARS (एकाधिक सक्रिय परिणाम सेट)
मेरा लक्ष्य प्रत्येक तकनीक का परीक्षण करना और यह देखना था कि क्या इसने TRANSACTION_MUTEX
. को प्रभावित किया है प्रतीक्षा प्रकार।
मेरे द्वारा किया गया पहला परीक्षण पदावनत sp_getbindtoken
. का उपयोग करता था और sp_bindsession
संग्रहित प्रक्रियाएं। sp_getbindtoken
एक लेन-देन पहचानकर्ता देता है जिसका उपयोग तब sp_bindsession
. द्वारा किया जा सकता है एक ही लेन-देन पर कई सत्रों को एक साथ बाँधने के लिए।
प्रत्येक परीक्षण परिदृश्य से पहले, मैंने अपने परीक्षण SQL सर्वर इंस्टेंस के प्रतीक्षा आंकड़ों को साफ़ करना सुनिश्चित किया:
DBCC SQLPERF('waitstats', CLEAR); GO
मेरा परीक्षण SQL सर्वर आवृत्ति SQL Server 2012 SP1 डेवलपर संस्करण (11.0.3000) चला रहा था। मैंने क्रेडिट नमूना डेटाबेस का उपयोग किया है, हालांकि यदि आप चाहते हैं तो आप किसी अन्य प्रकार के नमूना डेटाबेस जैसे एडवेंचरवर्क्स का उपयोग कर सकते हैं, क्योंकि स्कीमा और डेटा वितरण इस आलेख के विषय के लिए सीधे प्रासंगिक नहीं है और ड्राइव करने के लिए आवश्यक नहीं था TRANSACTION_MUTEX
प्रतीक्षा समय।
sp_getbindtoken / sp_bindsession
SQL सर्वर प्रबंधन स्टूडियो के पहले सत्र विंडो में, मैंने लेन-देन शुरू करने के लिए निम्नलिखित कोड निष्पादित किया और अन्य नियोजित सत्रों द्वारा नामांकन के लिए बाइंड टोकन को आउटपुट किया:
USE Credit; GO BEGIN TRANSACTION; DECLARE @out_token varchar(255); EXECUTE sp_getbindtoken @out_token OUTPUT; SELECT @out_token AS out_token; GO
इसने एक @out_token
लौटाया का S/Z5_GOHLaGY<^i]S9LXZ-5---.fE---
. दो अलग-अलग SQL सर्वर प्रबंधन स्टूडियो क्वेरी विंडो में, मैंने मौजूदा सत्रों में शामिल होने के लिए निम्नलिखित कोड निष्पादित किया (साझा लेनदेन तक पहुंच):
USE Credit; GO EXEC sp_bindsession 'S/Z5_GOHLaGY<^i]S9LXZ-5---.fE---';
और पहले सत्र की खिड़की अभी भी खुली होने के साथ, मैंने चार्ज टेबल की तालिका को वर्तमान तिथि और समय के बराबर चार्ज तिथि के साथ अद्यतन करने के लिए निम्नलिखित लूप को शुरू किया, और फिर अन्य दो विंडो में उसी तर्क को निष्पादित किया (तीन सक्रिय सत्र में लूप):
WHILE 1 = 1 BEGIN UPDATE dbo.charge SET charge_dt = SYSDATETIME(); END
कुछ सेकंड के बाद, मैंने प्रत्येक निष्पादन क्वेरी को रद्द कर दिया। तीन सत्रों में से, केवल एक ही वास्तव में अपडेट करने में सक्षम था - भले ही अन्य दो सत्र सक्रिय रूप से एक ही लेनदेन में शामिल हो गए थे। और अगर मैंने TRANSACTION_MUTEX
. को देखा तो प्रतीक्षा प्रकार, मैं देख सकता हूँ कि इसने वास्तव में वृद्धि की:
SELECT [wait_type], [waiting_tasks_count], [wait_time_ms], [max_wait_time_ms], [signal_wait_time_ms] FROM sys.dm_os_wait_stats WHERE wait_type = 'TRANSACTION_MUTEX';
इस विशेष परीक्षण के परिणाम इस प्रकार थे:
wait_type waiting_tasks_count wait_time_ms max_wait_time_ms signal_wait_time_ms TRANSACTION_MUTEX 2 181732 93899 0
तो मैं देखता हूं कि दो प्रतीक्षा कार्य थे (दो सत्र जो एक साथ लूप के माध्यम से एक ही तालिका को अद्यतन करने का प्रयास कर रहे थे)। चूँकि मैंने SET NOCOUNT ON
को क्रियान्वित नहीं किया था , मैं देख पा रहा था कि केवल पहला निष्पादित UPDATE
लूप में परिवर्तन हुए। मैंने कुछ भिन्न भिन्नताओं (उदाहरण के लिए - चार समग्र सत्र, तीन प्रतीक्षा के साथ) का उपयोग करके इसी तरह की तकनीक की कोशिश की - और TRANSACTION_MUTEX
वृद्धि ने समान व्यवहार दिखाया। मैंने TRANSACTION_MUTEX
भी देखा प्रत्येक सत्र के लिए एक अलग तालिका को एक साथ अद्यतन करते समय संचय - इसलिए TRANSACTION_MUTEX
को पुन:उत्पन्न करने के लिए लूप में एक ही ऑब्जेक्ट के विरुद्ध संशोधन की आवश्यकता नहीं थी प्रतीक्षा समय संचय।
वितरित लेनदेन
मेरे अगले परीक्षण में यह देखना शामिल था कि क्या TRANSACTION_MUTEX
वितरित लेनदेन के लिए प्रतीक्षा समय बढ़ा दिया गया था। इस परीक्षण के लिए, मैंने दो SQL सर्वर इंस्टेंस और उन दोनों के बीच जुड़े एक लिंक किए गए सर्वर का उपयोग किया। MS DTC चल रहा था और ठीक से कॉन्फ़िगर किया गया था, और मैंने निम्नलिखित कोड को निष्पादित किया जो एक स्थानीय DELETE
का प्रदर्शन करता था और एक दूरस्थ DELETE
लिंक किए गए सर्वर के माध्यम से और फिर परिवर्तनों को वापस ले लिया:
USE Credit; GO SET XACT_ABORT ON; -- Assumes MS DTC service is available, running, properly configured BEGIN DISTRIBUTED TRANSACTION; DELETE [dbo].[charge] WHERE charge_no = 1; DELETE [JOSEPHSACK-PC\AUGUSTUS].[Credit].[dbo].[charge] WHERE charge_no = 1; ROLLBACK TRANSACTION;
TRANSACTION_MUTEX
स्थानीय सर्वर पर कोई गतिविधि नहीं दिखाई गई:
wait_type waiting_tasks_count wait_time_ms max_wait_time_ms signal_wait_time_ms TRANSACTION_MUTEX 0 0 0 0
हालाँकि दूरस्थ सर्वर पर प्रतीक्षा कार्यों की संख्या बढ़ा दी गई थी:
wait_type waiting_tasks_count wait_time_ms max_wait_time_ms signal_wait_time_ms TRANSACTION_MUTEX 1 0 0 0
इसलिए इसे देखने की मेरी उम्मीद की पुष्टि हुई - यह देखते हुए कि हमारे पास एक ही लेनदेन के साथ एक से अधिक सत्रों के साथ एक वितरित लेनदेन है।
MARS (एकाधिक सक्रिय परिणाम सेट)
एकाधिक सक्रिय परिणाम सेट (MARS) के उपयोग के बारे में क्या? क्या हम TRANSACTION_MUTEX
. देखने की भी अपेक्षा करेंगे? MARS उपयोग से संबद्ध होने पर जमा हो जाता है?
इसके लिए, मैंने अपने SQL Server 2012 इंस्टेंस और क्रेडिट डेटाबेस के विरुद्ध Microsoft Visual Studio से परीक्षण किए गए निम्नलिखित C# कंसोल एप्लिकेशन कोड का उपयोग किया। मैं वास्तव में जो कर रहा हूं उसका तर्क बहुत उपयोगी नहीं है (प्रत्येक तालिका से एक पंक्ति देता है), लेकिन डेटा पाठक एक ही कनेक्शन पर हैं और कनेक्शन विशेषता MultipleActiveResultSets
सत्य पर सेट है, इसलिए यह सत्यापित करने के लिए पर्याप्त था कि क्या वास्तव में MARS TRANSACTION_MUTEX
चला सकता है संचय भी:
string ConnString = @"Server=.;Database=Credit;Trusted_Connection=True;MultipleActiveResultSets=true;"; SqlConnection MARSCon = new SqlConnection(ConnString); MARSCon.Open(); SqlCommand MARSCmd1 = new SqlCommand("SELECT payment_no FROM dbo.payment;", MARSCon); SqlCommand MARSCmd2 = new SqlCommand("SELECT charge_no FROM dbo.charge;", MARSCon); SqlDataReader MARSReader1 = MARSCmd1.ExecuteReader(); SqlDataReader MARSReader2 = MARSCmd2.ExecuteReader(); MARSReader1.Read(); MARSReader2.Read(); Console.WriteLine("\t{0}", MARSReader1[0]); Console.WriteLine("\t{0}", MARSReader2[0]);
इस कोड को निष्पादित करने के बाद, मैंने TRANSACTION_MUTEX
के लिए निम्नलिखित संचय देखा :
wait_type waiting_tasks_count wait_time_ms max_wait_time_ms signal_wait_time_ms TRANSACTION_MUTEX 8 2 0 0
तो जैसा कि आप देख सकते हैं, MARS गतिविधि (हालाँकि मामूली रूप से लागू) ने TRANSACTION_MUTEX
में वृद्धि का कारण बना प्रतीक्षा प्रकार संचय। और कनेक्शन स्ट्रिंग विशेषता स्वयं इसे ड्राइव नहीं करती है, वास्तविक कार्यान्वयन करता है। उदाहरण के लिए, मैंने दूसरे पाठक कार्यान्वयन को हटा दिया और केवल एक पाठक को MultipleActiveResultSets=true
के साथ बनाए रखा , और जैसा कि अपेक्षित था, कोई TRANSACTION_MUTEX
. नहीं था प्रतीक्षा समय संचय।
निष्कर्ष
यदि आप उच्च TRANSACTION_MUTEX
. देख रहे हैं आपके परिवेश में प्रतीक्षा करता है, मुझे आशा है कि यह पोस्ट आपको तलाशने के तीन तरीकों में कुछ अंतर्दृष्टि प्रदान करती है - यह निर्धारित करने के लिए कि ये प्रतीक्षाएँ कहाँ से आ रही हैं, और क्या वे आवश्यक हैं या नहीं।