क्या ट्रिगर में निष्पादन कॉल स्टैक प्राप्त करना संभव है?


16

मेरे पास 10 संग्रहीत कार्यविधियाँ हैं और उनमें से प्रत्येक एक तालिका में INSERTs करता है।

क्या यह संभव है कि टेबलएक्स के एक ट्रिगर बॉडी में टेबलएक्स (संग्रहीत proc1 या sp2 या ....) के संशोधन का कारण बनता है?

धन्यवाद।

जवाबों:


9

हां, पूरा नाम रखने के लिए @@ procid सिस्टम फ़ंक्शन , और बेहतर OBJECT_NAME (@@ PROCID) का उपयोग करके , रनिंग कोड की पहचान करना संभव है ।

परिभाषा: "वर्तमान Transact-SQL मॉड्यूल के ऑब्जेक्ट आइडेंटिफ़ायर (ID) को लौटाता है। एक Transact-SQL मॉड्यूल एक संग्रहीत कार्यविधि, उपयोगकर्ता-परिभाषित फ़ंक्शन या ट्रिगर हो सकता है। @@ PROCID को CLR मॉड्यूल या में निर्दिष्ट नहीं किया जा सकता है। डेटा एक्सेस प्रदाता की प्रक्रिया करें। "

आप इसके बारे में यहां पढ़ सकते हैं ।

एक अन्य विकल्प वर्तमान स्पिड की sql योजना की जांच करना और लॉगिंग टेबल में उस जानकारी को सहेजना होगा। ऑडिट डेटा को बचाने के लिए प्रत्येक प्रक्रिया में उपयोग की जाने वाली एक नमूना क्वेरी होगी:

select sp.hostname, sp.program_name, sp.loginame,
    st.text as query_text
from sysprocesses sp
cross apply sys.dm_exec_sql_text(sp.sql_handle) as st  
where sp.spid = @@spid

शायद वहाँ बहुत सारे विवरण हैं..लेकिन मेरा मानना ​​है कि आपको विचार मिलता है।

तीसरा विकल्प वर्तमान एसपी के सत्र के संदर्भ_ जानकारी का उपयोग करना होगा । और कहीं न कहीं संदर्भ जानकारी को प्रत्येक प्रक्रिया के साथ सहेजा। उदाहरण के लिए प्रक्रिया 1 में आप संदर्भ में 111 लिखते हैं, प्रक्रिया 2 में आप 222 लिखते हैं .. और इसी तरह।

Reference_info के बारे में बहुत अधिक जानकारी आप इस SO प्रश्न में पढ़ सकते हैं ।


1
1) ट्रिगर रिटर्न में OBJECT_NAME (@@ PROCID) ट्रिगर नाम :( 2) ट्रिगर पर बस जानकारी होना आवश्यक है। 3) Reference_info एक समाधान है। धन्यवाद।
गरिक जूल

1
हाँ, एक ट्रिगर के अंदर OBJECT_NAME(@@PROCID)ट्रिगर नाम लौटाता है, कॉलिंग नहीं।
ProfK

यह सीधे तौर पर गलत है। यह ट्रिगर का नाम देता है, न कि कॉलिंग प्रक्रिया का। जैसा कि ओपी ने पूछा
उलटा इंजीनियर

सहमत, उत्तर गलत है। यदि आप अपस्ट्रीम प्रक्रिया को संशोधित कर सकते हैं तो CONTEXT_INFO काम करता है।
टॉम वॉरफील्ड

3

मैं भी यही करना चाहता था। जवाब के लिए धन्यवाद। जैसा कि मैं अभी भी यहाँ हूँ, मैं अपना परीक्षण दूसरों के समय को बचाने के लिए करूँगा :)

CREATE TABLE  Test ( TestID INT )
GO

CREATE TRIGGER TestTrigger ON Test
FOR INSERT
AS

SELECT CAST(CONTEXT_INFO() AS NVARCHAR(128));
GO

CREATE PROCEDURE usp_ProcIDTest
AS

DECLARE @ProcedureName VARBINARY(MAX) = CAST(OBJECT_NAME(@@PROCID) AS VARBINARY(MAX))
SET CONTEXT_INFO @ProcedureName

INSERT INTO Test ( TestID ) VALUES ( 1 ) 

GO

EXEC usp_ProcIDTest
GO

DROP TABLE Test
GO

2

