6

在我的应用程序中,我做了以下事情:

  1. 使用 Jet/ADO 和 VB6 打开 Access 数据库 (.mdb)
  2. 用新数据清除并重新填充表格
  3. 关闭数据库
  4. 启动另一个处理新数据的进程。

问题是有时第二个进程找不到新数据。有时表只是空的,有时 RecordCount > 0,但 EOF 为真,我不能执行 MoveFirst 或 MoveNext。简而言之:各种奇怪的东西。

我目前的解决方法是在关闭数据库和启动第二个进程之间添加延迟。

  • 这里发生了什么?
  • 我能做点什么吗?(除了使用不同的数据库)
4

3 回答 3

7

只是一个猜测,但我可能是因为 Jet 引擎具有读取缓存和延迟写入功能:

如何在 Jet 4.0 和 ADO 2.1 中实现多用户自定义计数器

“Microsoft Jet 有一个读取缓存,每 PageTimeout 毫秒更新一次(默认为 5000ms = 5 秒)。它还有一个惰性写入机制,该机制在一个单独的线程上运行到主处理,因此异步将更改写入磁盘。这两个机制有助于提高性能,但在某些需要高并发的情况下,它们可能会产生问题。”

该文章建议使用 Jet 的 RefreshCache 方法并将 Jet OLEDB:Transaction Commit Mode 设置为 1 毫秒(ADO 优于 Jet 的 DAO 的一个优点是您可以更改此设置而无需更改注册表中的值)。

PS你应该考虑编辑Access数据库(.mdb)来提及'Jet'并使用'Jet'标签,否则你会得到某个SO用户的评论,他对这些事情很挑剔:)

于 2009-01-28T10:06:56.197 回答
3

Microsoft 知识库文章解释了如何执行此操作。

这是示例代码的摘录。该代码使用来自一个进程的两个连接,因此您需要将阅读部分拉入第二个进程。

  1. 写入者必须在写入数据之前使用 ADO 的 Connection.BeginTrans 启动事务。
  2. 编写者必须进行数据库更新,然后提交事务(使用 ADO 的 Connection.CommitTrans)。
  3. 读取器在尝试读取数据之前必须调用 JRO.JetEngine.RefreshCache 传入它的连接。

请注意,通过向您的 VB 项目添加对 Microsoft Jet And Replication Objects 2.1 Library 的引用来包含 JRO.JetEngine。

    Sub SyncReadDemo()
    Dim conn1 As New ADODB.Connection
    Dim conn2 As New ADODB.Connection
    Dim rs As New ADODB.recordset
    Dim JRO As New JRO.JetEngine
    Dim strConnect As String
    Dim i As Long


  ' Set up our connection string (requires a database named c:\db1.mdb).
    strConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\db1.mdb"

    ' Open connection 1 and drop and re-create test table.
    conn1.CursorLocation = adUseServer
    conn1.Open strConnect
    On Error Resume Next
    conn1.Execute "drop table tmpTest", , _
        adExecuteNoRecords + adCmdText
    On Error GoTo 0
    conn1.Execute "create table tmpTest (id long)", , _
        adExecuteNoRecords + adCmdText

    ' Close connection 1 to flush the creation of table tmpTest. 
    conn1.Close

    ' Now open connection 1 and connection 2.
    conn1.Open strConnect
    conn2.Open strConnect

    ' Insert 10 records using connection 1.
    ' Note we must perform all writes inside of a transaction.
    conn1.BeginTrans
    For i = 1 To 10
        conn1.Execute "insert into tmpTest (id) values (1)", , _
            adExecuteNoRecords + adCmdText
    Next i
    conn1.CommitTrans

    ' Refresh cache for reader connection.
    JRO.RefreshCache conn2
    Set rs = conn2.Execute("select * from tmpTest", , adCmdText)

    ' Count records in our table (should be 10).
    i = 0
    While Not rs.EOF
        i = i + 1
        rs.MoveNext
    Wend
    rs.Close

    MsgBox "Read " & i & " records using different connections."

    conn1.Close
    conn2.Close

End Sub
于 2009-01-28T10:21:28.353 回答
-1

由于第一个进程是唯一打开 MDB 的进程,因此将内容写回文件可能有点懒惰。即使在您结束进程之后,在操作系统写回未完成的页面时也可能会出现延迟,这可能在进程发出已完成的信号后发生。

我的建议是,停止使用 Access,改用 SQL Server 2008 Express。

于 2009-01-28T09:17:53.160 回答