/********** 加锁 ***************
设table1(A,B,C)
A B C
a1 b1 c1
a2 b2 c2
a3 b3 c31)排它锁
新建两个连接
在第一个连接中执行以下语句
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 E
d1 e1
d2 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 --自动提交模式。在自动提交模式下,如果各个语句成功
--完成则提交。
设table1(A,B,C)
A B C
a1 b1 c1
a2 b2 c2
a3 b3 c31)排它锁
新建两个连接
在第一个连接中执行以下语句
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 E
d1 e1
d2 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 --自动提交模式。在自动提交模式下,如果各个语句成功
--完成则提交。
update t1 with(rowlock) set b=b+1 where a=45
这一句,其实根本不是行级锁。是不是这个问题真的解决不了?
如果是这样,我只能绕道而行了。
我怎么能让
begin tran(事务一)
update t1 with(rowlock) set b=b+1 where a=45
commit tran
和
begin tran(事务二)
update t1 with(rowlock) set b=b+1 where a=23
commit tran
各自处理自己的事情,不相互影响。
我想我已经说得很明白了吧。
万事具备,只欠高手。
自定义索引的锁定
在大多数情况下,Microsoft® SQL Server™ 2000 动态锁定策略自动选择查询的最佳锁定粒度。在访问模式很好理解且一致的情况下,限制索引可用的锁定级别是很有益的。例如,数据库应用程序使用的查找表在批处理进程中每周进行刷新。最有效的锁定策略是关闭页和行锁定,并允许所有并发读取器获得表上的共享 (S) 锁以减少开销。在每周的批处理更新时,更新进程可以使用排它 (X) 锁,然后更新整个表。可以使用 sp_indexoption 系统存储过程来设置用于索引的锁定粒度。若要显示给定索引的当前锁定选项,请使用 INDEXPROPERTY 函数。可以禁止将页级锁、行级锁或二者的组合用于指定的索引。禁止的锁 访问索引的锁
页级 行级锁和表级锁
行级 页级锁和表级锁
页级和行级 表级锁
例如,当已知表是争夺点时,禁止页级锁从而只允许行级锁会有好处。或者如果总是使用表扫描来访问索引或表,那么通过只允许表级锁而禁止页级锁和行级锁将会很有帮助。
重要 SQL Server 查询优化器自动作出正确的决定。建议您不要替代优化器作出的选择。禁止锁定级别反过来会影响表或索引的并发。例如,在由许多用户频繁访问的大型表上只指定表级锁会严重影响性能。用户在访问表之前必须等待释放表级锁。
之所以,楼主认为SQL server 2000的锁定策略与你说的不符,很有可能是因为:
你的表中没有合适的主键。当一个表没有主键时,数据库就把整行做为主键。
你用update t1 with(rowlock) set b=b+1 where a=45这样的话,试图来锁定
a b
----------- -----------
45 49
这条记录,其实是不可能的,数据库认为,其它行也可以存在a=45这样的情况,
所以,他就锁定了整个表。其实,SQL Server 2000 自动选择的锁定粒度是对的,
只是与你想的不一样而矣。
解决办法有两个。
1.把Where a=45改为where a=45 and b=49
2.把A做为表的主键。(个人以为,这种方法更好一些)
当然,你上面的Rowlock改过UPDLock可能更好些(因为,粒度是自动选择的,所以,
我个人以为,可能就不用写RowLock了)
楼主遇到的情况不知道是不是这样的,反正我以前被这个问题困扰时,就是这样解决的。
估计差不多。
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)
其他事务不能读取表,更新和删除