通常我们在进行数据库的新增修改删除查询的时候如果我们面对的不是多个用户也及时单机处理的时候一般我们基本上不需要考虑数据库的表锁定以及死锁之类情况但是如果我们面对的是多用户的并行处理的网络环境的时候我们对表锁定的问题就需要较为仔细的分析和考虑否则他给我们带来的麻烦就不言而喻了下面就把我的在这件事情上遇到的问题以及解决办法同大家一起分享
也是在我的开发过程当中有这样的事情
两个用户同时保存新增的数据我们的程序开始是这样处理
cnBeginTrans
cnExecute insert into tableA
Set rs = cnExecute(select count(*) from tableA where )
If rsRecordCount > Then
表A 的字段A不能从复
cnRollbackTrans
Else
cnCommitTrans
End If
当SQL SERVER 在执行INSERT命令时如果我们不添加任何参数时数据库默认申请一个 IX 锁 给表A这时候我们来分析上面的程序当第一个用户执行 cnExecute insert into tableA Connection
向数据库申请了一个 IX 锁 给表A 与此同时当第二个用户执行 cnExecute insert into tableA Connection 也向数据库也成功地申请了一个 IX 锁 给表A 但是当执行
Set rs = cnExecute(select count(*) from tableA where )
这一句的时候就会有问题产生我们假设第一个用户先一步执行 由于SELECT命令需要向数据库申请一个
S 锁给表A但是由于这时候表A已经存在一个IX锁并且属于另外一个连接因此他只好在此等候紧接着第二个
用户也执行
Set rs = cnExecute(select count(*) from tableA where )
他也会向数据库申请一个S 锁给表A 这时候数据就会自动结束较晚申请IX锁的连接同时回滚这个事务
这样子对于我们的应用来说就是一个很大的失败
解决的办法一设置数据参数让我们可以读取没有提交的数据
cnBeginTrans
cnExecute SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
cnExecute insert into tableA
Set rs = cnExecute(select count(*) from tableA where )
If rsRecordCount > Then
表A 的字段A不能从复
cnRollbackTrans
Else
cnCommitTrans
End If
cnExecute SET TRANSACTION ISOLATION LEVEL READ COMMITTED
解决的办法二设置INSERT 命令 参数 with (tablock)
cnBeginTrans
cnExecute insert into tableA with (tablock)
Set rs = cnExecute(select count(*) from tableA where )
If rsRecordCount > Then
表A 的字段A不能从复
cnRollbackTrans
Else
cnCommitTrans
End If
解决的办法三增加一个没有用Lock 表
cnBeginTrans
cnExecute update tmpLockTable set FieldLock=
cnExecute insert into tableA with (tablock)
Set rs = cnExecute(select count(*) from tableA where )
If rsRecordCount > Then
表A 的字段A不能从复
cnRollbackTrans
Else
cnCommitTrans
End If