Sql Server में, क्या यह जांचने का एक तरीका है कि चयनित पंक्तियों का समूह लॉक है या नहीं?


21

हम बहु-अरब पंक्ति तालिका में बड़ी संख्या में रिकॉर्ड अपडेट / डिलीट करने का प्रयास कर रहे हैं। चूंकि यह एक लोकप्रिय तालिका है, इसलिए इस तालिका के विभिन्न अनुभागों में बहुत सारी गतिविधि है। किसी भी बड़ी अपडेट / डिलीट गतिविधि को समय की विस्तारित अवधि के लिए अवरुद्ध किया जा रहा है (क्योंकि यह सभी पंक्तियों या पेज लॉक या टेबल लॉक पर ताले पाने के लिए इंतजार कर रहा है) जिसके परिणामस्वरूप टाइमआउट या कार्य को पूरा करने के लिए कई दिन लगते हैं।

इसलिए, हम उस समय पंक्तियों के छोटे बैच को हटाने के लिए दृष्टिकोण बदल रहे हैं। लेकिन हम यह जांचना चाहते हैं कि चयनित (मान लें कि 100 या 1000 या 2000 पंक्तियाँ) वर्तमान में किसी भिन्न प्रक्रिया द्वारा लॉक हैं या नहीं।

  • यदि नहीं, तो हटाएं / अपडेट के साथ आगे बढ़ें।
  • यदि वे बंद हैं, तो रिकॉर्ड के अगले समूह पर जाएं।
  • अंत में, भीख मांगने के लिए वापस आएं और बाएं लोगों को अपडेट / हटाने का प्रयास करें।

क्या यह करने योग्य है?

धन्यवाद, ToC


2
क्या आपने डिलीट स्टेटमेंट या NowAIT (पूरे ग्रुप को फेल करने के लिए) के हिस्से के रूप में READPAST में देखा है? इनमें से एक आपके लिए काम कर सकता है। msdn.microsoft.com/en-us/library/ms187373.aspx
सीन कहता है सारा चीप्स निकालें

@ सीनगर्लडी मैंने उस विचार पर विचार नहीं किया है, लेकिन अब मैं करूंगा। लेकिन क्या यह जांचने का एक आसान तरीका है कि कोई विशेष पंक्ति लॉक है या नहीं? धन्यवाद।
टीओसी

3
आप LOCK_TIMEOUT ( msdn.microsoft.com/en-us/library/ms189470.aspx ) को भी देख सकते हैं । उदाहरण के लिए, यह वह तरीका है जो एडम मैकानिक के sp_whoisactive सुनिश्चित करता है कि निष्पादन योजना को इकट्ठा करने की कोशिश में अवरुद्ध होने पर प्रक्रिया बहुत लंबे समय तक इंतजार नहीं करती है। आप कुछ समय समाप्त कर सकते हैं या यहां तक ​​कि 0 के मूल्य का उपयोग कर सकते हैं ("0 का मतलब बिल्कुल भी इंतजार न करें और जैसे ही एक लॉक का सामना होता है एक संदेश वापस करें।") आप इसे 1222 (त्रुटि) को पकड़ने के लिए TRY / CATCH के साथ जोड़ सकते हैं। "लॉक रिक्वेस्ट टाइम आउट पीरियड पार हो गया") और अगले बैच के लिए आगे बढ़ें।
ज्योफ पैटरसन

@gpatterson दिलचस्प दृष्टिकोण। मैं भी यही कोशिश करूँगा।
टीओसी

2
जवाब देने के लिए, नहीं, यह देखने का एक आसान तरीका नहीं है कि क्या पंक्तियां लॉक हैं जब तक कि विशेष रूप से आवेदन में कुछ न हो। मूल रूप से आप पहली बार एक Lock_timeout सेट के साथ HOLDLOCK और XLOCK के साथ चयन कर सकते हैं (जो कि मेरी मूल टिप्पणी में NowAIT है, समय-सीमा को 0 पर सेट करता है)। यदि आपको यह नहीं मिलता है, तो आपको पता है कि कुछ बंद है। कुछ भी आसानी से उपलब्ध नहीं है "इंडेक्स जेड का उपयोग करके तालिका Y में पंक्ति X है"। हम देख सकते हैं कि क्या तालिका में ताले हैं या किसी भी पृष्ठ / पंक्तियों / कुंजियों / आदि में ताले हैं, लेकिन किसी क्वेरी में विशिष्ट पंक्तियों में अनुवाद करना आसान नहीं होगा।
सीन कहता है कि सारा चीप्स निकालें