XEvents टी-एसक्यूएल स्टैक ज्ञात करने के लिए एक और तरीका प्रदान करते हैं, हालांकि SQL Server 2008 एक प्रयुक्त घटना प्रकार का समर्थन नहीं कर सकता है। समाधान में एक ट्रिगर, एक त्रुटि और एक XEvent सत्र होता है। जिस तरह से यह काम करता है, मैंने जिम ब्राउन का उदाहरण लिया।

सबसे पहले, मैंने SQL Server 2016 SP2CU2 देव संस्करण के समाधान का परीक्षण किया। SQL सर्वर 2008 कुछ EXevent का समर्थन करता है, लेकिन मेरे पास कोई उदाहरण नहीं है ताकि मैं इसका परीक्षण न कर सकूं।

विचार एक डमी ट्राइ-कैच ब्लॉक में उपयोगकर्ता त्रुटि उत्पन्न करने के लिए है, फिर tsql_stackकार्रवाई के साथ XEvent सत्र के अंदर त्रुटि को पकड़ें । SQLSERVER.error_reportedXEvent प्रकार सभी त्रुटियों को पकड़ सकता है, भले ही एक ट्राइ-कैच ब्लॉक उन्हें फंसा ले। अंत में, sys.dm_exec_sql_textक्वेरी से हैंडल किए गए टी-एसक्यूएल प्रश्नों को निकालें , जो tsql_stackएक्शन देता है।

जिम ब्राउन के उत्तर से एक उदाहरण, जो मैंने विकसित किया है, नीचे दिखाया गया है। एक ट्रिगर 'मुझे पकड़ लो' पाठ के साथ त्रुटि उठाता है। XEvent सत्र केवल 'मुझे पकड़ो' जैसे पाठ के साथ त्रुटियों को पकड़ता है।

CREATE TABLE  Test ( TestID INT )

GO

CREATE TRIGGER TestTrigger ON Test
FOR INSERT
AS
BEGIN TRY
    SET XACT_ABORT OFF; -- REALLY IMPORTANT!
    /* make an catching a great deal more interesting */
    DECLARE @TestID NVARCHAR(MAX) ;
    SELECT TOP (1) @TestID = CAST(ins.TestID AS NVARCHAR(MAX)) FROM inserted AS ins ;
    RAISERROR (N'catch_me TestID = "%s"' , 11 , 0 , @TestID) ;
END TRY BEGIN CATCH /* NOTHING TO DO */ END CATCH

GO

CREATE PROCEDURE usp_ProcIDTest
AS
INSERT INTO Test ( TestID ) VALUES ( 1 ) 

GO

CREATE PROCEDURE usp_RootProcIDTest
AS
EXEC usp_ProcIDTest

GO

-- This XEvent session definition was kindly provided by XEvent 'New Session' wizard.
CREATE EVENT SESSION [catch_insertion_into_Test] ON SERVER 
ADD EVENT sqlserver.error_reported(
    ACTION(package0.callstack,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_nt_username,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack,sqlserver.username,sqlserver.context_info,sqlserver.plan_handle)
    WHERE ([message] like N'catch_me%'))
ADD TARGET package0.ring_buffer(SET max_memory=(10240))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=ON)

GO

अब, यदि आप XEvent सेशन (SSMS, ऑब्जेक्ट एक्सप्लोरर, मैनेजमेंट, एक्सटेंडेड इवेंट्स, सेशंस, catch_insertion_into_Test) लॉन्च करते हैं, तो usp_RootProcIDTest निष्पादित करें और XEvent सेशन के रिंग बफर देखें, आपको XML को देखना चाहिए जिसमें नोड हो <action name="tsql_stack" package="sqlserver">। फ्रेम नोड्स का एक क्रम है। handleसिस्टम फ़ंक्शन 'sysinos_exec_sql_text', औरilil में एक 'गुण का मान रखें

-- REPLACE MY HANDLES WITH YOURS
SELECT * FROM sys.dm_exec_sql_text(0x03000800D153096910272C01A6AA000000000000000000000000000000000000000000000000000000000000);
SELECT * FROM sys.dm_exec_sql_text(0x030008000A78FD6912272C01A6AA000001000000000000000000000000000000000000000000000000000000);
SELECT * FROM sys.dm_exec_sql_text(0x03000800439CF16A13272C01A6AA000001000000000000000000000000000000000000000000000000000000);

एक निष्पादन कॉल स्टैक उदाहरण

XEvent आपको इससे बहुत अधिक काम करने देता है! उन्हें सीखने के अवसर न चूकें!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.