5

एमएस एसक्यूएल सर्वर में, मैं क्लाइंट द्वारा पारित सत्र से संबंधित जानकारी संग्रहीत करने के लिए एक वैश्विक अस्थायी तालिका का उपयोग कर रहा हूं और फिर मैं उस जानकारी को ट्रिगर्स के अंदर उपयोग करता हूं।एमएस एसक्यूएल सर्वर - वैश्विक अस्थायी तालिका का सुरक्षित समवर्ती उपयोग?

चूंकि एक ही वैश्विक अस्थायी तालिका का उपयोग अलग-अलग सत्रों में किया जा सकता है और जब मैं इसमें लिखना चाहता हूं तो यह हो सकता है या नहीं हो सकता है (इस पर निर्भर करता है कि पिछले सभी सत्र जो इसे पहले बंद कर चुके हैं), मैं कर रहा हूं ग्लोबल अस्थायी तालिका अस्तित्व के लिए एक चेक जिसके आधार पर मैं इसे लिखने से पहले बना हूं।

IF OBJECT_ID('tempdb..##VTT_CONTEXT_INFO_USER_TASK') IS NULL 
    CREATE TABLE ##VTT_CONTEXT_INFO_USER_TASK (
    session_id smallint, 
    login_time datetime, 
    HstryUserName VDT_USERNAME, 
    HstryTaskName VDT_TASKNAME, 
) 

MERGE ##VTT_CONTEXT_INFO_USER_TASK As target 
USING (SELECT @@SPID, @HstryUserName, @HstryTaskName) as source (session_id, HstryUserName, HstryTaskName) 
ON (target.session_id = source.session_id) 
WHEN MATCHED THEN 
    UPDATE SET HstryUserName = source.HstryUserName, HstryTaskName = source.HstryTaskName 
WHEN NOT MATCHED THEN 
    INSERT VALUES (@@SPID, @LoginTime, source.HstryUserName, source.HstryTaskName); 

समस्या तालिका अस्तित्व के लिए मेरा चैक और MERGE बयान के बीच, एसक्यूएल सर्वर अस्थायी तालिका छोड़ सकते कि सभी सत्रों जो इसे पहले हो उपयोग कर रहे थे कि सटीक उदाहरण में बंद करने के लिए कि क्या (यह वास्तव में क्या हुआ है मेरे परीक्षण में)।

इस तरह के समवर्ती मुद्दों से बचने के तरीके पर एक सर्वोत्तम अभ्यास है, कि इसके अस्तित्व के लिए चेक और इसके बाद के उपयोग के बीच एक तालिका नहीं छोड़ी गई है?

उत्तर

2

मैं यह कहकर शुरू करूंगा कि, लंबी अवधि में, मैं गॉर्डन की सलाह का पालन करूंगा, यानी मैं क्लाइंट एप्लिकेशन जानकारी को संग्रहीत करने के लिए डेटाबेस में एक सामान्य तालिका पेश करने के लिए आवश्यक कदम उठाऊंगा, जिसमें इसे सुलभ करने की आवश्यकता है चलाता है।

लेकिन चूंकि समय की बाधाओं के कारण अब यह वास्तव में संभव नहीं था (एक नई सामान्य तालिका के लिए आवश्यक औपचारिक अनुमोदन प्राप्त करने में सप्ताह लगते हैं), मैं SQL सर्वर को वैश्विक अस्थायी तालिका को छोड़ने से रोकने के लिए एक समाधान के साथ आया इसके अस्तित्व की जांच और MERGE कथन।

SQL सर्वर द्वारा वैश्विक टेम्पल तालिका को गिराए जाने के बारे में कुछ जानकारी है; मेरे व्यक्तिगत परीक्षणों से पता चला है कि SQL सर्वर एक वैश्विक अस्थायी तालिका को छोड़ देता है जिस क्षण इसे बनाया गया सत्र बंद हो जाता है और अन्य सत्रों में शुरू होने वाले किसी अन्य लेन-देन को उस तालिका में डेटा बदल दिया जाता है।

मेरा समाधान वैश्विक अस्तित्व तालिका पर नकली डेटा परिवर्तनों के लिए था, इससे पहले कि मैं इसके अस्तित्व की जांच कर सकूं। यदि उस पल में तालिका मौजूद है, तो SQL सर्वर तब पता चलेगा कि इसे चालू लेनदेन समाप्त होने तक इसे रखने की आवश्यकता है, और इसके अस्तित्व की जांच के बाद इसे और नहीं छोड़ा जा सकता है। कोड इस तरह अब लग रहा है (ठीक से टिप्पणी की है, क्योंकि यह एक हैक की तरह है):