जवाबों:


10

यदि मैं अनुरोध को सही ढंग से समझता हूं, तो लक्ष्य पंक्तियों के बैचों को हटाना है, जबकि उसी समय, तालिका में पंक्तियों पर डीएमएल संचालन हो रहा है। लक्ष्य एक बैच को हटाना है; हालाँकि, यदि किसी बैच द्वारा बताई गई सीमा के भीतर निहित कोई अंतर्निहित पंक्तियाँ बंद हैं, तो हमें उस बैच को छोड़ देना चाहिए और अगले बैच में चले जाना चाहिए। फिर हमें उन बैचों पर वापस लौटना चाहिए जो पहले हटाए नहीं गए थे और हमारे मूल डिलीट लॉजिक को पुनः प्राप्त कर रहे थे। हमें इस चक्र को तब तक दोहराना चाहिए जब तक कि पंक्तियों के सभी आवश्यक बैच हटा नहीं दिए जाते।

जैसा कि उल्लेख किया गया है, पिछली पंक्तियों को अवरुद्ध करने वाली पंक्तियों को शामिल करने के लिए READPAST संकेत और READ COMMITTED (डिफ़ॉल्ट) अलगाव स्तर का उपयोग करना उचित है। मैं एक कदम आगे जाऊंगा और सर्जिकल आइसोलेशन स्तर और नीबलिंग डिलीट का उपयोग करने की सलाह दूंगा।

SQL सर्वर सीरियल-रेंज के अलग-थलग लेन-देन के स्तर का उपयोग करते हुए Transact-SQL स्टेटमेंट द्वारा पढ़े जा रहे रिकॉर्ड सेट में शामिल पंक्तियों की एक श्रृंखला की सुरक्षा के लिए की-रेंज लॉक का उपयोग करता है ... अधिक जानकारी के लिए यहां देखें: https://technet.microsoft.com /en-US/library/ms191272(v=SQL.105).aspx

निम्बलिंग हटाने के साथ, हमारा लक्ष्य पंक्तियों की एक श्रृंखला को अलग करना है और यह सुनिश्चित करना है कि उन पंक्तियों में कोई परिवर्तन नहीं होगा जबकि हम उन्हें हटा रहे हैं, यही कहना है, हम प्रेत रीड या सम्मिलन नहीं चाहते हैं। इस समस्या को हल करने के लिए क्रमिक पृथक्करण स्तर है।

इससे पहले कि मैं अपना समाधान प्रदर्शित करूं, मैं यह जोड़ना चाहूंगा कि न तो मैं आपके डेटाबेस के डिफ़ॉल्ट अलगाव स्तर को SERIALIZABLE में बदलने की सिफारिश कर रहा हूं और न ही मैं यह सिफारिश कर रहा हूं कि मेरा समाधान सबसे अच्छा है। मैं केवल इसे प्रस्तुत करना चाहता हूं और देखना चाहता हूं कि हम यहां से कहां जा सकते हैं।

कुछ घर में रखने वाले नोट:

  1. SQL सर्वर संस्करण जो मैं उपयोग कर रहा हूं वह Microsoft SQL Server 2012 है - 11.0.5343.0 (X64)
  2. मेरा परीक्षण डेटाबेस पूर्ण पुनर्प्राप्ति मॉडल का उपयोग कर रहा है

अपना प्रयोग शुरू करने के लिए, मैं एक परीक्षण डेटाबेस, एक नमूना तालिका स्थापित करूंगा, और मैं 2,000,000 पंक्तियों के साथ तालिका भरूंगा।


