SQL SERVER 行加锁问题
2008-03-22 23:24
232 查看
◆问题描述
想在检索一批数据的同时,加上更新锁,以禁止其他端末的更新。不是表级,页级加锁,自然而然想到了行级加锁。
但是,发现检索出来的记录以外的数据也被加上锁了。
◆问题分析
tabale
----------------------------------------------------
字段 C1(key1) C2( key2) C3 ............
c1001 c2003 c3001
c1002 c2002 c3001
c1003 c2001 c3001
索引 IX_TEST (C2,C1)
----------------------------------------------------
用户A,用户B,公用部分SQL
set lock_timeout 0
begin transaction
select * from TEST with (index=IX_TEST,rowlock,updlock)
CASE①
用户A
where C1 ='c1003'
结果-- c1003 c2001 c3001 (Locked)
用户B
where C1 ='c1003'
结果-- 已超过了锁请求超时时段。 和预想的一样
where C1 ='c1002'
结果-- 已超过了锁请求超时时段。 感觉这行也被锁住了
where C1 ='c1001'
结果-- 已超过了锁请求超时时段。 感觉这行也被锁住了
分析--CASE①的结果来看,用户A对第三条数据加锁的同时,对第一第二条数据也加上锁了
(这个不是我们预想的结果)
那我们再接着看。。。。。。。。。。。。。。。。。。。。
CASE②
用户A
where C1 ='c1003'
结果-- c1003 c2001 c3001 (Locked)
用户B
where C2 ='c2001'
结果-- 已超过了锁请求超时时段。 和预想的一样
where C2 ='c2002'
结果-- c1002 c2002 c3001 (发现没有被用户A锁住)
where C2 ='c2003'
结果-- c1001 c2003 c3001 (发现没有被用户A锁住)
分析--CASE②的结果来看,用户A只对第三条数据加了锁,其他两条没有被锁住
(这符合我们预想的结果)
结合起来分析看,CASE①和CASE①的用户B只是用了不同的检索条件检索相同的记录,
但得出的加锁状态结果却不同。这是为什么呢?继续分析。。。
1.毫无疑问,首先,SQLSERVER的行级锁和表的索引有密切的关系,他是按照索引的顺序
去检索数据,并且在相应的记录上加锁。(默认索引是表的主键顺序-升序?)
2.查了一些论坛,有的是这么解释的,说是如果where条件中没有索引字段的相应条件的话
所有记录都会被上锁,相当于变成了表级锁。从上面的例子看不这么回事,锁还是该加在哪行就是在哪行的。
只不过是在第一次给某些记录加上了锁的基础上,再一次给这个表的某些记录去加锁的时候,SQLSERVER是
根据索引怎么去加锁的呢。上面的例子可以看出,不同的where条件,SQLSERVER去遍历记录的顺序是不同。
从两个case猜测,加锁的方式是,先根据WHERE条件确定在索引中位置. 遍历记录并给记录加锁,符合WHERE
中所用条件的记录情况下,就不解锁,如果不符合的话就解锁,这就把要加锁的记录加上了锁。
回头再看CASE①
索引 IX_TEST (C2,C1)是先按字段C1,再是字段C2排序的,顺序如下
字段 C1(key1) C2( key2) C3 ............
c1001 c2003 c3001
c1002 c2002 c3001
c1003 c2001 c3001
用户B因为,用C1作为WHERE条件的C1 就无法准确的定位在索引位置,只能是从头到尾了,
这个时候它就会去遍历被用户A锁上的那条记录,因为已经锁上了,再加一次锁就会出现
【已超过了锁请求超时时段。】这个结果,貌似其他两条也被加上锁了。
CASE②的用户B因为能定位在索引中位置,所以没有再去遍历被用户A加上锁了的那条数据
所以能正确的检索出结果来。
======================================================================
总结,在操作行级别锁的时候,WHERE条件中必须要明确的确定在索引中位置的WHERE条件。
也就是说按照索引的顺序where C1 =,[C2=]。。。。
想在检索一批数据的同时,加上更新锁,以禁止其他端末的更新。不是表级,页级加锁,自然而然想到了行级加锁。
但是,发现检索出来的记录以外的数据也被加上锁了。
◆问题分析
tabale
----------------------------------------------------
字段 C1(key1) C2( key2) C3 ............
c1001 c2003 c3001
c1002 c2002 c3001
c1003 c2001 c3001
索引 IX_TEST (C2,C1)
----------------------------------------------------
用户A,用户B,公用部分SQL
set lock_timeout 0
begin transaction
select * from TEST with (index=IX_TEST,rowlock,updlock)
CASE①
用户A
where C1 ='c1003'
结果-- c1003 c2001 c3001 (Locked)
用户B
where C1 ='c1003'
结果-- 已超过了锁请求超时时段。 和预想的一样
where C1 ='c1002'
结果-- 已超过了锁请求超时时段。 感觉这行也被锁住了
where C1 ='c1001'
结果-- 已超过了锁请求超时时段。 感觉这行也被锁住了
分析--CASE①的结果来看,用户A对第三条数据加锁的同时,对第一第二条数据也加上锁了
(这个不是我们预想的结果)
那我们再接着看。。。。。。。。。。。。。。。。。。。。
CASE②
用户A
where C1 ='c1003'
结果-- c1003 c2001 c3001 (Locked)
用户B
where C2 ='c2001'
结果-- 已超过了锁请求超时时段。 和预想的一样
where C2 ='c2002'
结果-- c1002 c2002 c3001 (发现没有被用户A锁住)
where C2 ='c2003'
结果-- c1001 c2003 c3001 (发现没有被用户A锁住)
分析--CASE②的结果来看,用户A只对第三条数据加了锁,其他两条没有被锁住
(这符合我们预想的结果)
结合起来分析看,CASE①和CASE①的用户B只是用了不同的检索条件检索相同的记录,
但得出的加锁状态结果却不同。这是为什么呢?继续分析。。。
1.毫无疑问,首先,SQLSERVER的行级锁和表的索引有密切的关系,他是按照索引的顺序
去检索数据,并且在相应的记录上加锁。(默认索引是表的主键顺序-升序?)
2.查了一些论坛,有的是这么解释的,说是如果where条件中没有索引字段的相应条件的话
所有记录都会被上锁,相当于变成了表级锁。从上面的例子看不这么回事,锁还是该加在哪行就是在哪行的。
只不过是在第一次给某些记录加上了锁的基础上,再一次给这个表的某些记录去加锁的时候,SQLSERVER是
根据索引怎么去加锁的呢。上面的例子可以看出,不同的where条件,SQLSERVER去遍历记录的顺序是不同。
从两个case猜测,加锁的方式是,先根据WHERE条件确定在索引中位置. 遍历记录并给记录加锁,符合WHERE
中所用条件的记录情况下,就不解锁,如果不符合的话就解锁,这就把要加锁的记录加上了锁。
回头再看CASE①
索引 IX_TEST (C2,C1)是先按字段C1,再是字段C2排序的,顺序如下
字段 C1(key1) C2( key2) C3 ............
c1001 c2003 c3001
c1002 c2002 c3001
c1003 c2001 c3001
用户B因为,用C1作为WHERE条件的C1 就无法准确的定位在索引位置,只能是从头到尾了,
这个时候它就会去遍历被用户A锁上的那条记录,因为已经锁上了,再加一次锁就会出现
【已超过了锁请求超时时段。】这个结果,貌似其他两条也被加上锁了。
CASE②的用户B因为能定位在索引中位置,所以没有再去遍历被用户A加上锁了的那条数据
所以能正确的检索出结果来。
======================================================================
总结,在操作行级别锁的时候,WHERE条件中必须要明确的确定在索引中位置的WHERE条件。
也就是说按照索引的顺序where C1 =,[C2=]。。。。
相关文章推荐
- SQL Server 语句操纵数据库
- linux快速部署mysql服务器
- sql 存储过程分页
- 在WINXP系统上安装SQL Server企业版的方法
- SQL Server 存储过程的分页
- SQL SERVER编写存储过程小工具
- SQL Server 2000 注入防护大全(二)
- SQL Server 2000 注入防护大全(一)
- PJBlog存在SQL注入漏洞大家要快下补丁了
- Access to SQLserver 数据库生迁脚本编写器(DB_CreateSqlEV1.06下载)
- SQL 新增/修改 表字段列的类型等
- sql server中千万数量级分页存储过程代码
- SQL SERVER的优化建议与方法
- 五种提高 SQL 性能的方法
- SQL SERVER 与ACCESS、EXCEL的数据转换
- SQL Server SQL Agent服务使用教程小结
- ms SQL server数据库备份、压缩与SQL数据库数据处理的方法
- 如何在 SQL SERVER 中快速有条件删除海量数据
- Access 数据类型与 MS SQL 数据类型的相应
- sql server中datetime字段去除时间的语句