数据记录的锁定

yingxiangchen 2006-05-27 04:45:54
1.要怎样才能知道数据库(Access & SQL Sever)中某表的某条记录的锁定状态呢?
2.各位通常采用什么样的锁定方法来锁定数据记录呢?
...全文
193 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
yechat 2006-06-10
  • 打赏
  • 举报
回复
原来是张老贴,我晕
yechat 2006-06-10
  • 打赏
  • 举报
回复
ADO操纵SQL的锁定机制:

锁定一般分为“乐观锁定”和“悲观锁定”。
也叫:“保守式记录锁定”和“开放式记录锁定”

在ADO中,锁定行为作用于一条记录,即:行锁。这种锁定提高了并发粒度(即可以有多个并发对同一个对像进行操作,而表级锁定,当一个并发锁定表后,其他并发都不能更新此表,直到锁定完成。而行锁不同,它只锁定行中的一行,当一个并发锁定表中一行时,其他并发还可以更新其它行)。

同时,行锁增加了SQL SERVER的系统开锁。

SQL自动管理锁,并使用合适的锁定粒度:
Microsoft® SQL Server™ 2000 使用动态锁定策略确定最经济的锁。
应用程序开发人员可以集中精力进行开发。SQL Server 自动调整锁定。


设有两个连接:A、B

乐观锁定:
A在执行UPDATE这一刻才锁定数据,锁定后的数据,在执行锁定当时那一刻之前是可以被B更改的,但被B更改后,A在UPDATE时会收到一错误消息:“乐观并发检查失败。已在此游标之外修改了该行。”

还有一种情况,当大量并发连接更改数据时,可能在你锁定这一刻的同时有连接B也同时UPDATE,此时会发生“阻塞”。也就是A连接完成UPDATE前,B连接一直处理等待状态。

当然,乐观锁定发生“阻塞”的可能性很小,因为锁定只发生在UPDATE那一刻,但不代表不发生。
乐观并发:乐观并发控制假定不太可能(但不是不可能)在多个用户间发生资源冲突。

乐观锁定的这种特性,造成了一个缺点:使用乐观锁定时,不能确保在UPDATE时能成功。

悲观锁定:
A在执行数据修改时,UPDATE之前就对数据进行锁定,比如:objRs2("iOrder_Qty") = Rnd 这条语句执行时,数据就会被锁定。

此时,B如果使用的乐观锁定,那么在B执行UPDATE时,会发生阻塞,阻塞直到A完成UPDATE并对数据解锁;此时B才能继续。
当然B出错,因为B打开记录时为x,而A执行UPDATE后变成了y,所以B会报错:“乐观并发检查失败。已在此游标之外修改了该行。”
还有一种可能是B因为等待太久超时而返回错误:“[DBNETLIB][ConnectionRead (WrapperRead()).]一般性网络错误。请检查网络文档。”

另外:B如果使用的悲观锁定,那么在B执行数据修改时,UPDATE之前就会阻塞,比如:objRs2("iOrder_Qty") = Rnd 这条语句执行时,阻塞发生。

A被称为“阻塞者”,B是“被阻塞者”,在SQL企业管理器中:A为“正在阻塞”,B会列出阻塞者的spid,即是A。


综上:在一般企业应用程序设计时,使用“乐观锁定”以便得到高并发性。而对阻塞的处理,使用超时错误处理机制。实际上使用ADO+SQL不太需要考虑锁的问题,因为这都由SQL SERVER为你代劳了。

只有一种情况要避免:在程序中因为执行顺序而引起阻塞,此时的阻塞无法解除,形同“死锁”。只能在“企业管理器”中取消阻塞者的进程。或者等待超时。

在SQL企业管理器中查看阻塞的路径为:Microsoft SQL Servers\SQL Server组\Server Name\管理\当前活动\ [锁/进程 ID]



以下是一个阻塞的演示,可能你需要更改一些变量值,比如:strCn$,strSql$和列名。
这个演示必然引起阻塞,而且这是形同死锁的阻塞,此时你可以在SQL企业管理器中取消阻塞者的进程。


Sub main()
On Error GoTo msg
Dim strCn$, strSql$

Dim objCn As New ADODB.Connection
Dim objCn2 As New ADODB.Connection
Dim objRs As New ADODB.Recordset
Dim objRs2 As New ADODB.Recordset

strCn$ = "Provider=SQLOLEDB.1;Password=;Persist Security Info=True;User ID=sa;Initial Catalog=myDB;Data Source=localhost"
strSql$ = "SELECT * From myTab"

objCn.Open strCn$
objCn2.Open strCn$

objRs.Open strSql$, objCn, adOpenDynamic, adLockPessimistic, adCmdText '悲观锁定

objRs("iOrder_Qty") = Rnd

objRs2.Open strSql$, objCn2, adOpenDynamic, adLockPessimistic, adCmdText '悲观锁定

objRs2("iOrder_Qty") = Rnd

objRs2.Update
objRs.Update
msg:
If Err Then Msgbox Err.Description
End Sub

yingxiangchen 2006-06-09
  • 打赏
  • 举报
回复
up
verious 2006-05-28
  • 打赏
  • 举报
回复
如果要实现你说的这种方式,那就用独占模式打开数据库,然后连接时判断数据库是否已打开,返回一标识
yingxiangchen 2006-05-28
  • 打赏
  • 举报
回复
顶,没人知道吗?

1,216

社区成员

发帖
与我相关
我的任务
社区描述
VB 数据库(包含打印,安装,报表)
社区管理员
  • 数据库(包含打印,安装,报表)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