USE [master];
GO

SET NOCOUNT ON;

IF DATABASEPROPERTYEX (N'test', N'Version') > 0
BEGIN
    ALTER DATABASE [test] SET SINGLE_USER
        WITH ROLLBACK IMMEDIATE;
    DROP DATABASE [test];
END
GO

-- Create the test database
CREATE DATABASE [test];
GO

-- Set the recovery model to FULL
ALTER DATABASE [test] SET RECOVERY FULL;

-- Create a FULL database backup
-- in order to ensure we are in fact using 
-- the FULL recovery model
-- I pipe it to dev null for simplicity
BACKUP DATABASE [test]
TO DISK = N'nul';
GO

USE [test];
GO

-- Create our table
IF OBJECT_ID('dbo.tbl','U') IS NOT NULL
BEGIN
    DROP TABLE dbo.tbl;
END;
CREATE TABLE dbo.tbl
(
      c1 BIGINT IDENTITY (1,1) NOT NULL
    , c2 INT NOT NULL
) ON [PRIMARY];
GO

-- Insert 2,000,000 rows 
INSERT INTO dbo.tbl
    SELECT TOP 2000
        number
    FROM
        master..spt_values
    ORDER BY 
        number
GO 1000

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


-- Add a clustered index
CREATE UNIQUE CLUSTERED INDEX CIX_tbl_c1
    ON dbo.tbl (c1);
GO

-- Add a non-clustered index
CREATE NONCLUSTERED INDEX IX_tbl_c2 
    ON dbo.tbl (c2);
GO

अब, हम देखते हैं कि हमारी 2,000,000 पंक्तियाँ बनाई गई थीं


SELECT
    COUNT(*)
FROM
    tbl;

यहाँ छवि विवरण दर्ज करें

तो, हमारे पास हमारा डेटाबेस, टेबल, इंडेक्स और पंक्तियाँ हैं। तो, आइए हम निबलिंग डिलीट के लिए प्रयोग सेट करें। सबसे पहले, हमें यह तय करना होगा कि एक विशिष्ट निबलिंग डिलीट मैकेनिज्म कैसे बनाया जाए।


DECLARE
      @BatchSize        INT    = 100
    , @LowestValue      BIGINT = 20000
    , @HighestValue     BIGINT = 20010
    , @DeletedRowsCount BIGINT = 0
    , @RowCount         BIGINT = 1;

SET NOCOUNT ON;
GO

WHILE  @DeletedRowsCount <  ( @HighestValue - @LowestValue ) 
BEGIN

    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    BEGIN TRANSACTION

        DELETE 
        FROM
            dbo.tbl 
        WHERE
            c1 IN ( 
                    SELECT TOP (@BatchSize)
                        c1
                    FROM
                        dbo.tbl 
                    WHERE 
                        c1 BETWEEN @LowestValue AND @HighestValue
                    ORDER BY 
                        c1
                  );

        SET @RowCount = ROWCOUNT_BIG();

    COMMIT TRANSACTION;

    SET @DeletedRowsCount += @RowCount;
    WAITFOR DELAY '000:00:00.025';
    CHECKPOINT;

END;

जैसा कि आप देख सकते हैं, मैंने स्पष्ट लेनदेन को लूप के अंदर रखा। यदि आप लॉग फ्लश को सीमित करना चाहते हैं, तो इसे लूप के बाहर रखने के लिए स्वतंत्र महसूस करें। इसके अलावा, चूंकि हम पूर्ण पुनर्प्राप्ति मॉडल में हैं, इसलिए आप यह सुनिश्चित करने के लिए कि आप अपने लेन-देन लॉग को अपमानजनक रूप से बढ़ने से रोका जा सकता है, को सुनिश्चित करने के लिए अपने nIBling हटाए गए संचालन को चलाने के दौरान लेनदेन लॉग बैकअप बनाने की इच्छा हो सकती है।

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

