आंशिक रूप से अपडेट की गई पंक्ति पढ़ें?


15

मान लें कि मेरे दो प्रश्न हैं, SSMS में दो अलग-अलग सत्रों में चल रहे हैं:

प्रथम सत्र:

UPDATE Person
SET Name='Jonny', Surname='Cage'
WHERE Id=42

दूसरा सत्र:

SELECT Name, Surname
FROM Person WITH(NOLOCK)
WHERE Id > 30

क्या यह संभव है कि SELECTबयान आधा अद्यतन पंक्ति पढ़ सकता है, उदाहरण के लिए Name = 'Jonny'और साथ में Surname = 'Goody'?

क्वेरीज़ को अलग-अलग सत्रों में लगभग एक साथ निष्पादित किया जाता है।

जवाबों:


22

हाँ, SQL सर्वर कुछ परिस्थितियों में पंक्ति के "पुराने" संस्करण से एक कॉलम का मूल्य पढ़ सकता है, और पंक्ति के "नए" संस्करण से दूसरे कॉलम का मान।

सेट अप:

CREATE TABLE Person
  (
     Id      INT PRIMARY KEY,
     Name    VARCHAR(100),
     Surname VARCHAR(100)
  );

CREATE INDEX ix_Name
  ON Person(Name);

CREATE INDEX ix_Surname
  ON Person(Surname);

INSERT INTO Person
SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY @@SPID),
                   'Jonny1',
                   'Jonny1'
FROM   master..spt_values v1,
       master..spt_values v2 

पहले कनेक्शन में, इसे चलाएं:

WHILE ( 1 = 1 )
  BEGIN
      UPDATE Person
      SET    Name = 'Jonny2',
             Surname = 'Jonny2'

      UPDATE Person
      SET    Name = 'Jonny1',
             Surname = 'Jonny1'
  END 

दूसरे कनेक्शन में, इसे चलाएं:

DECLARE @Person TABLE (
  Id      INT PRIMARY KEY,
  Name    VARCHAR(100),
  Surname VARCHAR(100));

SELECT 'Setting intial Rowcount'
WHERE  1 = 0

WHILE @@ROWCOUNT = 0
  INSERT INTO @Person
  SELECT Id,
         Name,
         Surname
  FROM   Person WITH(NOLOCK, INDEX = ix_Name, INDEX = ix_Surname)
  WHERE  Id > 30
         AND Name <> Surname

SELECT *
FROM   @Person 

लगभग 30 सेकंड के लिए दौड़ने के बाद मुझे:

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

SELECTक्वेरी (संकेत की वजह से हालांकि) संकुल अनुक्रमणिका के बजाय गैर क्लस्टर अनुक्रमित से स्तंभ को पुन: प्राप्त कर रहा है।

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

अपडेट स्टेटमेंट को एक विस्तृत अपडेट योजना मिलती है ...

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

... और अनुक्रमों को अनुक्रम में अपडेट करता है इसलिए "एक सूचकांक से मूल्यों" से पहले और दूसरे से "बाद" पढ़ना संभव है।

एक ही स्तंभ मान के दो अलग-अलग संस्करणों को पुनर्प्राप्त करना भी संभव है।

पहले कनेक्शन में, इसे चलाएं:

DECLARE @A VARCHAR(MAX) = 'A';
DECLARE @B VARCHAR(MAX) = 'B';

SELECT @A = REPLICATE(@A, 200000),
       @B = REPLICATE(@B, 200000);

CREATE TABLE T
  (
     V VARCHAR(MAX) NULL
  );

INSERT INTO T
VALUES     (@B);

WHILE 1 = 1
  BEGIN
      UPDATE T
      SET    V = @A;

      UPDATE T
      SET    V = @B;
  END   

और फिर दूसरे में, इसे चलाएं:

SELECT 'Setting intial Rowcount'
WHERE  1 = 0;

WHILE @@ROWCOUNT = 0
  SELECT LEFT(V, 10)  AS Left10,
         RIGHT(V, 10) AS Right10
  FROM   T WITH (NOLOCK)
  WHERE  LEFT(V, 10) <> RIGHT(V, 10);

DROP TABLE T;

सीधे, यह मेरे लिए निम्नलिखित परिणाम लौटा

+------------+------------+
|   Left10   |  Right10   |
+------------+------------+
| BBBBBBBBBB | AAAAAAAAAA |
+------------+------------+

1
क्या मैं सही हूं कि अगर मेरे पास एक टेबल है तोटेबल पर्सन (Id INT PRIMARY KEY, नाम VARCHAR (100), उपनाम VARCHAR (100)) (नाम और उपनाम पर कोई अनुक्रमणिका के बिना) और दो प्रश्न की तरह, जिन्हें निष्पादित किया जाता है अलग-अलग सत्रों में, फिर मुझे एक अद्यतन पंक्ति या एक पुरानी पंक्ति मिलेगी, लेकिन पंक्ति को अद्यतन करने के कुछ मध्यवर्ती परिणाम नहीं?
तेश

@ हाँ, मुझे नहीं लगता कि किसी अन्य परिणाम को प्राप्त करना संभव होगा क्योंकि यह सभी एक ही पृष्ठ पर होगा और लेखन के दौरान एक कुंडी द्वारा संरक्षित होगा।
मार्टिन स्मिथ

कुछ भी अप्रत्याशित आपको WITH (NLOCK)संकेत के साथ मिलता है आपकी अपनी गलती है। क्या यह NOLOCKसंकेत के बिना हो सकता है ?
रोस प्रेसर

2
@RossPresser - पहले उदाहरण के लिए हां, यहां इंडेक्स चौराहे का टुकड़ा देखें blogs.msdn.com/b/craigfr/archive/2007/05/02/… । दूसरे के लिए मैं संभावित रूप से यह अनुमान लगा सकता हूं कि क्या दो अलग-अलग प्रतिबद्ध संस्करण उपलब्ध थे। यकीन नहीं है कि यह व्यवहार में इंजीनियर के लिए संभव होगा।
मार्टिन स्मिथ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.