Почему моя база данных Access не обновлена, когда я читаю ее из другого процесса?
В своем приложении я делаю следующие вещи:
- Откройте базу данных Access (.mdb), используя Jet/ADO и VB6.
- Очистить и заново заполнить таблицу новыми данными
- Закройте базу данных
- Запустите другой процесс, который что-то делает с новыми данными.
Проблема в том, что иногда второй процесс не может найти новые данные. Иногда таблица просто пуста, иногда 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, который привередлив в этих вещах:)
В этой статье базы знаний Майкрософт объясняется, как это сделать.
Вот выдержка с примером кода. Код использует два соединения из одного процесса, поэтому вам нужно вставить часть чтения во второй процесс.
- Автор должен начать транзакцию, используя ADO Connection.BeginTrans, до записи данных.
- Автор должен обновить базу данных, а затем зафиксировать транзакцию (используя ADO Connection.CommitTrans).
- Читатель должен вызвать 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.