अब, मैं कार्रवाई में इस विलोपन दिनचर्या का एक बहुत छोटा उदाहरण प्रदान करना चाहता हूं। हमें SSMS के भीतर एक नई विंडो खोलनी होगी और अपनी टेबल से एक पंक्ति को हटाना होगा। मैं डिफ़ॉल्ट READ COMMITTED आइसोलेशन स्तर का उपयोग करते हुए निहित लेनदेन के भीतर ऐसा करूंगा।


DELETE FROM
    dbo.tbl
WHERE
    c1 = 20005;

क्या यह पंक्ति वास्तव में हटा दी गई थी?


SELECT
    c1
FROM
    dbo.tbl
WHERE
    c1 BETWEEN 20000 AND 20010;

हाँ, इसे हटा दिया गया था।

हटाए गए रोल का सबूत

अब, हमारे तालों को देखने के लिए, SSMS के भीतर एक नई विंडो खोलें और एक कोड स्निपेट या दो जोड़ें। मैं एडम मैकेनिक के sp_whoisactive का उपयोग कर रहा हूं, जो यहां पाया जा सकता है: sp_whoisactive


SELECT
    DB_NAME(resource_database_id) AS DatabaseName
  , resource_type
  , request_mode
FROM
    sys.dm_tran_locks
WHERE
    DB_NAME(resource_database_id) = 'test'
    AND resource_type = 'KEY'
ORDER BY
    request_mode;

-- Our insert
sp_lock 55;

-- Our deletions
sp_lock 52;

-- Our active sessions
sp_whoisactive;

अब, हम शुरू करने के लिए तैयार हैं। एक नई SSMS विंडो में, हम एक स्पष्ट लेन-देन शुरू करते हैं जो हमने हटा दी गई एक पंक्ति को फिर से सम्मिलित करने का प्रयास करेगा। उसी समय, हम अपने nibbling डिलीट ऑपरेशन को बंद कर देंगे।

सम्मिलित कोड:


BEGIN TRANSACTION

    SET IDENTITY_INSERT dbo.tbl ON;

    INSERT  INTO dbo.tbl
            ( c1 , c2 )
    VALUES
            ( 20005 , 1 );

    SET IDENTITY_INSERT dbo.tbl OFF;

--COMMIT TRANSACTION;

आइए डालने के साथ शुरू होने वाले दोनों ऑपरेशनों को किक करते हैं और उसके बाद हमारा डिलीट करते हैं। हम कुंजी-श्रेणी के ताले और अनन्य ताले देख सकते हैं।

रेंज और eXclusive ताले

सम्मिलित ने इन तालों को उत्पन्न किया:

ताले डालें

निम्बलिंग हटाएं / चयन इन तालों को पकड़ रहा है:

यहाँ छवि विवरण दर्ज करें

हमारा इन्सर्ट उम्मीद के अनुसार हमारे डिलीट को रोक रहा है:

ब्लॉक हटाएं डालें

अब, इंसर्ट ट्रांजेक्शन करें और देखें कि क्या है।

हटाएं

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


SELECT
    c1
FROM
    dbo.tbl
WHERE
    c1 BETWEEN 20000 AND 20015;

वास्तव में, सम्मिलित हटा दिया गया था; इसलिए, कोई प्रेत डालने की अनुमति नहीं थी।

कोई प्रेत नहीं डालें

इसलिए, निष्कर्ष में, मुझे लगता है कि इस अभ्यास का असली इरादा हर एक पंक्ति, पृष्ठ, या तालिका-स्तरीय लॉक को ट्रैक करना और ट्रैक करना नहीं है और यह निर्धारित करने का प्रयास करना है कि क्या बैच का एक तत्व बंद है और इसलिए हमारे हटाने के ऑपरेशन की आवश्यकता होगी रुकिए। यह प्रश्नकर्ताओं की मंशा रही होगी; हालाँकि, यह कार्य असंभव है और यदि असंभव नहीं है तो मूल रूप से अव्यवहारिक है। वास्तविक लक्ष्य यह सुनिश्चित करना है कि एक बार कोई अवांछित घटना न उत्पन्न हो जाए, जब हमने अपने बैच की सीमा को अपने स्वयं के ताले से अलग कर दिया है और फिर बैच को हटाने के लिए पूर्ववर्ती है। अनुक्रमिक अलगाव स्तर इस उद्देश्य को प्राप्त करता है। कुंजी आपके निबल्स को छोटा रखना, आपके लेन-देन को नियंत्रण में रखना और अवांछित घटनाओं को खत्म करना है।

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

