也谈SQLSERVER的锁

来源:互联网 发布:单片机自制电台 编辑:程序博客网 时间:2024/06/13 12:49
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 160x600, 创建于 08-4-23MSDN */google_ad_slot = "4367022601";google_ad_width = 160;google_ad_height = 600;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>

 通常我们在进行的新增、修改、删除、查询的时候如果我们面对的不是多个用户也及时单机处理的时候,
一般我们基本上不需要考虑数据库的表锁定以及死锁之类情况,但是如果我们面对的是多用户的并行处理的
网络环境的时候我们对表锁定的问题就需要较为仔细的分析和考虑,否则他给我们带来的麻烦就不言而喻了,
下面就把我的在这件事情上遇到的问题以及解决办法同大家一起分享。
也是在我的开发过程当中有这样的事情:
两个用户同时保存新增的数据,我们的程序开始是这样处理
   cn.BeginTrans
   cn.Execute"insertintotableA....."
   Setrs=cn.Execute("selectcount(*)fromtableAwhere...")
   Ifrs.RecordCount>0Then
       '表A的字段A不能从复
       cn.RollbackTrans
   Else
       cn.CommitTrans
   EndIf

SQLSERVER在执行INSERT 命令时如果我们不添加任何参数时 数据库默认申请一个IX锁给表A
这时候我们来分析上面的程序,当第一个用户执行   cn.Execute"insertintotableA....."Connection
向数据库申请了一个IX锁给表A,与此同时当第二个用户执行   cn.Execute"insertintotableA....."Connection也向数据库也成功地申请了一个IX锁给表A,但是当执行  
Setrs=cn.Execute("selectcount(*)fromtableAwhere...")
这一句的时候就会有问题产生,我们假设第一个用户先一步执行,由于SELECT命令需要向数据库申请一个
S锁给表A,但是由于这时候表A已经存在一个IX锁并且属于另外一个连接因此他只好在此等候。紧接着第二个
用户也执行
Setrs=cn.Execute("selectcount(*)fromtableAwhere...")
他也会向数据库申请一个S锁给表A,这时候数据就会自动结束较晚申请IX锁的连接同时回滚这个事务
这样子对于我们的应用来说就是一个很大的失败。

解决的办法一,设置数据参数让我们可以读取没有提交的数据、

   cn.BeginTrans
   cn.Execute"SETTRANSACTIONISOLATIONLEVELREADUNCOMMITTED"
   cn.Execute"insertintotableA....."
   Setrs=cn.Execute("selectcount(*)fromtableAwhere...")
   Ifrs.RecordCount>0Then
       '表A的字段A不能从复
       cn.RollbackTrans
   Else
       cn.CommitTrans
   EndIf
   cn.Execute"SETTRANSACTIONISOLATIONLEVELREADCOMMITTED"

解决的办法二,设置INSERT命令参数with(tablock)、

   cn.BeginTrans
   cn.Execute"insertintotableAwith(tablock) ....."
   Setrs=cn.Execute("selectcount(*)fromtableAwhere...")
   Ifrs.RecordCount>0Then
       '表A的字段A不能从复
       cn.RollbackTrans
   Else
       cn.CommitTrans
   EndIf
 
解决的办法三,增加一个没有用Lock表、

   cn.BeginTrans
   cn.Execute"updatetmpLockTablesetFieldLock=1"1

<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 160x600, 创建于 08-4-23MSDN */google_ad_slot = "4367022601";google_ad_width = 160;google_ad_height = 600;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
原创粉丝点击