-- Faking a delete on the table ensures that SQL Server will keep the table until the end of the transaction 
-- Since ##VTT_CONTEXT_INFO_USER_TASK may actually not exist, we need to fake the delete inside TRY .. CATCH 
-- FUTURE 2016, Feb 03: A cleaner solution would use a real table instead of a global temp table. 
BEGIN TRY 
    -- Because schema errors are checked during compile, they cannot be caught using TRY, this can be done by wrapping the query in sp_executesql 
    DECLARE @QueryText NVARCHAR(100) = 'DELETE ##VTT_CONTEXT_INFO_USER_TASK WHERE 0 = 1' 
    EXEC sp_executesql @QueryText 
END TRY 
BEGIN CATCH 
-- nothing to do here (see comment above) 
END CATCH 

IF OBJECT_ID('tempdb..##VTT_CONTEXT_INFO_USER_TASK') IS NULL 
    CREATE TABLE ##VTT_CONTEXT_INFO_USER_TASK (
    session_id smallint, 
    login_time datetime, 
    HstryUserName VDT_USERNAME, 
    HstryTaskName VDT_TASKNAME, 
) 

MERGE ##VTT_CONTEXT_INFO_USER_TASK As target 
USING (SELECT @@SPID, @HstryUserName, @HstryTaskName) as source (session_id, HstryUserName, HstryTaskName) 
ON (target.session_id = source.session_id) 
WHEN MATCHED THEN 
    UPDATE SET HstryUserName = source.HstryUserName, HstryTaskName = source.HstryTaskName 
WHEN NOT MATCHED THEN 
    INSERT VALUES (@@SPID, @LoginTime, source.HstryUserName, source.HstryTaskName); 

हालांकि मैं यह एक समाधान "अपने जोखिम पर इसका इस्तेमाल करते हैं" कहेंगे, इसे रोक है कि के उपयोग अन्य सत्रों में वैश्विक अस्थायी तालिका वर्तमान में अपने उपयोग को प्रभावित करती है, जो चिंता थी जिसने मुझे यह धागा शुरू किया।

आपके समय के लिए धन्यवाद! (पाठ स्वरूपण संपादन से जवाब में)

4

"वैश्विक अस्थायी तालिका" और "ट्रिगर" की धारणा बस क्लिक न करें। टेबल्स स्थायी डेटा स्टोर्स हैं, जैसे कि उनके गुण - ट्रिगर सहित। सर्वर फिर से शुरू होने पर अस्थायी सारणी गिरा दी जाती है। कोई भी ऐसे सिस्टम को क्यों डिजाइन करेगा जहां स्थायी कोड ब्लॉक (ट्रिगर) अस्थायी साझा स्टोरेज तंत्र पर निर्भर करता है? यह विफलता के लिए एक नुस्खा की तरह लगता है।

वैश्विक अस्थायी तालिका के बजाय, वास्तविक तालिका का उपयोग करें। यदि आप चाहें, तो नाम के सामने temp_ जैसे सहायक उपसर्ग डालें। यदि तालिका डेटाबेस द्वारा साझा की जा रही है, तो उसे डेटाबेस में रखें जहां सभी कोडों तक पहुंच हो।

एक बार तालिका बनाएं और इसे वहां छोड़ दें (पंक्तियों को हटाना ठीक है) तो ट्रिगर कोड इसका उपयोग कर सकता है।

+0

त्वरित उत्तर के लिए धन्यवाद! जबकि मैं मानता हूं कि मैंने स्थायी कोड बनाम अस्थायी साझा स्टोरेज अवधारणा नहीं माना है और आपने मुझे कुछ सोचने के लिए कुछ दिया है, मेरे पास वैश्विक अस्थायी तालिका का उपयोग करने के लिए कारण हैं: - मेरे काम में, मैं उपयोग करने के लिए स्वतंत्र हूं अस्थायी सारणी, लेकिन वास्तविक तालिकाओं के निर्माण को एक अलग, औपचारिक, नौकरशाही प्रक्रिया के माध्यम से जाना है; मैं इससे बचने की कोशिश करता हूं। - एक अस्थायी तालिका का उपयोग करके, मुझे लाभ मिलता है कि SQL सर्वर इसे मेरे लिए हटा देता है जब कोई सत्र अब इसका उपयोग नहीं कर रहा है। एक असली मेज बस वहां रहेगी और बढ़ती रहेगी। –

+0

@loadH। । । ओह, हां, नौकरशाही और अजीब मतभेद वास्तव में चीजों को पूरा करने के लिए। मैं पूरी तरह से समझता हूं। फिर भी, शायद कुछ स्टार्ट-अप कार्रवाई के दौरान वैश्विक अस्थायी तालिका बनाने की संभावना है, इसलिए यह ट्रिगर्स के लिए उपलब्ध है। मुझे ट्रिगर्स में टेबल बनाने की कोशिश करने का विचार पसंद नहीं है। –

संबंधित मुद्दे