好的陈述情景。我决定测试它。
这是我的安装脚本:
CREATE TABLE Deposits(Amount Money, UserID int)
INSERT INTO Deposits (Amount, UserID)
SELECT 0.0, 123
--Reset
UPDATE Deposits
SET Amount = 0.00
WHERE UserID = 123
这里是我的测试脚本。
SET TRANSACTION ISOLATION LEVEL Serializable
----------------------------------------
-- Part 1
----------------------------------------
BEGIN TRANSACTION
DECLARE @amount MONEY
SET @amount =
(
SELECT Amount
FROM Deposits
WHERE UserId = 123
)
SELECT @amount as Amount
----------------------------------------
-- Part 2
----------------------------------------
DECLARE @amount MONEY
SET @amount = *value from step 1*
UPDATE Deposits
SET Amount = @amount + 100.0
WHERE UserId = 123
COMMIT
SELECT *
FROM Deposits
WHERE UserID = 123
我在两个查询分析器窗口中加载了这个测试脚本,并按问题所述运行了每个部分。
所有的阅读发生在任何写入之前,所以所有的线程/场景都会将0的值读入@amount。
下面是结果:
读取已提交
1 [email protected] = 0.00
2 [email protected] = 0.00
3 Deposits.Amount = 100.00
4 Deposits.Amount = 100.00
读未提交
1 [email protected] = 0.00
2 [email protected] = 0.00
3 Deposits.Amount = 100.00
4 Deposits.Amount = 100.00
重复读
1 [email protected] = 0.00 (locks out changes by others on Deposit.UserID = 123)
2 [email protected] = 0.00 (locks out changes by others on Deposit.UserID = 123)
3 Hangs until step 4. (due to lock in step 2)
4 Deadlock!
Final result: Deposits.Amount = 100.00
序列化
1 [email protected] = 0.00 (locks out changes by others on Deposit)
2 [email protected] = 0.00 (locks out changes by others on Deposit)
3 Hangs until step 4. (due to lock in step 2)
4 Deadlock!
Final result: Deposits.Amount = 100.00
下面是可用于通过思想模拟来达到这些结果的每种类型的解释。
提交读和阅读UNCOMMITED,既不要锁被读取对其他用户修改数据。不同之处在于,未提交的读取将允许您查看尚未提交的数据(下侧),并且如果有其他数据被读取锁定(上行),这实际上是两次说同样的事情,则不会阻止读取。
可重复读取和可序列化的,都表现得像阅读承诺阅读。对于锁定,锁定已被读取的数据以防其他用户修改。不同之处在于,可序列化的块比已读取的行更多,它也会阻止会引入之前不存在的记录的插入。
因此,通过重复读取,您可以在稍后的读取中看到新记录(称为:幻像记录)。在可序列化的情况下,您会阻止创建这些记录直到您提交。
以上解释来自我对msdn文章的解释。
您的声明是反向的。 – 2008-11-03 15:47:24
哈哈,科格斯将它同时编辑。 – 2008-11-03 18:27:54