मैं <स्ट्राइक>कर सकता हूंस्ट्राइक> मेरी मशीन पर इस 100% समय को भी पुन:पेश कर सकता है। (नोट अंत में देखें)
समस्या का सार यह है कि आप S
. निकाल रहे हैं tempdb
. में सिस्टम तालिका पंक्तियों पर ताले जो आंतरिक tempdb
. के लिए आवश्यक तालों के साथ विरोध कर सकता है सफाई लेनदेन।
जब यह सफाई कार्य उसी सत्र को आवंटित किया जाता है जिसके पास S
. होता है लॉक अनिश्चितकालीन हैंग हो सकता है।
निश्चित रूप से इस समस्या से बचने के लिए आपको system
. का संदर्भ देना बंद करना होगा tempdb
. के अंदर की वस्तुएं ।
किसी भी बाहरी तालिका को संदर्भित किए बिना संख्या तालिका बनाना संभव है। निम्नलिखित को कोई आधार तालिका पंक्तियों को पढ़ने की आवश्यकता नहीं है और इस प्रकार कोई ताले भी नहीं लगते हैं।
WITH Ten(N) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
SELECT TOP 1000000 IDENTITY(INT, 1, 1) Number
INTO Numbers
FROM Ten T10,
Ten T100,
Ten T1000,
Ten T10000,
Ten T100000,
Ten T1000000
प्रजनन के चरण
पहले एक प्रक्रिया बनाएं
CREATE PROC P
AS
SET NOCOUNT ON;
DECLARE @T TABLE (X INT)
GO
फिर SQL सेवा को पुनरारंभ करें और एक कनेक्शन में निष्पादित करें
WHILE NOT EXISTS(SELECT *
FROM sys.dm_os_waiting_tasks
WHERE session_id = blocking_session_id)
BEGIN
/*This will cause the problematic droptemp transactions*/
EXEC sp_recompile 'P'
EXEC P
END;
SELECT *
FROM sys.dm_os_waiting_tasks
WHERE session_id = blocking_session_id
फिर दूसरे कनेक्शन में चलाएं
USE tempdb;
SELECT TOP 1000000 IDENTITY(INT, 1, 1) Number
INTO #T
FROM sys.objects s1
CROSS JOIN sys.objects s2
CROSS JOIN sys.objects s3
CROSS JOIN sys.objects s4;
DROP TABLE #T
संख्या तालिका को पॉप्युलेट करने वाली क्वेरी आंतरिक सिस्टम लेनदेन के साथ लाइव लॉक स्थिति में आने का प्रबंधन करती है जो अस्थायी वस्तुओं जैसे तालिका चर को साफ करती है।
मैं सत्र आईडी 53 को इस तरह से अवरुद्ध करने में कामयाब रहा। यह अनिश्चित काल के लिए अवरुद्ध है। sp_WhoIsActive
. का आउटपुट दिखाता है कि यह मकड़ी लगभग सारा समय निलंबित रहने में बिताती है। लगातार रन में reads
. में नंबर कॉलम बढ़ता है लेकिन अन्य कॉलम में मान काफी हद तक वही रहता है।
प्रतीक्षा अवधि बढ़ते हुए पैटर्न को नहीं दिखाती है, हालांकि यह इंगित करती है कि इसे फिर से अवरुद्ध होने से पहले समय-समय पर अनब्लॉक किया जाना चाहिए।
SELECT *
FROM sys.dm_os_waiting_tasks
WHERE session_id = blocking_session_id
रिटर्न
+----------------------+------------+-----------------+------------------+-----------+--------------------+-----------------------+---------------------+--------------------------+--------------------------------------------------------------------------------------------------+
| waiting_task_address | session_id | exec_context_id | wait_duration_ms | wait_type | resource_address | blocking_task_address | blocking_session_id | blocking_exec_context_id | resource_description |
+----------------------+------------+-----------------+------------------+-----------+--------------------+-----------------------+---------------------+--------------------------+--------------------------------------------------------------------------------------------------+
| 0x00000002F2C170C8 | 53 | 0 | 86 | LCK_M_X | 0x00000002F9B13040 | 0x00000002F2C170C8 | 53 | NULL | keylock hobtid=281474978938880 dbid=2 id=lock2f9ac8880 mode=U associatedObjectId=281474978938880 |
+----------------------+------------+-----------------+------------------+-----------+--------------------+-----------------------+---------------------+--------------------------+--------------------------------------------------------------------------------------------------+
संसाधन विवरण में आईडी का उपयोग करना
SELECT o.name
FROM sys.allocation_units au WITH (NOLOCK)
INNER JOIN sys.partitions p WITH (NOLOCK)
ON au.container_id = p.partition_id
INNER JOIN sys.all_objects o WITH (NOLOCK)
ON o.object_id = p.object_id
WHERE allocation_unit_id = 281474978938880
रिटर्न
+------------+
| name |
+------------+
| sysschobjs |
+------------+
चल रहा है
SELECT resource_description,request_status
FROM sys.dm_tran_locks
WHERE request_session_id = 53 AND request_status <> 'GRANT'
रिटर्न
+----------------------+----------------+
| resource_description | request_status |
+----------------------+----------------+
| (246708db8c1f) | CONVERT |
+----------------------+----------------+
डीएसी के माध्यम से कनेक्ट हो रहा है और चल रहा है
SELECT id,name
FROM tempdb.sys.sysschobjs WITH (NOLOCK)
WHERE %%LOCKRES%% = '(246708db8c1f)'
रिटर्न
+-------------+-----------+
| id | name |
+-------------+-----------+
| -1578606288 | #A1E86130 |
+-------------+-----------+
उत्सुक है कि वह क्या है
SELECT name,user_type_id
FROM tempdb.sys.columns
WHERE object_id = -1578606288
रिटर्न
+------+--------------+
| name | user_type_id |
+------+--------------+
| X | 56 |
+------+--------------+
संग्रहित खरीद द्वारा उपयोग किए जाने वाले तालिका चर में यह स्तंभ नाम है।
चल रहा है
SELECT request_mode,
request_status,
request_session_id,
request_owner_id,
lock_owner_address,
t.transaction_id,
t.name,
t.transaction_begin_time
FROM sys.dm_tran_locks l
JOIN sys.dm_tran_active_transactions t
ON l.request_owner_id = t.transaction_id
WHERE resource_description = '(246708db8c1f)'
रिटर्न
+--------------+----------------+--------------------+------------------+--------------------+----------------+-------------+-------------------------+
| request_mode | request_status | request_session_id | request_owner_id | lock_owner_address | transaction_id | name | transaction_begin_time |
+--------------+----------------+--------------------+------------------+--------------------+----------------+-------------+-------------------------+
| U | GRANT | 53 | 227647 | 0x00000002F1EF6800 | 227647 | droptemp | 2013-11-24 18:36:28.267 |
| S | GRANT | 53 | 191790 | 0x00000002F9B16380 | 191790 | SELECT INTO | 2013-11-24 18:21:30.083 |
| X | CONVERT | 53 | 227647 | 0x00000002F9B12FC0 | 227647 | droptemp | 2013-11-24 18:36:28.267 |
+--------------+----------------+--------------------+------------------+--------------------+----------------+-------------+-------------------------+
तो SELECT INTO
लेन-देन एक S
holding धारण कर रहा है tempdb.sys.sysschobjs
. में पंक्ति को लॉक करें तालिका चर से संबंधित #A1E86130
. droptemp
लेन-देन को X
नहीं मिल सकता है इस परस्पर विरोधी S
. के कारण इस पंक्ति को लॉक करें ताला।
इस क्वेरी को बार-बार चलाने से पता चलता है कि transaction_id
droptemp
. के लिए लेन-देन बार-बार बदलता है।
मैं अनुमान लगाता हूं कि SQL सर्वर को इन आंतरिक लेनदेन को उपयोगकर्ता के स्पिड्स पर आवंटित करना चाहिए और उपयोगकर्ता के काम करने से पहले उन्हें प्राथमिकता देनी चाहिए। तो सत्र आईडी 53 एक स्थिर चक्र में फंस गया है जहां यह एक droptemp
. शुरू करता है लेन-देन, उसी स्पिड पर चल रहे उपयोगकर्ता लेनदेन द्वारा अवरुद्ध है। आंतरिक लेन-देन को वापस ले लेता है और फिर प्रक्रिया को अनिश्चित काल तक दोहराता है।
यह स्पिड के हैंग होने के बाद SQL सर्वर प्रोफाइलर में विभिन्न लॉकिंग और ट्रांजेक्शन इवेंट्स को ट्रेस करके वहन किया जाता है।
मैंने उससे पहले की लॉकिंग घटनाओं का भी पता लगाया।
इवेंट ब्लॉक करना लॉक करें
अधिकांश साझा किए गए कुंजी लॉक SELECT INTO
. द्वारा निकाले गए sysschobjs
. में कुंजियों पर लेन-देन तुरंत रिहा हो जाओ। अपवाद (246708db8c1f)
. पर पहला लॉक है ।
यह कुछ समझ में आता है क्योंकि योजना [sys].[sysschobjs].[clst] [o]
के नेस्टेड लूप स्कैन दिखाती है। और क्योंकि अस्थायी वस्तुओं को नकारात्मक ऑब्जेक्ट दिया जाता है, वे स्कैन क्रम में सामने आने वाली पहली पंक्तियाँ होंगी।
मुझे ओपी में वर्णित स्थिति का भी सामना करना पड़ा जहां पहले तीन तरह से क्रॉस जॉइन चलाना चार तरह से एक को सफल होने की अनुमति देता है।
SELECT INTO
. के लिए ट्रेस में पहली कुछ घटनाएं लेन-देन एक पूरी तरह से अलग पैटर्न हैं।
यह सेवा के पुनरारंभ होने के बाद था, इसलिए टेक्स्ट डेटा कॉलम में लॉक संसाधन मान सीधे तुलनीय नहीं हैं।
ऐसा लगता है कि पहली कुंजी पर ताला बनाए रखने के बजाय और बाद की चाबियों को प्राप्त करने और जारी करने का एक पैटर्न शुरू में उन्हें जारी किए बिना बहुत अधिक ताले प्राप्त कर लेता है।
मुझे लगता है कि निष्पादन रणनीति में कुछ भिन्नता होनी चाहिए जो इस मुद्दे से बचाती है।
अपडेट करें
कनेक्ट आइटम जो मैंने उठाया इस बारे में
निश्चित के रूप में चिह्नित नहीं किया गया है, लेकिन मैं अब SQL सर्वर 2012 SP2 पर हूं और अब स्थायी के बजाय केवल अस्थायी स्वयं अवरोधन को पुन:उत्पन्न कर सकता हूं। मुझे अभी भी सेल्फ ब्लॉकिंग मिलती है लेकिन droptemp
. को निष्पादित करने के कुछ असफल प्रयासों के बाद भी लेनदेन सफलतापूर्वक ऐसा प्रतीत होता है कि उपयोगकर्ता लेनदेन को संसाधित करने के लिए वापस जाना प्रतीत होता है। उसके बाद सिस्टम लेनदेन करता है फिर सफलतापूर्वक निष्पादित किया जाता है। अब भी उसी चक्कर में। (एक उदाहरण में आठ प्रयास चलते हैं। मुझे यकीन नहीं है कि यह लगातार दोहराया जाएगा)