Tes*_*esh 16 sql-server concurrency
假设我有两个查询,在 SSMS 中的两个单独会话中运行:
第一节:
UPDATE Person
SET Name='Jonny', Surname='Cage'
WHERE Id=42
Run Code Online (Sandbox Code Playgroud)
第二场:
SELECT Name, Surname
FROM Person WITH(NOLOCK)
WHERE Id > 30
Run Code Online (Sandbox Code Playgroud)
SELECT语句是否有可能读取半更新的行,例如带有Name = 'Jonny'和的行Surname = 'Goody'?
查询几乎在不同的会话中同时执行。
Mar*_*ith 22
是的,在某些情况下,SQL Server 可以从行的“旧”版本中读取一列的值,从行的“新”版本中读取另一列的值。
设置:
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
Run Code Online (Sandbox Code Playgroud)
在第一个连接中,运行:
WHILE ( 1 = 1 )
BEGIN
UPDATE Person
SET Name = 'Jonny2',
Surname = 'Jonny2'
UPDATE Person
SET Name = 'Jonny1',
Surname = 'Jonny1'
END
Run Code Online (Sandbox Code Playgroud)
在第二个连接中,运行:
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
Run Code Online (Sandbox Code Playgroud)
运行约 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
Run Code Online (Sandbox Code Playgroud)
然后在第二个,运行这个:
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;
Run Code Online (Sandbox Code Playgroud)
马上,这为我返回了以下结果
+------------+------------+
| Left10 | Right10 |
+------------+------------+
| BBBBBBBBBB | AAAAAAAAAA |
+------------+------------+
Run Code Online (Sandbox Code Playgroud)