SQL सर्वर कमांड का इतिहास नहीं रखता है जिसे 1,2 निष्पादित किया गया है । आप यह निर्धारित कर सकते हैं कि किन वस्तुओं में ताले हैं, लेकिन आप जरूरी नहीं देख सकते हैं कि उन तालों के कारण क्या कथन हुआ।
उदाहरण के लिए, यदि आप इस कथन को निष्पादित करते हैं:
BEGIN TRANSACTION
INSERT INTO dbo.TestLock DEFAULT VALUES
और सबसे हाल ही में SQL हैंडल के माध्यम से SQL टेक्स्ट को देखें, आप देखेंगे कि स्टेटमेंट दिखाई देता है। हालाँकि, यदि सत्र ने ऐसा किया है:
BEGIN TRANSACTION
INSERT INTO dbo.TestLock DEFAULT VALUES
GO
SELECT *
FROM dbo.TestLock;
GO
SELECT * FROM dbo.TestLock;
लेन-देन के लिए प्रतिबद्ध नहीं होने पर भी आप केवल कथन देखेंगे , और INSERT
कथन पाठकों को dbo.TestLock
तालिका के विरुद्ध रोक रहा है ।
मैं इसका उपयोग अनपेक्षित लेनदेन की तलाश में करता हूं जो अन्य सत्रों को रोक रहे हैं:
/*
This query shows sessions that are blocking other sessions, including sessions that are
not currently processing requests (for instance, they have an open, uncommitted transaction).
By: Max Vernon, 2017-03-20
*/
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; --reduce possible blocking by this query.
USE tempdb;
IF OBJECT_ID('tempdb..#dm_tran_session_transactions') IS NOT NULL
DROP TABLE #dm_tran_session_transactions;
SELECT *
INTO #dm_tran_session_transactions
FROM sys.dm_tran_session_transactions;
IF OBJECT_ID('tempdb..#dm_exec_connections') IS NOT NULL
DROP TABLE #dm_exec_connections;
SELECT *
INTO #dm_exec_connections
FROM sys.dm_exec_connections;
IF OBJECT_ID('tempdb..#dm_os_waiting_tasks') IS NOT NULL
DROP TABLE #dm_os_waiting_tasks;
SELECT *
INTO #dm_os_waiting_tasks
FROM sys.dm_os_waiting_tasks;
IF OBJECT_ID('tempdb..#dm_exec_sessions') IS NOT NULL
DROP TABLE #dm_exec_sessions;
SELECT *
INTO #dm_exec_sessions
FROM sys.dm_exec_sessions;
IF OBJECT_ID('tempdb..#dm_exec_requests') IS NOT NULL
DROP TABLE #dm_exec_requests;
SELECT *
INTO #dm_exec_requests
FROM sys.dm_exec_requests;
;WITH IsolationLevels AS
(
SELECT v.*
FROM (VALUES
(0, 'Unspecified')
, (1, 'Read Uncomitted')
, (2, 'Read Committed')
, (3, 'Repeatable')
, (4, 'Serializable')
, (5, 'Snapshot')
) v(Level, Description)
)
, trans AS
(
SELECT dtst.session_id
, blocking_sesion_id = 0
, Type = 'Transaction'
, QueryText = dest.text
FROM #dm_tran_session_transactions dtst
LEFT JOIN #dm_exec_connections dec ON dtst.session_id = dec.session_id
OUTER APPLY sys.dm_exec_sql_text(dec.most_recent_sql_handle) dest
)
, tasks AS
(
SELECT dowt.session_id
, dowt.blocking_session_id
, Type = 'Waiting Task'
, QueryText = dest.text
FROM #dm_os_waiting_tasks dowt
LEFT JOIN #dm_exec_connections dec ON dowt.session_id = dec.session_id
OUTER APPLY sys.dm_exec_sql_text(dec.most_recent_sql_handle) dest
WHERE dowt.blocking_session_id IS NOT NULL
)
, requests AS
(
SELECT des.session_id
, der.blocking_session_id
, Type = 'Session Request'
, QueryText = dest.text
FROM #dm_exec_sessions des
INNER JOIN #dm_exec_requests der ON des.session_id = der.session_id
OUTER APPLY sys.dm_exec_sql_text(der.sql_handle) dest
WHERE der.blocking_session_id IS NOT NULL
AND der.blocking_session_id > 0
)
, Agg AS (
SELECT SessionID = tr.session_id
, ItemType = tr.Type
, CountOfBlockedSessions = (SELECT COUNT(*) FROM requests r WHERE r.blocking_session_id = tr.session_id)
, BlockedBySessionID = tr.blocking_sesion_id
, QueryText = tr.QueryText
FROM trans tr
WHERE EXISTS (
SELECT 1
FROM requests r
WHERE r.blocking_session_id = tr.session_id
)
UNION ALL
SELECT ta.session_id
, ta.Type
, CountOfBlockedSessions = (SELECT COUNT(*) FROM requests r WHERE r.blocking_session_id = ta.session_id)
, BlockedBySessionID = ta.blocking_session_id
, ta.QueryText
FROM tasks ta
UNION ALL
SELECT rq.session_id
, rq.Type
, CountOfBlockedSessions = (SELECT COUNT(*) FROM requests r WHERE r.blocking_session_id = rq.session_id)
, BlockedBySessionID = rq.blocking_session_id
, rq.QueryText
FROM requests rq
)
SELECT agg.SessionID
, ItemType = STUFF((SELECT ', ' + COALESCE(a.ItemType, '') FROM agg a WHERE a.SessionID = agg.SessionID ORDER BY a.ItemType FOR XML PATH ('')), 1, 2, '')
, agg.BlockedBySessionID
, agg.QueryText
, agg.CountOfBlockedSessions
, des.host_name
, des.login_name
, des.is_user_process
, des.program_name
, des.status
, TransactionIsolationLevel = il.Description
FROM agg
LEFT JOIN #dm_exec_sessions des ON agg.SessionID = des.session_id
LEFT JOIN IsolationLevels il ON des.transaction_isolation_level = il.Level
GROUP BY agg.SessionID
, agg.BlockedBySessionID
, agg.CountOfBlockedSessions
, agg.QueryText
, des.host_name
, des.login_name
, des.is_user_process
, des.program_name
, des.status
, il.Description
ORDER BY
agg.BlockedBySessionID
, agg.CountOfBlockedSessions
, agg.SessionID;
अगर हम SSMS में क्वेरी विंडो के एक जोड़े के साथ एक साधारण परीक्षण-बिस्तर सेट करते हैं, तो हम देख सकते हैं कि हम केवल सबसे हाल ही में सक्रिय बयान देख सकते हैं।
पहली क्वेरी विंडो में, इसे चलाएं:
CREATE TABLE dbo.TestLock
(
id int NOT NULL IDENTITY(1,1)
);
BEGIN TRANSACTION
INSERT INTO dbo.TestLock DEFAULT VALUES
दूसरी विंडो में, इसे चलाएं:
SELECT *
FROM dbo.TestLock
अब, यदि हम ऊपर से अनवांटेड ब्लॉकिंग ट्रांजेक्शन क्वेरी चलाते हैं, तो हम निम्नलिखित आउटपुट देखते हैं:
╔═══════════╦═══════════════════════════════╦═════ ═══════════════╦══════════════════════════════════ ═══════╗
║ सत्रिड T आइटमटाइप ║ अवरुद्धबेश सत्रआईडी T क्वेरीटेक्स्ट ║
╠═══════════╬═══════════════════════════════╬═════ ═══════════════╬══════════════════════════════════ ═══════╣
║ 67 ║ लेन-देन ║ 0 TRANS बेगिन लेन-देन ║
║ d ║ ERT INSERT INTO dbo.TestLock DEFAULT VALUES ║
║ 68 Request सत्र अनुरोध, प्रतीक्षा कार्य ║ 67 * चयन * ║
║ .T ║ d से dbo.TestLock ║
╚═══════════╩═══════════════════════════════╩═════ ═══════════════╩══════════════════════════════════ ═══════╝
(मैंने परिणामों के अंत से कुछ अप्रासंगिक कॉलम हटा दिए हैं)।
अब, यदि हम पहली क्वेरी विंडो को इसमें बदलते हैं:
BEGIN TRANSACTION
INSERT INTO dbo.TestLock DEFAULT VALUES
GO
SELECT *
FROM dbo.TestLock;
GO
और दूसरी क्वेरी विंडो को फिर से चलाएँ:
SELECT *
FROM dbo.TestLock
हम इस उत्पादन को अवरुद्ध लेनदेन क्वेरी से देखेंगे:
╔═══════════╦═══════════════════════════════╦═════ ═══════════════╦════════════════════╗
║ सत्रिड T आइटमटाइप ║ अवरुद्धबेश सत्रआईडी T क्वेरीटेक्स्ट ║
╠═══════════╬═══════════════════════════════╬═════ ═══════════════╬════════════════════╣
║ 67 ║ लेन-देन ║ 0 ║ का चयन करें * ║
║ .T ║ ║ FROM dbo.TestLock से; ║
║ 68 Request सत्र अनुरोध, प्रतीक्षा कार्य ║ 67 * चयन * ║
║ .T ║ d से dbo.TestLock ║
╚═══════════╩═══════════════════════════════╩═════ ═══════════════╩════════════════════╝
1 - पूरी तरह से सच नहीं है। प्रक्रिया कैश है, जिसमें लॉक के लिए जिम्मेदार कथन हो सकता है। हालाँकि, यह निर्धारित करना आसान नहीं होगा कि कौन सा कथन लॉक का वास्तविक कारण है क्योंकि कैश में बहुत सारे प्रश्न हो सकते हैं जो प्रश्न में संसाधन को छूते हैं।
नीचे दी गई क्वेरी परीक्षण क्वेरी के लिए क्वेरी प्लान दिखाती है क्योंकि मेरी प्रक्रिया कैश बहुत व्यस्त नहीं है।
SELECT TOP(30) t.text
, p.query_plan
, deqs.execution_count
, deqs.total_elapsed_time
, deqs.total_logical_reads
, deqs.total_logical_writes
, deqs.total_logical_writes
, deqs.total_rows
, deqs.total_worker_time
, deqs.*
FROM sys.dm_exec_query_stats deqs
OUTER APPLY sys.dm_exec_sql_text(deqs.sql_handle) t
OUTER APPLY sys.dm_exec_query_plan(deqs.plan_handle) p
WHERE t.text LIKE '%dbo.TestLock%' --change this to suit your needs
AND t.text NOT LIKE '/\/\/\/\/EXCLUDE ME/\/\/\/\/\'
ORDER BY
deqs.total_worker_time DESC;
इस क्वेरी के परिणाम आपको अपराधी को खोजने की अनुमति दे सकते हैं , लेकिन जागरूक रहें, प्रक्रिया कैश का निरीक्षण करना इस तरह व्यस्त सिस्टम पर काफी मांग हो सकती है।
2 SQL सर्वर 2016 और इसके बाद का संस्करण क्वेरी स्टोर प्रदान करता है , जो निष्पादित किए गए प्रश्नों का पूरा इतिहास बनाए रखता है।
Blocked Process Reports
उत्पादन में अवरुद्ध परिदृश्यों के मूल कारण का पता लगाने के लिए, फीचर का विश्लेषण करते हुए यह संदेह पैदा हुआ था । प्रत्येक लेन-देन कई प्रश्न चलाता है, और अधिकांश समय अंतिम (जो कि बीपीआर पर इनपुट बफर पर दिखाया गया है) शायद ही कभी ताला पकड़े हुए होता है। ऐसा लगता है कि इसे हल करने के लिए मेरा आखिरी संसाधन एक हल्का xEvents सत्र सेट करना है जो मुझे बताए कि प्रत्येक सत्र के तहत कौन से प्रश्न चले। यदि आप इसका एक उदाहरण दिखाते हुए एक लेख जानते हैं, तो मैं आभारी रहूंगा।