SQL SERVER 行加锁问题
来源:互联网 发布:农村淘宝开票信息 编辑:程序博客网 时间:2024/04/20 04:45
◆问题描述
想在检索一批数据的同时,加上更新锁,以禁止其他端末的更新。不是表级,页级加锁,自然而然想到了行级加锁。
但是,发现检索出来的记录以外的数据也被加上锁了。
分析--CASE①的结果来看,用户A对第三条数据加锁的同时,对第一第二条数据也加上锁了
(这个不是我们预想的结果)
那我们再接着看。。。。。。。。。。。。。。。。。。。。
CASE②
用户A
where C1 ='c1003'
结果-- c1003 c2001 c3001 (Locked)
想在检索一批数据的同时,加上更新锁,以禁止其他端末的更新。不是表级,页级加锁,自然而然想到了行级加锁。
但是,发现检索出来的记录以外的数据也被加上锁了。
◆问题分析
tabale
----------------------------------------------------
tabale
----------------------------------------------------
字段 C1(key1) C2( key2) C3 ............
c1001 c2003 c3001
c1002 c2002 c3001
c1003 c2001 c3001
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)
set lock_timeout 0
begin transaction
select * from TEST with (index=IX_TEST,rowlock,updlock)
CASE①
用户A
where C1 ='c1003'
结果-- c1003 c2001 c3001 (Locked)
用户A
where C1 ='c1003'
结果-- c1003 c2001 c3001 (Locked)
用户B
where C1 ='c1003'
结果-- 已超过了锁请求超时时段。 和预想的一样
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 ='c2001'
结果-- 已超过了锁请求超时时段。 和预想的一样
where C2 ='c2002'
结果-- c1002 c2002 c3001 (发现没有被用户A锁住)
结果-- c1002 c2002 c3001 (发现没有被用户A锁住)
where C2 ='c2003'
结果-- c1001 c2003 c3001 (发现没有被用户A锁住)
结果-- c1001 c2003 c3001 (发现没有被用户A锁住)
分析--CASE②的结果来看,用户A只对第三条数据加了锁,其他两条没有被锁住
(这符合我们预想的结果)
结合起来分析看,CASE①和CASE①的用户B只是用了不同的检索条件检索相同的记录,
但得出的加锁状态结果却不同。这是为什么呢?继续分析。。。
1.毫无疑问,首先,SQLSERVER的行级锁和表的索引有密切的关系,他是按照索引的顺序
去检索数据,并且在相应的记录上加锁。(默认索引是表的主键顺序-升序?)
2.查了一些论坛,有的是这么解释的,说是如果where条件中没有索引字段的相应条件的话
所有记录都会被上锁,相当于变成了表级锁。从上面的例子看不这么回事,锁还是该加在哪行就是在哪行的。
只不过是在第一次给某些记录加上了锁的基础上,再一次给这个表的某些记录去加锁的时候,SQLSERVER是
根据索引怎么去加锁的呢。上面的例子可以看出,不同的where条件,SQLSERVER去遍历记录的顺序是不同。
从两个case猜测,加锁的方式是,先根据WHERE条件确定在索引中位置. 遍历记录并给记录加锁,符合WHERE
中所用条件的记录情况下,就不解锁,如果不符合的话就解锁,这就把要加锁的记录加上了锁。
(这符合我们预想的结果)
结合起来分析看,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
字段 C1(key1) C2( key2) C3 ............
c1001 c2003 c3001
c1002 c2002 c3001
c1003 c2001 c3001
用户B因为,用C1作为WHERE条件的C1 就无法准确的定位在索引位置,只能是从头到尾了,
这个时候它就会去遍历被用户A锁上的那条记录,因为已经锁上了,再加一次锁就会出现
【已超过了锁请求超时时段。】这个结果,貌似其他两条也被加上锁了。
这个时候它就会去遍历被用户A锁上的那条记录,因为已经锁上了,再加一次锁就会出现
【已超过了锁请求超时时段。】这个结果,貌似其他两条也被加上锁了。
CASE②的用户B因为能定位在索引中位置,所以没有再去遍历被用户A加上锁了的那条数据
所以能正确的检索出结果来。
所以能正确的检索出结果来。
======================================================================
总结,在操作行级别锁的时候,WHERE条件中必须要明确的确定在索引中位置的WHERE条件。
也就是说按照索引的顺序where C1 =,[C2=]。。。。
也就是说按照索引的顺序where C1 =,[C2=]。。。。
- SQL SERVER 行加锁问题
- SQL SERVER 行加锁问题
- SQL server数据库并发控制--加锁
- sql 加锁
- 关于sql server表加锁访问的一些经验
- SQL Server中游标加锁技术应用:获取唯一编号
- SQL Server中“加锁选项”的功能说明
- SQL SERVER SELECT语句中加锁选项的详细说明
- SQL加锁语句
- 文件加锁问题
- 数据库加锁问题
- 分布式应用加锁问题
- 多线程 变量 加锁问题
- SQL Server数据库删除行问题
- Sql Server问题摘要
- SQL Server 问题
- SQL server安装问题
- sql server连接问题
- 一份详尽的IPC$入侵资料
- 控件必须放在具有 runat=server 的窗体标记内
- 掉了手中 烟
- Java Path setting & compile java files
- 有关数据库书籍
- SQL SERVER 行加锁问题
- 一种全局变量的定义方式m_Data
- watir学习之旅(一):从Hello,world开始
- 跟我一起做 asp.net最简单的留言本
- 网络管理员-第一章
- “磁碟机”病毒疫情紧急!已有超过5万台电脑被感染
- vc++入门之路~~!~~~!~~【转】
- 世界编程语言排行榜08年03月
- 创造性能不能教?(转)