SQL事务与锁定学习笔记(一)
查询一:
SELECT * FROM TA WHERE TCID = 1
BEGIN TRAN
UPDATE TA
SET TCNAME = 'TA'
WHERE TCID = 1
--COMMIT TRAN --Don't commit
SELECT * FROM TA WHERE TCID = 1
SELECT @@SPID
/*
tcid Tcname
----------- --------------------
1 AA
(1 行受影响)
(1 行受影响)
tcid Tcname
----------- --------------------
1 TA
(1 行受影响)
SPID
------
54
(1 行受影响)
*/
查询二:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM TA WHERE TCID = 1
/*
tcid Tcname
----------- --------------------
1 TA
(1 行受影响)
*/
--显然未提交读模式我们读到SPID=54未提交的数据。
查询三:
SELECT * FROM TA WHERE TCID = 1
--查询一直进行中…… 无结果
--因为缺省下已提交读级别,所以修改数据设置了排它锁定必须等到SPID=54的事务结束
查询四:
--查看当前的锁定信息
exec sp_us_lockinfo
/*
*/
这个时候如果我们回头到查询一里执行commit tran ,你会发现查询三会得到结果,并且是查询一修改后的结果,如果你改用rollback ,那么结果就是原来的值不变,这个你们自己再测试。
设置已提交读隔离使用行版本控制
悲观并发下的已提交读,当进程要修改数据时会在数据行上申请排它锁,其它进程(无论是读还是写)必须等到排它锁释放才可以使用这些数据。如果进程仅是读取数据时会使用共享锁,其它进程虽然可以读取数据但是无法更新数据
查询一:
BEGIN TRAN
--用锁定提示模拟共享锁定,并强制共享锁定持续到事务结束
SELECT * FROM TA with(holdlock) WHERE TCID = 1
--COMMIT TRAN --Don't commit
SELECT @@SPID
/*
tcid Tcname
----------- --------------------
1 CA
(1 行受影响)
------
54
(1 行受影响)
*/
查询二:悲观模型下已提交读级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
UPDATE TA
SET TCNAME = 'TA'
WHERE TCID = 1
--查询一直没有结果,显然我们验证了共享锁定阻止了排它锁定。
查询三:
exec sp_us_lockinfo
--结果大家自己运行看结果。
II、修改数据测试
查询一:
SELECT * FROM TA WHERE TCID = 1
BEGIN TRAN
UPDATE TA
SET TCNAME = 'READ COMMITTED LOCK'
WHERE TCID = 1
--COMMIT TRAN --Don't commit
SELECT @@SPID
/*
tcid Tcname
----------- --------------------
1 TA
(1 行受影响)
------
54
(1 行受影响)
*/
查询二:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
SELECT * FROM TA WHERE TCID = 1
/*
--查询一直进行中……被锁定无结果
--修改数据设置了排它锁定必须等到SPID=54的事务结束
*/
查询三:
exec sp_us_lockinfo
/*
*/
A、 READ_COMMITTED_SNAPSHOT为ON的情况
先修改当前当前库的READ_COMMITTED_SNAPSHOT为ON
ALTER DATABASE TESTCSDN
SET READ_COMMITTED_SNAPSHOT ON
GO
查询一:
SELECT * FROM TA WHERE TCID = 1
BEGIN TRAN
UPDATE TA
SET TCNAME = 'READ COMMITTED SNAP'
WHERE TCID = 1
--COMMIT TRAN --Don't commit
SELECT @@SPID
/*
TCID TCNAME
----------- --------------------
1 AA
(1 行受影响)
(1 行受影响)
------
56
(1 行受影响)
*/
查询二:因为启用行版本控制器来锁定数据,保证其它进程读取到虽然被排它锁定但在事务开始前已经提交的保证一致性的数据。
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
SELECT * FROM TA WHERE TCID = 1
/*
TCID TCNAME
----------- --------------------
1 AA
(1 行受影响)
*/
查询三:
exec sp_us_lockinfo
附录:隔离等级与意外数据行为
意外行为 隔离等级 | 丢失更新 | 脏读 | 不可 重复读 | 幻影 | 并发模型 |
未提交读 | 否 | 是 | 是 | 是 | 悲观 |
已提交读(锁 定) | 否 | 否 | 是 | 是 | 悲观 |
已提交读(行版本) | 否 | 否 | 是 | 是 | 乐观 |
可重复读 | 否 | 否 | 否 | 是 | 悲观 |
快照 | 否 | 否 | 否 | 否 | 乐观 |
可串行化 | 否 | 否 | 否 | 否 | 悲观 |