1
2
3
4
5
6
7
8
9
10
|
BEGIN
tran
DECLARE
@
name
NVARCHAR(50)
SELECT
@
name
=
name
FROM
dbo.investor
WITH
(UPDLOCK)
WHERE
id=1206
IF @
name
=
'sxf359'
BEGIN
UPDATE
dbo.investor
SET
name
=
'sxfabc'
WHERE
id=1206
END
PRINT @
name
WAITFOR DELAY
'0:00:20'
COMMIT
TRAN
|
此事务在执行过程中,如果使用
SELECT * FROM dbo.investor WITH(NOLOCK) WHERE id=1206
读取该条数据,感觉上name字段应该读取到的是sxf359。我一直是这样认为的,因为事务还没提交,还没更新为sxfabc。但事实是读取到的是sxfabc。把事务未最终提交的数据读取出来了。一些“脏数据”或未被提交的数据潜在的可能被读取,这就是脏读。我对脏读的定义有了更清晰的认识。
若用SELECT * FROM dbo.investor WHERE id=1206 读取数据,或者SELECT * FROM dbo.investor WITH(UPDLOCK) WHERE id=1206 读取数据,这个时候都会处于等待状态,直到事务执行完毕,才会执行这个两个读取操作
但,如果是下面的事务情况:
1
2
3
4
5
6
7
|
BEGIN
tran
DECLARE
@
name
NVARCHAR(50)
SELECT
@
name
=
name
FROM
dbo.investor
WITH
(UPDLOCK)
WHERE
id=1206
PRINT @
name
WAITFOR DELAY
'0:00:20'
COMMIT
TRAN
|
下面的这两条语句同时都能够执行:
SELECT * FROM dbo.investor WITH(NOLOCK) WHERE id=1206
SELECT * FROM dbo.investor WHERE id=1206
但是,下面这条语句不能执行:
SELECT * FROM dbo.investor WITH(UPDLOCK) WHERE id=1206
这条语句只有在事务执行完毕才会执行。
updlock意思就是更新锁
防范脏读,保险的方法是使用 with(updlock) ,但通常像这种正常读取SELECT * FROM dbo.investor WHERE id=1206 就可以了。因为若使用with(updlock)情形下,下步必然是要更新数据