也谈SQL SERVER 的锁-数据库专栏,SQL Server
来源:作者: 发布时间:2007-12-26 02:03:54


通常我们在进行数据库的新增、修改、删除、查询的时候假如我们面对的不是多个用户也及时单机处理的时候, 一般我们基本上无需考虑数据库的表锁定连同死锁之类情况,但是假如我们面对的是多用户的并行处理的 网络环境的时候我们对表锁定的问题就需要较为仔细的分析和考虑,否则他给我们带来的麻烦就不言而喻了, 下面就把我的在这件事情上碰到的问题连同解决办法同大家一起分享。 也是在我的研发过程当中有这样的事情: 两个用户同时保存新增的数据,我们的程式开始是这样处理 cn.begintrans cn.execute "insert into tablea ....." set rs = cn.execute("select count(*) from tablea where ...") if rs.recordcount > 0 then 表a 的字段a不能从复 cn.rollbacktrans else cn.committrans end if
当sql server 在执行insert 命令时假如我们不添加任何参数时 数据库默认申请一个 ix 锁 给表a 这时候我们来分析上面的程式,当第一个用户执行 cn.execute "insert into tablea ....." connection 向数据库申请了一个 ix 锁 给表a ,和此同时当第二个用户执行 cn.execute "insert into tablea ....." connection 也向数据库也成功地申请了一个 ix 锁 给表a ,但是当执行 set rs = cn.execute("select count(*) from tablea where ...") 这一句的时候就会有问题产生,我们假设第一个用户先一步执行 ,由于select命令需要向数据库申请一个 s 锁给表a,但是由于这时候表a已存在一个ix锁并且属于另外一个连接因此他只好在此等候。紧接着第二个 用户也执行 set rs = cn.execute("select count(*) from tablea where ...") 他也会向数据库申请一个s 锁给表a ,这时候数据就会自动结束较晚申请ix锁的连接同时回滚这个事务 这样子对于我们的应用来说就是个很大的失败。
解决的办法一,配置数据参数让我们能够读取没有提交的数据、
cn.begintrans cn.execute "set transaction isolation level read uncommitted " cn.execute "insert into tablea ....." set rs = cn.execute("select count(*) from tablea where ...") if rs.recordcount > 0 then 表a 的字段a不能从复 cn.rollbacktrans else cn.committrans end if cn.execute "set transaction isolation level read committed "
解决的办法二,配置insert 命令 参数 with (tablock) 、
cn.begintrans cn.execute "insert into tablea with (tablock) ....." set rs = cn.execute("select count(*) from tablea where ...") if rs.recordcount > 0 then 表a 的字段a不能从复 cn.rollbacktrans else cn.committrans end if 解决的办法三,增加一个没有用lock 表、
cn.begintrans cn.execute "update tmplocktable set fieldlock=1" cn.execute "insert into tablea with (tablock) ....." set rs = cn.execute("select count(*) from tablea where ...") if rs.recordcount > 0 then 表a 的字段a不能从复 cn.rollbacktrans else cn.committrans end if
|
还没有关于此文章的相关评论!