मुझे बताओ कि तुम क्या सोचते हो।

मैंने कार्रवाई में अनुक्रमिक अलगाव स्तर के कुछ और उदाहरण बनाए। वे नीचे दिए गए लिंक पर उपलब्ध होना चाहिए।

ऑपरेशन हटाएँ

ऑपरेशन डालें

इक्विटी ऑपरेशंस - की-रेंज लॉक्स नेक्स्ट की वैल्यूज पर

इक्वैलिटी ऑपरेशंस - सिंगलटन फ़ॉन्च ऑफ़ एक्स्टेंट डेटा

समानता संचालन - कोई नहीं डेटा का सिंगलटन फ़ेच

असमानता ऑपरेशन - की-रेंज लॉक्स ऑन रेंज और नेक्स्ट की वैल्यू


9

इसलिए, हम उस समय पंक्तियों के छोटे बैच को हटाने के लिए दृष्टिकोण बदल रहे हैं।

यह छोटे सावधान बैच या विखंडू में हटाने के लिए एक बहुत अच्छा विचार है । मैं होगा जोड़ने के लिए एक छोटा सा waitfor delay '00:00:05'और डेटाबेस की वसूली मॉडल के आधार पर - अगर FULLहै, तो एक कर log backupऔर अगर SIMPLEएक तो manual CHECKPOINTलेन-देन लॉग की सूजन से बचने के लिए - बैचों के बीच।

लेकिन हम यह जांचना चाहते हैं कि चयनित (मान लें कि 100 या 1000 या 2000 पंक्तियाँ) वर्तमान में किसी भिन्न प्रक्रिया द्वारा लॉक हैं या नहीं।

जो आप बता रहे हैं वह पूरी तरह से आउट ऑफ बॉक्स (आपके 3 बुलेट पॉइंट्स को ध्यान में रखते हुए) संभव नहीं है। यदि उपरोक्त सुझाव - small batches + waitfor delayकाम नहीं करता है (बशर्ते आप उचित परीक्षण करें), तो आप इसका उपयोग कर सकते हैं query HINT

उपयोग न करें NOLOCK- देखिए kb / 308886 , SQL सर्वर रीड-कंसिस्टेंसी प्रॉब्लम्स इट्ज़िक बेन-गण द्वारा , हर जगह NOLOCK लगाना - हारून बर्ट्रेंड और SQL सर्वर NOLOCK संकेत और अन्य खराब विचारों द्वारा

READPASTसंकेत आपके परिदृश्य में मदद करेगा। READPASTसंकेत का सार है - यदि कोई पंक्ति स्तर लॉक है तो SQL सर्वर इसे नहीं पढ़ेगा।

निर्दिष्ट करता है कि डेटाबेस इंजन उन पंक्तियों को नहीं पढ़ता है जो अन्य लेनदेन द्वारा लॉक हैं। जब READPASTनिर्दिष्ट किया जाता है, तो पंक्ति-स्तरीय लॉक को छोड़ दिया जाता है। यही है, डेटाबेस इंजन वर्तमान लेनदेन को अवरुद्ध करने के बजाय पंक्तियों को छोड़ देता है जब तक कि ताले जारी नहीं किए जाते हैं।

अपने सीमित परीक्षण के दौरान, मैंने DELETE from schema.tableName with (READPAST, READCOMMITTEDLOCK)क्वेरी सत्र अलगाव स्तर का READ COMMITTEDउपयोग करते हुए और सेट करते समय वास्तव में अच्छा थ्रूपुट पाया SET TRANSACTION ISOLATION LEVEL READ COMMITTEDजो कि वैसे भी डिफ़ॉल्ट अलगाव स्तर है।


2

