/********** 加锁 ***************设table1(A,B,C)A B Ca1 b1 c1a2 b2 c2a3 b3 c3
1)排它锁新建两个连接在第一个连接中执行以下语句begin tran update table1 set A='aa' where B='b2' waitfor delay '00:00:30' --等待30秒commit tran在第二个连接中执行以下语句begin tran select * from table1 where B='b2'commit tran若同时执行上述两个语句,则select查询必须等待update执行完毕才能执行即要等待30秒
2)共享锁在第一个连接中执行以下语句begin tran select * from table1 holdlock -holdlock人为加锁 where B='b2' waitfor delay '00:00:30' --等待30秒commit tran在第二个连接中执行以下语句begin tran select A,C from table1 where B='b2' update table1 set A='aa' where B='b2'commit tran若同时执行上述两个语句,则第二个连接中的select查询可以执行而update必须等待第一个连接中的共享锁结束后才能执行 即要等待30秒
3)死锁增设table2(D,E)D Ed1 e1d2 e2在第一个连接中执行以下语句begin tran update table1 set A='aa' where B='b2' waitfor delay '00:00:30' update table2 set D='d5' where E='e1'commit tran在第二个连接中执行以下语句begin tran update table2 set D='d5' where E='e1' waitfor delay '00:00:10' update table1 set A='aa' where B='b2'commit tran同时执行,系统会检测出死锁,并中止进程--------------------------------------------------------------SET IMPLICIT_TRANSACTIONS ON --用户每次必须显式提交或回滚。否则当用户断开连接时, --事务及其所包含的所有数据更改将回滚SET IMPLICIT_TRANSACTIONS OFF --自动提交模式。在自动提交模式下,如果各个语句成功 --完成则提交。
1:如上2: 如何锁一个表的某一行A 连接中执行SET TRANSACTION ISOLATION LEVEL REPEATABLE READbegin transelect * from tablename with (rowlock) where id=3waitfor delay '00:00:05'commit tranB连接中如果执行update tablename set colname='10' where id=3 --则要等待5秒update tablename set colname='10' where id<>3 --可立即执行
2 锁定数据库的一个表SELECT * FROM table WITH (HOLDLOCK)注意: 锁定数据库的一个表的区别SELECT * FROM table WITH (HOLDLOCK)其他事务可以读取表,但不能更新删除SELECT * FROM table WITH (TABLOCKX)其他事务不能读取表,更新和删除SELECT 语句中“加锁选项”的功能说明 SQL Server提供了强大而完备的锁机制来帮助实现数据库系统的并发性和高性能。用户既能使用SQL Server的缺省设置也可以在select 语句中使用“加锁选项”来实现预期的效果。 本文介绍了SELECT语句中的各项“加锁选项”以及相应的功能说明。 功能说明: NOLOCK(不加锁) 此选项被选中时,SQL Server 在读取或修改数据时不加任何锁。 在这种情况下,用户有可能读取到未完成事务(Uncommited Transaction)或回滚(Roll Back)中的数据, 即所谓的“脏数据”。 HOLDLOCK(保持锁) 此选项被选中时,SQL Server 会将此共享锁保持至整个事务结束,而不会在途中释放。 UPDLOCK(修改锁) 此选项被选中时,SQL Server 在读取数据时使用修改锁来代替共享锁,并将此锁保持至整个事务或命令结束。使用此选项能够保证多个进程能同时读取数据但只有该进程能修改数据。 TABLOCK(表锁) 此选项被选中时,SQL Server 将在整个表上置共享锁直至该命令结束。 这个选项保证其他进程只能读取而不能修改数据。 PAGLOCK(页锁) 此选项为默认选项, 当被选中时,SQL Server 使用共享页锁。 TABLOCKX(排它表锁) 此选项被选中时,SQL Server 将在整个表上置排它锁直至该命令或事务结束。这将防止其他进程读取或修改表中的数据。
--或者自己加锁(控制更灵活)--锁定记录,只允许单用户修改的例子:--创建测试环境--创建测试表--部门表create table 部门(departmentid int,name varchar(10))--记录锁定表create table lock(departmentid int,dt datetime)go--因为函数中不可以用getdate,所以用个视图,得到当前时间create view v_getdate as select dt=getdate()go--创建自定义函数,判断记录是否锁定create function f_chk(@departmentid int)returns bitasbegindeclare @re bit,@dt datetimeselect @dt=dt from v_getdateif exists(select 1 from lock where departmentid=@departmentidand datediff(ss,dt,@dt)<5)set @re=1elseset @re=0return(@re)endgo--数据处理测试if dbo.f_chk(3)=1print '记录被锁定'elsebegin--也可以是查询begin traninsert into lock values(3,getdate())update 部门 set name='A' where departmentid=3delete from lock where departmentid=3commit tranend--删除测试环境drop table 部门drop view v_getdatedrop function f_chk
如果是死锁可以查一下: 1:sp_who 或 sp_who2 2: Select * from sysprocesses where blocked 0 3: 企业管理器->服务器->管理工具->活动->当前活动 然后把他kill掉。。。 进程信息中,如果发现旁边有一个锁状的图标,就表明这个进程是死锁,kill掉 4:SQL事件探查器,监控一下,看主要是那些处理引起的死锁.然后做相应的处理. 用事件探查器new一个trace,监视一下造成你sqlserver停顿的情况。。。 最好的办法还是检查一下引起锁的原因,一般是由你的代码引起的。