这是一个如何通过查看
MyCleanTable
构建“脏读”的示例
Id | Value
----------
1 | I am clean!
2 | I am clean!
使用未提交的隔离级别执行简单查询transaction_a
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRAN
SELECT * FROM [MyCleanTable]
输出:
Id | Value
----------
1 | I am clean!
2 | I am clean!
使用 transaction_b 用脏值更新表:
BEGIN TRAN
UPDATE [ConcurrencyDemo].[dbo].[MyCleanTable]
SET [Value] = 'I am dirty'
WHERE [Id] = 1
在 transaction_a 中执行另一个查询并提交它:
SELECT * FROM [ConcurrencyDemo].[dbo].[MyCleanTable]
COMMIT;
输出:
Id | Value
----------
1 | I am dirty! ------> "dirty read"
2 | I am clean!
回滚transaction_b的更新:
ROLLBACK;
在此阶段,表已回滚到其原始值:
Id | Value
----------
1 | I am clean!
2 | I am clean!
但是第 3 部分的查询读取到了脏值。
这不是脏读。其作用的详细信息如下:隐式交易
要获得脏读,您需要将 select column1 from dbo.table1 WITH (NOLOCK)。 With (NOLOCK) 读取未提交的数据,如果事务以某种方式回滚,这些数据可能会消失并且永远不会真正存在。
获取脏读的另一种方法是使用:隔离级别读未提交。
我用 MSSQL(SQL Server) 和 2 个命令提示符进行了脏读实验。
首先,我设置
READ UNCOMMITTED
隔离级别发生脏读:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
然后,我用
person
和 id
创建了 name
表,如下所示。
person
表:id | 名字 |
---|---|
1 | 约翰 |
2 | 大卫 |
现在,我使用 MSSQL 查询执行了以下步骤:
流量 | 交易1(T1) | 交易2(T2) | 说明 |
---|---|---|---|
步骤1 |
|
T1开始。 | |
第2步 |
|
T2开始。 | |
第3步 |
2大卫 |
T1 读取为 。 |
|
第4步 |
|
T2 将 更新为 。 |
|
第5步 |
2 汤姆 |
T1 在 T2 提交之前读取 而不是 。*发生脏读!! |
|
第6步 |
|
T2 提交。 | |
第7步 |
|
T1 提交。 |