मूल रूप से प्रश्न के लिए टिप्पणियों में पेश किए गए अन्य दृष्टिकोणों को सारांशित करना।


  1. NOWAITयदि असंगत लॉक का सामना होते ही पूरे चंक को विफल करने के लिए इच्छित व्यवहार का उपयोग किया जाता है।

    से NOWAITप्रलेखन :

    डेटाबेस इंजन को निर्देश देता है कि जैसे ही मेज पर ताला लगा हो, एक संदेश लौटा दें। एक विशिष्ट तालिका के NOWAITलिए निर्दिष्ट करने के बराबर है SET LOCK_TIMEOUT 0NOWAITजब संकेत काम नहीं करता TABLOCKसंकेत भी शामिल है। TABLOCKसंकेत का उपयोग किए बिना प्रतीक्षा किए बिना किसी क्वेरी को समाप्त करने के लिए , SETLOCK_TIMEOUT 0;इसके बजाय क्वेरी को प्रस्तुत करें ।

  2. SET LOCK_TIMEOUTएक समान परिणाम प्राप्त करने के लिए उपयोग करें , लेकिन एक कॉन्फ़िगर करने योग्य समयबाह्य के साथ:

    से SET LOCK_TIMEOUTप्रलेखन

    निर्दिष्ट करता है कि मिलिसेकंड की संख्या एक बयान के लॉक होने का इंतजार करती है।

    जब किसी लॉक का इंतजार टाइमआउट मान से अधिक हो जाता है, तो एक त्रुटि वापस आ जाती है। 0 के मान का अर्थ है कि सभी का इंतजार न करना और लॉक का सामना होते ही एक संदेश वापस करना।


0

मानने के लिए हमारे पास 2 समानताएं प्रश्न हैं:

कनेक्ट / सत्र 1: पंक्ति को बंद कर देगा = 777

SELECT * FROM your_table WITH(UPDLOCK,READPAST) WHERE id = 777

कनेक्ट / सत्र 2: बंद पंक्ति = 777 की अनदेखी करेगा

SELECT * FROM your_table WITH(UPDLOCK,READPAST) WHERE id = 777

या कनेक्ट / सत्र 2: अपवाद को फेंक देगा

DECLARE @id integer;
SELECT @id = id FROM your_table WITH(UPDLOCK,READPAST) WHERE id = 777;
IF @id is NULL
  THROW 51000, 'Hi, a record is locked or does not exist.', 1;

-1

कुछ इस तरह से फ़िल्टर करने का प्रयास करें - यह जटिल हो सकता है यदि आप वास्तव में, वास्तव में विशिष्ट प्राप्त करना चाहते हैं। Sysinos_tran_locks के विवरण के लिए BOL में देखें

SELECT 
tl.request_session_id,
tl.resource_type,
tl.resource_associated_entity_id,
db_name(tl.resource_database_id) 'Database',
CASE 
    WHEN tl.resource_type = 'object' THEN object_name(tl.resource_associated_entity_id, tl.resource_database_id)
    ELSE NULL
END 'LockedObject',
tl.resource_database_id,
tl.resource_description,
tl.request_mode,
tl.request_type,
tl.request_status FROM [sys].[dm_tran_locks] tl WHERE resource_database_id <> 2order by tl.request_session_id

बस जिज्ञासु - नीचे क्यों?
रोटेनजेक

-11

आप हटाते समय NoLOCK का उपयोग कर सकते हैं और यदि पंक्तियाँ लॉक हैं, तो वे हटाए नहीं जाएंगे। यह आदर्श नहीं है, लेकिन आप के लिए चाल हो सकती है।

DELETE TA FROM dbo.TableA TA WITH (NOLOCK) WHERE Condition = True

7
अगर मैं कोशिश करता हूं कि मैं अपनी स्थानीय मशीन पर Msg 1065, Level 15, State 1, Line 15 The NOLOCK and READUNCOMMITTED lock hints are not allowed for target tables of INSERT, UPDATE, DELETE or MERGE statements., 2005 के बाद से पदावनत हो जाऊं
टॉम वी - टीम मोनिका
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.