SQL2005中的事务与锁定(三)- 转载
------------------------------------------------------------------------
-- Author : HappyFlyStone
-- Date : 2009-10-03 15:30:00
-- Version: Microsoft SQL Server 2005 - 9.00.2047.00 (Intel X86)
-- Apr 14 2006 01:12:25
-- Copyright (c) 1988-2005 Microsoft Corporation
-- Enterprise Edition on Windows NT 5.2 (Build 3790: Service Pack 2)
-- 转载请注明出处,更多请关注:http://blog.csdn.net/happyflystone
-- 关键字:隔离等级 锁定 意外数据行为 Lock Hint
------------------------------------------------------------------------
在前面的两篇里我从纯理论上把事务相关的知识作了一个梳理,有人看了一定觉得无味了吧,好这一篇我们加入一点T-SQL语句把前面所说有东东关联起来,我们人为产生锁定来理解不同的意外数据行为在不同隔离等级下的表现,顺便再重温一下意外数据行及隔离等级,让大家对交易事务有一个直观的认识。
在进行实例前不得不先介绍一点锁的知识,注意这儿只是简单的说一下,不作深入讨论。我们根据用户访问资源的行为先归纳出几种锁,这几种锁在下面的实例里会出现,它们为:共享锁定、排它锁定、更新锁定及用意向这个限定词限定的三种锁(意向共享、意向排它、意向更新),当当然还有其它的模式,我们在下一篇再说。意向锁的存在是解决死锁的发生,保证进程在申请锁定前确定当前数据是否存在不兼容性的锁定。
先对上面提到的锁作一个简单的描述,更详细的下面再说。
共享锁定发生在查询记录时,直观就是我们select啦,但是并不是只有select才有共享锁定。一个查询记录的语句必须在没有与共享锁定互斥锁定存在或等待互斥锁定结束后,才能设置共享锁定并提取数据(互斥不互斥就是锁的兼容性,这在以后再说明)。
排它锁定发生在对数据增加、删除、修改时,事务开始以后语句申请并设置排它锁定(前提是没有其它互斥锁定存在),以明确告知其它进程对当前数据不可以查询或修改,等待事务结束后其它进程才可以查询或修改。
更新锁定是一个介于共享与排它之间的中继锁定,比如我们带where条件的update语句,在查询要更新的记录时是设置共享锁定,当要更新数据时这时锁定必须由共享锁定升级成更新锁定继而升级为排它锁定,当排它锁定设置成功才可以进行数据修改操作。显然也是要要求在锁升级的过程中没有互斥锁定的存在。简单的理解更新锁定是一个中继闸一样,把升级成排它锁定进程“序列化”,以解决死锁。最后重点说明一下,数据更新阶段是要对数据排它锁定不是更新锁定,不要被字面意思训导哦。
最后说一下在上述锁定模式下的互斥,共享锁定只与排它锁定互斥,更新锁定只与共享锁定不互斥。
在进行具体实例前我们一定要有一个工具来对我们实例过程进行监控,好,下面我写了一个过程,在需要时直接调用就行,过程如下:
Create Proc sp_us_lockinfo
---------------------------------------------------------------------
-- Author : HappyFlyStone
-- Date : 2009-10-03 15:30:00
-- BLOG : http://blog.csdn.net/happyflystone
-- 申明 :请保留作者信息,转载注明出处
--------------------------------------------------------------------
AS
BEGIN
SELECT
DB_NAME(t1.resource_database_id) AS [数据库名],
t1.resource_type AS [资源类型],
-- t1.request_type AS [请求类型],
t1.request_status AS [请求状态],
-- t1.resource_description AS [资源说明],
CASE t1.request_owner_type WHEN 'TRANSACTION' THEN '事务所有'
WHEN 'CURSOR' THEN '游标所有'
WHEN 'SESSION' THEN '用户会话所有'
WHEN 'SHARED_TRANSACTION_WORKSPACE' THEN '事务工作区的共享所有'
WHEN 'EXCLUSIVE_TRANSACTION_WORKSPACE' THEN '事务工作区的独占所有'
ELSE ''
END AS [拥有请求的实体类型],
CASE WHEN T1.resource_type = 'OBJECT'
THEN OBJECT_NAME(T1.resource_ASsociated_entity_id)
ELSE T1.resource_type+':'+ISNULL(LTRIM(T1.resource_ASsociated_entity_id),'')
END AS [锁定的对象],
t4.[name] AS [索引],
t1.request_mode AS [锁定类型],
t1.request_session_id AS [当前spid],
t2.blocking_session_id AS [锁定spid],
-- t3.snapshot_isolation_state AS [快照隔离状态],
t3.snapshot_isolation_state_desc AS [快照隔离状态描述],
t3.is_read_committed_snapshot_on AS [已提交读快照隔离]
FROM
sys.dm_tran_locks AS t1
left join
sys.dm_os_waiting_tasks AS t2
ON
t1.lock_owner_address = t2.resource_address
left join
sys.databases AS t3
ON t1.resource_database_id = t3.database_id
left join
(
SELECT rsc_text,rsc_indid,rsc_objid,b.[name]
FROM
sys.syslockinfo a
JOIN
sys.indexes b
ON a.rsc_indid = b.index_id and b.object_id = a.rsc_objid) t4
ON t1.resource_description = t4.rsc_text END
GO
/*
调用示例:exec sp_us_lockinfo
*/
exec sp_us_lockinfo
/*
最后介绍一个隔离等级设置命令:
SET TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SNAPSHOT | SERIALIZABLE}[;]
该设置的选项将一直对当前连接(数据库连接)始终有效,直到显式更改该选项为止。详情参见。
好,下面开始实例“快乐”之旅了。
五、隔离等级实例
测试数据准备:
CREATE DATABASE testcsdn; GO CREATE TABLE TA(TCID INT PRIMARY KEY,TCNAME VARCHAR(20)) INSERT TA SELECT 1,'AA' INSERT TA SELECT 2,'AA' INSERT TA SELECT 3,'AA' INSERT TA SELECT 4,'BB' INSERT TA SELECT 5,'CC' INSERT TA SELECT 6,'DD' INSERT TA SELECT 7,'DD' GO
1、 未提交读(uncommitted Read)
概念回顾:未提交读是最低等级的隔离,允许其它进程读取本进程未提交的数据行,也就是读取数据时不设置共享锁定直接读取,忽略已经存在的互斥锁定。很显然未提交读这种隔离级别不会造成丢失更新,但是其它意外行为还是可以发生的。它和select 加锁定提示NOLOCK效果相当。
测试实例:
查询一:
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 ,那么结果就是原来的值不变,这个你们自己再测试。
2、已提交读(Read Committed)
概念回顾:已提交读是SQL SERVER的缺省隔离级别,悲观模型下是用锁定,乐观模型下使用行版本控制器。这个设置可以通过SET READ_CIMMITTED_SNAPSHOT来修改。在悲观模型下对于读取来说设置共享锁定仅阻止排它锁定,并在数据读取结束自动释放,其它进程方可进行修改操作。也就是说读不会阻止其它进程设置共享及更新锁定,仅阻止排它锁定。在悲观模型下对于修改数据来说设置排锁定阻止所有锁定请示,必须等到排它锁定释放。这个级别的隔离解决了脏读的意外行为。
A、 READ_COMMITTED_SNAPSHOT为OFF的情况(缺省)
I、读数据测试
查询一:
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
B、 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
SQL2005中的事务与锁定(三)- 转载的更多相关文章
- SQL2005中的事务与锁定(七) - 转载
------------------------------------------------------------------------ -- Author : HappyFlyStone - ...
- SQL2005中的事务与锁定(一) - 转载
----------------------------------------------------------------------- -- Author : HappyFlyStone -- ...
- SQL2005中的事务与锁定(八)- 转载
------------------------------------------------------------------------ -- Author : happyflystone - ...
- SQL2005中的事务与锁定(四)- 转载
------------------------------------------------------------------------ -- Author : HappyFlyStone - ...
- SQL2005中的事务与锁定(二)- 转载
------------------------------------------------------------------------ -- Author : HappyFlyStone ...
- SQL2005中的事务与锁定(九)-(2)- 转载
-------------------------------------------------------------------------- Author : HappyFlyStone -- ...
- SQL2005中的事务与锁定(六) - 转载
------------------------------------------------------------------------ -- Author : HappyFlyStone - ...
- SQL2005中的事务与锁定(五)- 转载
------------------------------------------------------------------------ -- Author : HappyFlyStone - ...
- SQL2005中的事务与锁定(九)- 转载
------------------------------------------------------------------------ -- Author : HappyFlyStone - ...
随机推荐
- MongoDB的数据库基本操作(二)
创建数据库 >use mydb switched to db mydb 查看所有的数据表 >show collections system.indexes 创建数据表 >db.c ...
- ACM Steps 2.1.8
小数化分数2 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...
- js控制滚动条平滑滚动到制定位置
http://www.daixiaorui.com/read/92.html 滚动到顶部: $('.scroll_top').click(function(){$('html,body').anima ...
- Android中layout_gravity和gravity的区别
安卓中的 layout_gravity 属性和 gravity属性 有啥区别? LinearLayout有两个非常相似的属性: android:gravity与android:layout_gravi ...
- ant学习
如果在构建文件当中depends后面有多个依赖,而且这多个依赖还相互依赖,那么只会执行被依赖的任务,不会重复执行任务 ant学习
- 【iCore3 双核心板_FPGA】实验十七:基于I2C总线的ARM与FPGA通信实验
实验指导书及代码包下载: http://pan.baidu.com/s/1dFqddMp iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...
- MyEclipse 8.5整合Git,并在Github上发布项目【转】
最近Git火得如日中天,而且速度体验和团队模式都很不错.手头正好有个学生实训项目,时间紧任务重,而且学校内网管理太紧,所以就想借助于Internet的分布式开发,因此想到了Github. 经过一天的调 ...
- 使用 U盘 重装 Mac OSX
一.制作 U 盘系统启动盘 1.从 App Store 上下载 OS Application.(这里需要注意,取消下载完的自动更新,并存储下这个 OS.Application 文件,因为系统更新完后, ...
- 【爬虫】python之BeautifulSoup用法
1.爬虫 网络爬虫是捜索引擎抓取系统的重要组成部分.爬虫的主要目的是将互联网上的网页下载到本地形成一个或联网内容的镜像备份.通过分析和过滤HTML 代码,实现对图片.文字等资源的获取. 2.pytho ...
- 带AI的俄罗斯方块源码
好久没写俄罗斯方块的游戏了.从学习编程到现在,相继用Win32 API.MFC.C.C#.JS.iOS写过大约二十款左右的俄罗斯方块游戏.最近用Cocos2d-x写了一下,第一次完全将游戏逻辑与UI层 ...