Почему моя база данных Access не обновлена, когда я читаю ее из другого процесса?

В своем приложении я делаю следующие вещи:

  1. Откройте базу данных Access (.mdb), используя Jet/ADO и VB6.
  2. Очистить и заново заполнить таблицу новыми данными
  3. Закройте базу данных
  4. Запустите другой процесс, который что-то делает с новыми данными.

Проблема в том, что иногда второй процесс не может найти новые данные. Иногда таблица просто пуста, иногда RecordCount > 0, но EOF имеет значение true, и я не могу сделать MoveFirst или MoveNext. В двух словах: все виды странных вещей.

Мой текущий обходной путь - добавление задержки между закрытием базы данных и запуском второго процесса.

  • Что здесь происходит?
  • Могу ли я что-нибудь с этим сделать? (Помимо использования другой базы данных)

3 ответа

Решение

Просто предположение, но я могу быть из-за того, что движок Jet имеет кеш чтения и ленивые записи:

Как реализовать многопользовательские пользовательские счетчики в Jet 4.0 и ADO 2.1

"Microsoft Jet имеет кэш-память чтения, которая обновляется каждые миллисекунды PageTimeout (по умолчанию 5000 мс = 5 секунд). Он также имеет механизм отложенной записи, который работает в отдельном потоке для основной обработки и, таким образом, записывает изменения на диск асинхронно. Эти два Механизмы помогают повысить производительность, но в определенных ситуациях, требующих высокого уровня параллелизма, они могут создавать проблемы ".

В статье предлагается использовать метод Jet RefreshCache и установить для Jet OLEDB:Transaction Commit mode значение 1 миллисекунду (одно преимущество ADO над DAO для Jet заключается в том, что вы можете изменить этот параметр без изменения значения в реестре).

PS вам следует подумать о том, чтобы отредактировать базу данных Access (.mdb), чтобы вместо нее упомянуть "Jet", а также использовать тег "Jet", в противном случае вы получите комментарий от определенного пользователя SO, который привередлив в этих вещах:)

В этой статье базы знаний Майкрософт объясняется, как это сделать.

Вот выдержка с примером кода. Код использует два соединения из одного процесса, поэтому вам нужно вставить часть чтения во второй процесс.

  1. Автор должен начать транзакцию, используя ADO Connection.BeginTrans, до записи данных.
  2. Автор должен обновить базу данных, а затем зафиксировать транзакцию (используя ADO Connection.CommitTrans).
  3. Читатель должен вызвать JRO.JetEngine.RefreshCache, передавая его соединение, прежде чем пытаться прочитать данные.

Обратите внимание, что JRO.JetEngine включен путем добавления ссылки на библиотеку Microsoft Jet и объекты репликации 2.1 в ваш проект VB.

    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

Поскольку первый процесс является единственным процессом с открытым MDB, он может быть немного ленивым о записи материала обратно в файл. Даже после того, как вы завершите процесс, может возникнуть задержка, пока ОС записывает оставшиеся страницы, и это может произойти после того, как процесс дал сигнал о завершении.

Я бы рекомендовал прекратить использование Access, вместо этого использовать SQL Server 2008 Express.

Другие вопросы по тегам