VB+ADO检测数据库并发操作和处理并解决并发冲突[1]

[入库:2005年8月18日] [更新:2007年3月24日]

本文简介:选择自 chenyu5188 的 blog

前言:

数据库并发问题详述http://www.csdn.net/develop/read_article.asp?id=24366已经说明了并发的严重性与危害性。下面讲述vb+ado来处理并发操作的实际案例:

在以前dao中可以对数据库进行记录锁,页面锁,表锁来处理并发操作,还可以使用事务处理,那么现在怎么用ado来检测并处理数据库的并发操作呢?

相关背景知识:

ado中对数据库的也是采用锁定的方法来实现的,还可以用事务来做。事务有个特点就是:要么全成功,要么就全失败。那么在实际工作中有可能只有几条或一小部分的记录有冲突,只要对那一小部分的记录进行处理就行了。ado也使用来锁定来实现。

那么什么是锁定?

锁定是一种进程,dbms 通过该进程限制多用户环境中对行的访问。当一行或一列被独占锁定时,不允许其他用户在释放锁定之前访问锁定的数据。这确保了两个用户无法同时更新一行中的同一列。

从资源角度而言,锁定的成本可能非常高昂,只有在需要保持数据完整性的情况下才应当使用此功能。在每秒有数百或数千用户试图访问某个记录的数据库(例如连接到 internet 的数据库)中,不必要的锁定将很快导致应用程序性能的下降。

可选择适当的锁定选项来控制数据源和 ado 游标库管理并发性的方式。

打开 recordset 之前先设置 locktype 属性,以指定提供者打开它时使用的锁定类型。读取该属性以返回打开的 recordset 对象中使用的锁定类型。

提供者可能不支持所有锁定类型。如果提供者不支持请求的 locktype 设置,则替换为另一种锁定类型。若要确定 recordset 对象中实际可用的锁定功能,将soppurts 方法与 adupdate 和 adupdatebatch 一起使用。

如果 cursorlocation  属性设置为 aduseclient,则不支持 adlockpessimistic 设置。如果设置了不支持的值,将不产生错误,而使用所支持的最相近的 locktype。

locktype 属性在 recordset 关闭时为读/写,而在 recordset 打开时为只读。

锁定类型种类(locktype 属性):
1.adlockbatchoptimistic
指示开放式批更新。需要批更新模式。

许多应用程序都一次提取多行,然后需要进行相应的更新,这些更新包括所有需要插入、更新或删除的行的完整集合。使用批游标只需一次往返服务器,因而导致更新性能的提高和网络通信量的降低。使用批游标库可创建静态游标,然后断开到数据源的连接。这时就可以对行进行更改,然后重新连接到数据源并将更改以批的形式发布到数据源。

2.adlockoptimistic
提供者使用开放式锁定,仅在调用 update 方法时锁定记录。这意味着另一个用户有可能会利用您编辑记录和调用 update 的时间间隔更改数据,这就会引起冲突。而使用此锁定类型时发生冲突的几率很低,即使发生了冲突也会很快得到解决。

3.adlockpessimistic
指示逐个记录保守式锁定。提供者要确保记录编辑成功,通常在编辑之前立即在数据源锁定记录。当然,这意味着一旦您开始编辑记录,这些记录就会对其他用户不可用,知道您通过调用 update 释放锁定。如果您的系统不提供对数据的并发更改,例如预定系统,那么可使用此锁定类型。

4.adlockreadonly
指示只读记录。无法改变数据。只读锁定是速度“最快”的锁定类型,因为它不要求服务器保持对记录的锁定。冲突

5.adlockunspecified
未指定锁定类型。

检测和解决冲突:
如果在立即模式中处理 recordset,则很少出现并发问题。另一方面,如果应用程序使用批模式更新,则在保存由一个正在编辑记录的用户所作的更改之前,编辑同一个记录的另一个用户比较有可能会更改记录。在这种情况下,需要应用程序准确处理冲突。无论是哪种情况,都可以使用 ado 提供的 field 对象的 underlyingvalue 和 originalvalue 属性来处理这些类型的冲突。将这些属性与 recordset 的 resync 方法和 filter 属性配合使用。

检测错误
在批更新期间 ado 遇到冲突时,将在 errors 集合中放入警告。因此,调用 batchupdate 之后,一定要立即检查是否有错误,如果找到了错误,则应当假设已遇到冲突并开始进行测试。第一步要将 recordset 的 filter 属性设置为等于 adfilterconflictingrecords。该设置将使 recordset对象限制为只显示那些发生冲突的记录。如果这一步之后 recordcount 属性等于零,就说明错误是由冲突以外的其他原因引起的。

调用 batchupdate 时,ado 和提供者将生成对数据源执行更新的 sql 语句。下一步,调用 recordset 的 resync 方法,并且将 affectrecords 参数设置为等于 adaffectgroup,将 resyncvalues 参数设置为等于 adresyncunderlyingvalues。resync 方法将用来自基本数据库中的数据刷新在当前 recordset 对象中的数据。通过使用 adaffectgroup,可以确保只有使用当前筛选设置的情况下可见的记录(即只有冲突记录)会与数据库重新同步。如果处理的是大型 recordset,该操作会对性能有较大影响。通过在调用 resync 时将 resyncvalues 参数设置为 adresyncunderlyingvalues,可以确保 underlyingvalue 属性将包含数据库中的(冲突)值,并确保 value 属性仍然是由用户输入的值,还会确保 originalvalue 属性将持有字段的原始值(即在上一次成功进行 updatebatch 调用之前该字段所拥有的值)。然后,可以使用这些值通过编程方式解决冲突,或要求用户选择将要使用的值。

范例:

在调用 updatebatch 之前,本范例通过使用单独的 recordset 来更改基本表中的值,人为地创建一个冲突。

'begin
    on error goto errhandler:   
    dim objrs1 as new adodb.recordset
    dim objrs2 as new adodb.recordset
    dim strsql as string
    dim strmsg as string   
    strsql = "select * from shippers where shipperid = 2"’sql查询
    objrs1.cursorlocation = aduseclient’设置客户端游标
    objrs1.open strsql, strconn, adopenstatic, adlockbatchoptimistic, adcmdtext’执行查询生成objrs1记录集
    objrs1("phone") = "(111) 555-1111"’更改表中一条记录phone字段的值
    objrs2.open strsql, strconn, adopenkeyset, adlockoptimistic, adcmdtext’执行查询生成objrs2记录集
    objrs2("phone") = "(999) 555-9999" ’更改表中记录phone字段的值
    objrs2.update
    objrs2.close
    set objrs2 = nothing   
    on error resume next
    objrs1.updatebatch   
    if objrs1.activeconnection.errors.count <> 0 then
        dim intconflicts as integer
        intconflicts = 0
        objrs1.filter = adfilterconflictingrecords
        intconflicts = objrs1.recordcount
        objrs1.resync adaffectgroup, adresyncunderlyingvalues
        if intconflicts > 0 then
           strmsg = "a conflict occurred with updates for " & intconflicts & "records." & vbcrlf & "the values will be restored"                     " to their original values."
           objrs1.movefirst
           while not objrs1.eof

本文关键:VB+ADO 数据库并发操作
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top