也谈SQL SERVER的锁
2007-11-11 10:07:04 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ょ紓宥咃躬瀵鎮㈤崗灏栨嫽闁诲酣娼ф竟濠偽i鍓х<闁诡垎鍐f寖闂佺娅曢幑鍥灳閺冨牆绀冩い蹇庣娴滈箖鏌ㄥ┑鍡欏嚬缂併劎绮妵鍕箳鐎n亞浠鹃梺闈涙搐鐎氫即鐛崶顒夋晬婵絾瀵ч幑鍥蓟閻斿摜鐟归柛顭戝枛椤牆顪冮妶搴′簼缂侇喗鎸搁悾鐑藉础閻愬秵妫冮崺鈧い鎺戝瀹撲礁鈹戦悩鎻掝伀缁惧彞绮欓弻娑氫沪閹规劕顥濋梺閫炲苯澧伴柟铏崌閿濈偛鈹戠€n€晠鏌嶆潪鎷屽厡闁汇倕鎳愮槐鎾存媴閸撴彃鍓卞銈嗗灦閻熲晛鐣烽妷褉鍋撻敐搴℃灍闁绘挻娲橀妵鍕箛闂堟稐绨肩紓浣藉煐濮樸劎妲愰幘璇茬闁冲搫鍊婚ˇ鏉库攽椤旂》宸ユい顓炲槻閻g兘骞掗幋鏃€鐎婚梺瑙勬儗閸樺€熲叺婵犵數濮烽弫鍛婃叏椤撱垹纾婚柟鍓х帛閳锋垶銇勯幒鍡椾壕缂備礁顦遍弫濠氱嵁閸℃稒鍊烽柛婵嗗椤旀劕鈹戦悜鍥╃У闁告挻鐟︽穱濠囨嚃閳哄啰锛滈梺褰掑亰閸欏骸鈻撳⿰鍫熺厸閻忕偟纭堕崑鎾诲箛娴e憡鍊梺纭呭亹鐞涖儵鍩€椤掑啫鐨洪柡浣圭墪閳规垿鎮欓弶鎴犱桓闂佸湱枪閹芥粎鍒掗弮鍫熷仺缂佸顕抽敃鍌涚厱闁哄洢鍔岄悘鐘绘煕閹般劌浜惧┑锛勫亼閸婃牠宕濋敃鈧…鍧楀焵椤掍胶绠剧€光偓婵犱線鍋楀┑顔硷龚濞咃絿妲愰幒鎳崇喓鎷犻懠鑸垫毐闂傚倷鑳舵灙婵炲鍏樺顐ゆ嫚瀹割喖娈ㄦ繝鐢靛У绾板秹寮查幓鎺濈唵閻犺櫣灏ㄥ銉р偓瑙勬尭濡繂顫忛搹鍦<婵☆垰鎼~宥囩磽娴i鍔嶉柟绋垮暱閻g兘骞嬮敃鈧粻濠氭偣閸パ冪骇鐎规挸绉撮—鍐Χ閸℃ê闉嶇紓浣割儐閸ㄥ墎绮嬪澶嬪€锋い鎺嶇瀵灝鈹戦埥鍡楃仯闁告鍕洸濡わ絽鍟崐鍨叏濡厧浜鹃悗姘炬嫹

通常我们在进行数据库的新增、修改、删除、查询的时候如果我们面对的不是多个用户也及时单机处理的时候,
一般我们基本上不需要考虑数据库的表锁定以及死锁之类情况,但是如果我们面对的是多用户的并行处理的
网络环境的时候我们对表锁定的问题就需要较为仔细的分析和考虑,否则他给我们带来的麻烦就不言而喻了,
下面就把我的在这件事情上遇到的问题以及解决办法同大家一起分享。
也是在我的开发过程当中有这样的事情:
两个用户同时保存新增的数据,我们的程序开始是这样处理
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(WINDOWS平台上强大的数据库平台) 在执行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 UNCOMM99vTED "
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 COMM99vTED "
解决的办法二,设置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
- ››SQL Server 2008 R2 下如何清理数据库日志文件
- ››sqlite 存取中文的解决方法
- ››SQL2005、2008、2000 清空删除日志
- ››SQL Server 2005和SQL Server 2000数据的相互导入...
- ››sql server 2008 在安装了活动目录以后无法启动服...
- ››sqlserver 每30分自动生成一次
- ››sqlite 数据库 对 BOOL型 数据的插入处理正确用法...
- ››sql server自动生成批量执行SQL脚本的批处理
- ››sql server 2008亿万数据性能优化
- ››SQL Server 2008清空数据库日志方法
- ››sqlserver安装和简单的使用
- ››SQL Sever 2008 R2 数据库管理
更多精彩
赞助商链接