আংশিক আপডেট হওয়া সারিটি পড়ুন?


15

ধরা যাক আমার দুটি প্রশ্ন রয়েছে, এসএসএমএসে দুটি পৃথক সেশনে চলছে:

প্রথম অধিবেশন:

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

হ্যাঁ, এসকিউএল সার্ভার, কিছু পরিস্থিতিতে সারিটির "পুরাতন" সংস্করণ থেকে একটি কলামের মান এবং সারিটির "নতুন" সংস্করণ থেকে অন্য কলামের মান পড়তে পারে।

সেটআপ:

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 সেকেন্ড চালানোর পরে আমি পেয়েছি:

এখানে চিত্র বর্ণনা লিখুন

SELECTQUERY (নির্দেশ কারণে যদিও) ক্লাস্টার সূচক বদলে অ ক্লাস্টার ইনডেক্স থেকে কলাম পুনরুদ্ধার করছে।

এখানে চিত্র বর্ণনা লিখুন

আপডেট বিবৃতিটি একটি বিস্তৃত আপডেট পরিকল্পনা পেয়েছে ...

এখানে চিত্র বর্ণনা লিখুন

... এবং সূচকে ধারাবাহিকভাবে আপডেট করে যাতে এক সূচক থেকে "পূর্বে" মানগুলি এবং অন্যের "পরে" পড়া সম্ভব হয়।

একই কলাম মানটির দুটি পৃথক সংস্করণ পুনরুদ্ধার করাও সম্ভব।

প্রথম সংযোগে, এটি চালান:

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
আমি কি ঠিক বলেছি যদি আমার কাছে একটি টেবিল তৈরি হয় তবে টেবিল ব্যক্তি তৈরি করুন (আইডি আইএনটি প্রাইমারি কী, নাম ভর্চার (১০০), উপাধি আলোচনার (১০০)) (নাম এবং উপাধিতে কোনও সূচক ছাড়াই) এবং প্রশ্নে দুটি প্রশ্ন রয়েছে যা কার্যকর করা হয় পৃথক সেশনে, তারপরে আমি একটি আপডেট সারি বা একটি পুরানো সারি পাব, তবে সারিটি আপডেট করার কোনও মধ্যবর্তী ফলাফল নয়?
তেশ

@ তাশ হ্যাঁ আমি মনে করি না যে অন্য কোনও ফলাফল পাওয়া সম্ভব হবে কারণ সেগুলি একই পৃষ্ঠায় থাকবে এবং লেখার সময় একটি ল্যাচ দ্বারা সুরক্ষিত থাকবে।
মার্টিন স্মিথ

WITH (NLOCK)ইঙ্গিত দিয়ে আপনি যেই কিছু অপ্রত্যাশিত হন তা আপনার নিজের দোষ fault NOLOCKইঙ্গিত ছাড়া কি এটি ঘটতে পারে ?
রস প্রেসার

2
@ রসপ্রেসার - হ্যাঁ প্রথম উদাহরণ হিসাবে, সূচক ছেদটি এখানে দেখুন ব্লগস.এমএসএনএন / বি / ক্রাইগ্রফার / অর্চিভ / ২০০7/০5/২০১২ । দ্বিতীয়টির জন্য আমি অনুমান করি যে এটি দুটি পৃথক প্রতিশ্রুতিবদ্ধ সংস্করণ উপলব্ধ থাকলে could অনুশীলনে প্রকৌশলী করা সম্ভব হবে তা নিশ্চিত নয়।
মার্টিন স্মিথ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.