मैं यह जानना चाहता हूं कि सटीक क्वेरी या संग्रहीत खरीद की पहचान कैसे की जाए जो वास्तव में TEMPDB डेटाबेस के ट्रांजेक्शनल लॉग को भर रही है।
मैं यह जानना चाहता हूं कि सटीक क्वेरी या संग्रहीत खरीद की पहचान कैसे की जाए जो वास्तव में TEMPDB डेटाबेस के ट्रांजेक्शनल लॉग को भर रही है।
जवाबों:
से http://www.sqlservercentral.com/scripts/tempdb/72007/
;WITH task_space_usage AS (
-- SUM alloc/delloc pages
SELECT session_id,
request_id,
SUM(internal_objects_alloc_page_count) AS alloc_pages,
SUM(internal_objects_dealloc_page_count) AS dealloc_pages
FROM sys.dm_db_task_space_usage WITH (NOLOCK)
WHERE session_id <> @@SPID
GROUP BY session_id, request_id
)
SELECT TSU.session_id,
TSU.alloc_pages * 1.0 / 128 AS [internal object MB space],
TSU.dealloc_pages * 1.0 / 128 AS [internal object dealloc MB space],
EST.text,
-- Extract statement from sql text
ISNULL(
NULLIF(
SUBSTRING(
EST.text,
ERQ.statement_start_offset / 2,
CASE WHEN ERQ.statement_end_offset < ERQ.statement_start_offset
THEN 0
ELSE( ERQ.statement_end_offset - ERQ.statement_start_offset ) / 2 END
), ''
), EST.text
) AS [statement text],
EQP.query_plan
FROM task_space_usage AS TSU
INNER JOIN sys.dm_exec_requests ERQ WITH (NOLOCK)
ON TSU.session_id = ERQ.session_id
AND TSU.request_id = ERQ.request_id
OUTER APPLY sys.dm_exec_sql_text(ERQ.sql_handle) AS EST
OUTER APPLY sys.dm_exec_query_plan(ERQ.plan_handle) AS EQP
WHERE EST.text IS NOT NULL OR EQP.query_plan IS NOT NULL
ORDER BY 3 DESC;
संपादित करें
जैसा कि मार्टिन ने एक टिप्पणी में कहा है, यह सक्रिय लेनदेन नहीं ढूंढेगा जो टेम्पर्ड बीपी में अंतरिक्ष पर कब्जा कर रहे हैं, यह केवल सक्रिय प्रश्न पाएंगे जो वर्तमान में वहां अंतरिक्ष का उपयोग कर रहे हैं (और वर्तमान लॉग उपयोग के लिए संभावित अपराधी)। इसलिए एक खुला लेन-देन हो सकता है लेकिन वास्तविक क्वेरी जो समस्या का कारण बनती है वह अब नहीं चल रही है।
आप को बदल सकता है inner join
पर sys.dm_exec_requests
एक करने के लिए left outer join
, तो आप उस नहीं वर्तमान में सक्रिय रूप से प्रश्नों चल रहे सत्र के लिए पंक्तियों वापस आ जाएगी।
मार्टिन ने पोस्ट किया ...
SELECT database_transaction_log_bytes_reserved,session_id
FROM sys.dm_tran_database_transactions AS tdt
INNER JOIN sys.dm_tran_session_transactions AS tst
ON tdt.transaction_id = tst.transaction_id
WHERE database_id = 2;
... session_id
सक्रिय लेनदेन के साथ एस की पहचान करेगा जो लॉग स्पेस पर कब्जा कर रहे हैं, लेकिन आप आवश्यक रूप से वास्तविक क्वेरी को निर्धारित करने में सक्षम नहीं होंगे जो समस्या का कारण बनता है, क्योंकि अगर यह अब नहीं चल रहा है तो यह उपरोक्त क्वेरी में कैप्चर नहीं किया जाएगा। सक्रिय अनुरोध। आप सबसे हालिया क्वेरी का उपयोग करके प्रतिक्रियात्मक रूप से जांच करने में सक्षम हो सकते हैं, DBCC INPUTBUFFER
लेकिन यह आपको यह नहीं बता सकता है कि आप क्या सुनना चाहते हैं। आप बाहरी रूप से सक्रिय रूप से चलने वालों को पकड़ने के लिए एक समान तरीके से जुड़ सकते हैं, जैसे:
SELECT tdt.database_transaction_log_bytes_reserved,tst.session_id,
t.[text], [statement] = COALESCE(NULLIF(
SUBSTRING(
t.[text],
r.statement_start_offset / 2,
CASE WHEN r.statement_end_offset < r.statement_start_offset
THEN 0
ELSE( r.statement_end_offset - r.statement_start_offset ) / 2 END
), ''
), t.[text])
FROM sys.dm_tran_database_transactions AS tdt
INNER JOIN sys.dm_tran_session_transactions AS tst
ON tdt.transaction_id = tst.transaction_id
LEFT OUTER JOIN sys.dm_exec_requests AS r
ON tst.session_id = r.session_id
OUTER APPLY sys.dm_exec_sql_text(r.plan_handle) AS t
WHERE tdt.database_id = 2;
आप डीएमवी sys.dm_db_session_space_usage
का उपयोग सत्र द्वारा समग्र अंतरिक्ष उपयोग को देखने के लिए भी कर सकते हैं (लेकिन फिर से आपको क्वेरी के लिए वैध परिणाम वापस नहीं मिल सकता है; यदि क्वेरी सक्रिय नहीं है, तो आपको जो वापस मिलेगा वह वास्तविक अपराधी नहीं हो सकता है)।
;WITH s AS
(
SELECT
s.session_id,
[pages] = SUM(s.user_objects_alloc_page_count
+ s.internal_objects_alloc_page_count)
FROM sys.dm_db_session_space_usage AS s
GROUP BY s.session_id
HAVING SUM(s.user_objects_alloc_page_count
+ s.internal_objects_alloc_page_count) > 0
)
SELECT s.session_id, s.[pages], t.[text],
[statement] = COALESCE(NULLIF(
SUBSTRING(
t.[text],
r.statement_start_offset / 2,
CASE WHEN r.statement_end_offset < r.statement_start_offset
THEN 0
ELSE( r.statement_end_offset - r.statement_start_offset ) / 2 END
), ''
), t.[text])
FROM s
LEFT OUTER JOIN
sys.dm_exec_requests AS r
ON s.session_id = r.session_id
OUTER APPLY sys.dm_exec_sql_text(r.plan_handle) AS t
ORDER BY s.[pages] DESC;
अपने निपटान में इन सभी प्रश्नों के साथ, आपको यह पता लगाने में सक्षम होना चाहिए कि कौन टेम्पर्डबी का उपयोग कर रहा है और कैसे, खासकर यदि आप उन्हें अधिनियम में पकड़ते हैं।
SORT_IN_TEMPDB
यदि आवश्यक न हो तो विकल्प से बचेंआप यह भी विचार कर सकते हैं कि आपका tempdb लॉग उपयोग आंतरिक प्रक्रियाओं के कारण हो सकता है जिनका आपके पास बहुत कम या कोई नियंत्रण नहीं है - उदाहरण के लिए डेटाबेस मेल, इवेंट नोटिफिकेशन, क्वेरी नोटिफिकेशन और सर्विस ब्रोकर सभी किसी न किसी तरह से tempdb का उपयोग करते हैं। आप इन सुविधाओं का उपयोग करना बंद कर सकते हैं, लेकिन अगर आप उनका उपयोग कर रहे हैं तो आप यह तय नहीं कर सकते कि वे कब और कैसे टेम्पपेड का उपयोग करते हैं।
session_id
निम्न क्वेरी के साथ दिखाता है SELECT database_transaction_log_bytes_reserved,session_id FROM sys.dm_tran_database_transactions tdt JOIN sys.dm_tran_session_transactions tst ON tdt.transaction_id = tst.transaction_id WHERE database_id = 2
। जिस क्वेरी को मैं खोजने की उम्मीद कर रहा था वह निम्नलिखित चलने के बाद थीBEGIN TRAN CREATE TABLE #T(X CHAR(8000)) INSERT INTO #T SELECT name FROM sys.objects
@@SPID
है <>
नहीं =
। मेरे लिए सभी कॉलमों के लिए खुले लेनदेन के साथ स्पिड की dm_db_task_space_usage
रिपोर्ट 0
। आश्चर्य है कि अगर आपको यह अनुरोध करने की आवश्यकता है जब अनुरोध वास्तव में खुले लेनदेन के साथ निष्क्रिय होने के बजाय निष्पादित हो रहा है।
SELECT tst.[session_id],
s.[login_name] AS [Login Name],
DB_NAME (tdt.database_id) AS [Database],
tdt.[database_transaction_begin_time] AS [Begin Time],
tdt.[database_transaction_log_record_count] AS [Log Records],
tdt.[database_transaction_log_bytes_used] AS [Log Bytes Used],
tdt.[database_transaction_log_bytes_reserved] AS [Log Bytes Rsvd],
SUBSTRING(st.text, (r.statement_start_offset/2)+1,
((CASE r.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE r.statement_end_offset
END - r.statement_start_offset)/2) + 1) AS statement_text,
st.[text] AS [Last T-SQL Text],
qp.[query_plan] AS [Last Plan]
FROM sys.dm_tran_database_transactions tdt
JOIN sys.dm_tran_session_transactions tst
ON tst.[transaction_id] = tdt.[transaction_id]
JOIN sys.[dm_exec_sessions] s
ON s.[session_id] = tst.[session_id]
JOIN sys.dm_exec_connections c
ON c.[session_id] = tst.[session_id]
LEFT OUTER JOIN sys.dm_exec_requests r
ON r.[session_id] = tst.[session_id]
CROSS APPLY sys.dm_exec_sql_text (c.[most_recent_sql_handle]) AS st
OUTER APPLY sys.dm_exec_query_plan (r.[plan_handle]) AS qp
WHERE DB_NAME (tdt.database_id) = 'tempdb'
ORDER BY [Log Bytes Used] DESC
GO
इस पोस्ट के लिए धन्यवाद, शायद अपनी तरह का एकमात्र। मेरा परीक्षण सरल था, एक अस्थायी तालिका बनाएं और सुनिश्चित करें कि जब मैं इस पोस्ट से किसी भी प्रश्न को चलाता हूं तो यह दिखाता है ... केवल एक या दो वास्तव में सफल हुए। मैंने इसे टी-एसक्यूएल में शामिल होने के लिए ठीक किया, इसे लंबे समय तक चलने के लिए अनुकूलित किया और इसे बहुत उपयोगी बना दिया। अगर मुझे कुछ याद है तो मुझे बताएं लेकिन अब तक आपको एक स्वचालित / लूप स्क्रिप्ट मिली है। यह आकलन करने का एक तरीका प्रदान करता है कि कौन सी क्वेरी / SPID मानक विचलन (STDEV) क्वेरी का उपयोग करके नीचे की अवधि में अपराधी है।
यह हर 3 मिनट 40 बार चलता है, इसलिए 2 घंटे। जैसा कि आप फिट देखते हैं मापदंडों को संशोधित करें।
नीचे एक WHERE> 50 पेज का फिल्टर है, जिसमें लोग आपके छोटे टेबल के बहुत सारे होने पर ही साफ करना चाहते हैं। अन्यथा आप उस बारीकियों को नीचे से नहीं पकड़ेंगे जैसा कि यह है ...
का आनंद लें!
DECLARE @minutes_apart INT; SET @minutes_apart = 3
DECLARE @how_many_times INT; SET @how_many_times = 40
--DROP TABLE tempdb..TempDBUsage
--SELECT * FROM tempdb..TempDBUsage
--SELECT session_id, STDEV(pages) stdev_pages FROM tempdb..TempDBUsage GROUP BY session_id HAVING STDEV(pages) > 0 ORDER BY stdev_pages DESC
DECLARE @delay_string NVARCHAR(8); SET @delay_string = '00:' + RIGHT('0'+ISNULL(CAST(@minutes_apart AS NVARCHAR(2)), ''),2) + ':00'
DECLARE @counter INT; SET @counter = 1
SET NOCOUNT ON
if object_id('tempdb..TempDBUsage') is null
begin
CREATE TABLE tempdb..TempDBUsage (
session_id INT, pages INT, num_reads INT, num_writes INT, login_time DATETIME, last_batch DATETIME,
cpu INT, physical_io INT, hostname NVARCHAR(64), program_name NVARCHAR(128), text NVARCHAR (MAX)
)
end
else
begin
PRINT 'To view the results run this:'
PRINT 'SELECT * FROM tempdb..TempDBUsage'
PRINT 'OR'
PRINT 'SELECT session_id, STDEV(pages) stdev_pages FROM tempdb..TempDBUsage GROUP BY session_id HAVING STDEV(pages) > 0 ORDER BY stdev_pages DESC'
PRINT ''
PRINT ''
PRINT 'Otherwise manually drop the table by running the following, then re-run the script:'
PRINT 'DROP TABLE tempdb..TempDBUsage'
RETURN
end
--GO
TRUNCATE TABLE tempdb..TempDBUsage
PRINT 'To view the results run this:'; PRINT 'SELECT * FROM tempdb..TempDBUsage'
PRINT 'OR'; PRINT 'SELECT session_id, STDEV(pages) stdev_pages FROM tempdb..TempDBUsage GROUP BY session_id HAVING STDEV(pages) > 0 ORDER BY stdev_pages DESC'
PRINT ''; PRINT ''
while @counter <= @how_many_times
begin
INSERT INTO tempdb..TempDBUsage (session_id,pages,num_reads,num_writes,login_time,last_batch,cpu,physical_io,hostname,program_name,text)
SELECT PAGES.session_id, PAGES.pages, r.num_reads, r.num_writes, sp.login_time, sp.last_batch, sp.cpu, sp.physical_io, sp.hostname, sp.program_name, t.text
FROM sys.dm_exec_connections AS r
LEFT OUTER JOIN master.sys.sysprocesses AS sp on sp.spid=r.session_id
OUTER APPLY sys.dm_exec_sql_text(r.most_recent_sql_handle) AS t
LEFT OUTER JOIN (
SELECT s.session_id, [pages] = SUM(s.user_objects_alloc_page_count + s.internal_objects_alloc_page_count)
FROM sys.dm_db_session_space_usage AS s
GROUP BY s.session_id
HAVING SUM(s.user_objects_alloc_page_count + s.internal_objects_alloc_page_count) > 0
) PAGES ON PAGES.session_id = r.session_id
WHERE PAGES.session_id IS NOT NULL AND PAGES.pages > 50
ORDER BY PAGES.pages DESC;
PRINT CONVERT(char(10), @counter) + ': Ran at: ' + CONVERT(char(30), GETDATE())
SET @counter = @counter + 1
waitfor delay @delay_string
end
दुर्भाग्य से tempDB लॉग सीधे चल रही प्रक्रियाओं को देखने के द्वारा सत्रांक में वापस पता नहीं लगाया जा सकता है।
TempDB लॉग फ़ाइल को उस बिंदु पर सिकोड़ें जहां वह फिर से बढ़ेगा। फिर लॉग ग्रोथ को कैप्चर करने के लिए एक विस्तारित ईवेंट बनाएं। एक बार जब यह फिर से बढ़ता है तो आप विस्तारित घटना का विस्तार कर सकते हैं और पैकेज ईवेंट फ़ाइल देख सकते हैं। फ़ाइल खोलें, एक समय फ़िल्टर जोड़ें, फ़ाइल प्रकार फ़िल्टर (आप डेटा फ़ाइल परिणाम शामिल नहीं करना चाहते हैं), और फिर इसे SSMS में सत्र आईडी द्वारा समूहित करें। इससे आपको अपराधी को ढूंढने में मदद मिलेगी, क्योंकि आप सत्र आईडी की तलाश कर रहे हैं। बेशक आपको एक और प्रक्रिया या उपकरण के माध्यम से सत्र आईडी में जो कुछ भी चल रहा है उसे इकट्ठा करने की आवश्यकता है। हो सकता है कि किसी को पता हो कि कैसे क्वेरी_हाश कॉलम से क्वेरी प्राप्त करना है और समाधान पोस्ट करने के लिए पर्याप्त होगा।
विस्तारित घटना के परिणाम:
विस्तारित घटना बनाने के लिए स्क्रिप्ट:
CREATE EVENT SESSION [tempdb_file_size_changed] ON SERVER ADD EVENT
sqlserver.database_file_size_change(SET collect_database_name=(1)ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.is_system,sqlserver.query_hash,sqlserver.session_id,sqlserver.session_nt_username,sqlserver.sql_text,sqlserver.username) WHERE ([database_id]=(2))) ADD TARGETpackage0.event_file(SET filename=N'C:\ExtendedEvents\TempDBGrowth.xel',max_file_size=(100),max_rollover_files=(25)) WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=1 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=ON)