Scheinbarer "Datenverlust" durch Jet Engine Cache?

17/04/2009 - 08:57 von al | Report spam
Hallo Gruppe,

ich habe ein Problem bei der Datenspeicherung in Access Datenbanken durch
Visual C++ 6 Module via DAO: Ab einem scheinbar zufàlligen Zeitpunkt kann auf
neuere Daten nicht zugegriffen werden, weil diese scheinbar statt direkt in
die Datenbank zunàchst in den Cache der Jet Engine geschrieben werden. Die
Daten können von Clients bis zu diesem Punkt gelesen werden, von da an sind
einfach keine Daten mehr in der DB (es wird auch kein Fehler an den Client
gemeldet). Sobald ich das Speichermodul beende, werden die Daten plötzlich in
die Datenbank geschrieben (flush?). Das Speichermodul behandelt mehrere
gleiche Datenbanken parallel, das Problem tritt jedoch nur sporadisch bei
einzelnen DBs auf.

Ich vermute das die Daten in den Puffer der Jet Engine geschrieben werden.
Laut http://office.microsoft.com/en-us/a...11033.aspx würde sich
die MaxBufferSize ca. 500MB betragen. Workaround wàre die Größe zu
verringern, ich möchte aber erstmal wissen was die Jet Engine dazu
veranlasst, überhaupt auf den Cache zu wechseln und nie wieder direkt in die
DB zu speichern.

Anmerkung: In einem Fall habe ich bemerkt das nach ein paar Tagen ca. 16000
Records aus dem Cache in die DB ge-flushed wurden ohne dass ich das
Speichermodul heruntergefahren habe. Vermutlich war der Cache gerade voll
o.à. Nach diesem Flush wurden neue Daten jedoch weiterhin in den (jetzt
leeren) Cache statt in die DB geschrieben. Als ich das Speichermodul
beendete, landeten diese Daten wieder in der DB.

Hintergrundinformationen:
Mein System besteht aus mehreren VC++ 6 Modulen die als Windows Service im
Hintergrund laufen. Datenzugriff auf die Access 2000 Datenbanken passiert via
DAO. Das Speichermodul öffnet die DB beim Start, speichert alle paar Sekunden
10-30 Datensàtze und schließt die Tabelle/DB erst beim Beenden. Ein
Loggingmodul öffnet eine andere Tabelle bei Bedarf (z.B. jede Stunde) und
schreibt dort Werte. Aus den Tabellen werden keine Daten gelöscht. Die
Datenbanken sind an einen Produktionsprozess geknüpft, welcher einige Tage
làuft. Für neue Prozesse werden neue Datenbanken verwendet. Typische Größe
der DB ist 100MB. Die DBs werden von Clients über das Netzwerk via UNC zum
Lesen geöffnet, die lokalen Module speichern jedoch lokal ohne UNC. Es werden
keine Transaktionen verwendet.
Als der Caching-Fehler auftrat, bemerkte ich auch das vom Loggingmodul keine
Daten geschrieben werden konnten, Fehlermeldung war "Table could not update.
Currently locked by user xyz". Jedoch öffnet die vom Loggingmodul verwendete
Tabelle kein anderes Modul.

Vielleicht ist es hilfreich zu wissen, das ein AntiViren-Programm im
Hintergrund làuft. Ob dieser jedoch einen Zugriffsscan durchführt und MDBs
evtl. ignoriert bin ich im Moment noch am Herausfinden.

Hatte irgendjemand schonmal ein solches Problem? Aus welchem Grund sollte
die Jet Engine plötzlich in den Cache schreiben statt in die DB? Wie kann ich
vom Programm aus dieses Verhalten abschalten/verhindern/erkennen?
Irgendwelche Ideen/Tools die mir helfen könnten, das Problem weiter zu
analysieren?

Vielen Dank
Alex
 

Lesen sie die antworten

#1 Sascha Trowitzsch
17/04/2009 - 11:18 | Warnen spam
Hallo Alex,

"al" schrieb im Newsbeitrag
news:
Hallo Gruppe,

ich habe ein Problem bei der Datenspeicherung in Access Datenbanken durch
Visual C++ 6 Module via DAO: Ab einem scheinbar zufàlligen Zeitpunkt kann auf
neuere Daten nicht zugegriffen werden, weil diese scheinbar statt direkt in
die Datenbank zunàchst in den Cache der Jet Engine geschrieben werden. Die
Daten können von Clients bis zu diesem Punkt gelesen werden, von da an sind
einfach keine Daten mehr in der DB (es wird auch kein Fehler an den Client
gemeldet). Sobald ich das Speichermodul beende, werden die Daten plötzlich in
die Datenbank geschrieben (flush?). Das Speichermodul behandelt mehrere
gleiche Datenbanken parallel, das Problem tritt jedoch nur sporadisch bei
einzelnen DBs auf.

Ich vermute das die Daten in den Puffer der Jet Engine geschrieben werden.
Laut http://office.microsoft.com/en-us/a...11033.aspx würde sich
die MaxBufferSize ca. 500MB betragen. Workaround wàre die Größe zu
verringern, ich möchte aber erstmal wissen was die Jet Engine dazu
veranlasst, überhaupt auf den Cache zu wechseln und nie wieder direkt in die
DB zu speichern.

Anmerkung: In einem Fall habe ich bemerkt das nach ein paar Tagen ca. 16000
Records aus dem Cache in die DB ge-flushed wurden ohne dass ich das
Speichermodul heruntergefahren habe. Vermutlich war der Cache gerade voll
o.à. Nach diesem Flush wurden neue Daten jedoch weiterhin in den (jetzt
leeren) Cache statt in die DB geschrieben. Als ich das Speichermodul
beendete, landeten diese Daten wieder in der DB.

Hintergrundinformationen:
Mein System besteht aus mehreren VC++ 6 Modulen die als Windows Service im
Hintergrund laufen. Datenzugriff auf die Access 2000 Datenbanken passiert via
DAO. Das Speichermodul öffnet die DB beim Start, speichert alle paar Sekunden
10-30 Datensàtze und schließt die Tabelle/DB erst beim Beenden. Ein
Loggingmodul öffnet eine andere Tabelle bei Bedarf (z.B. jede Stunde) und
schreibt dort Werte. Aus den Tabellen werden keine Daten gelöscht. Die
Datenbanken sind an einen Produktionsprozess geknüpft, welcher einige Tage
làuft. Für neue Prozesse werden neue Datenbanken verwendet. Typische Größe
der DB ist 100MB. Die DBs werden von Clients über das Netzwerk via UNC zum
Lesen geöffnet, die lokalen Module speichern jedoch lokal ohne UNC. Es werden
keine Transaktionen verwendet.
Als der Caching-Fehler auftrat, bemerkte ich auch das vom Loggingmodul keine
Daten geschrieben werden konnten, Fehlermeldung war "Table could not update.
Currently locked by user xyz". Jedoch öffnet die vom Loggingmodul verwendete
Tabelle kein anderes Modul.

Vielleicht ist es hilfreich zu wissen, das ein AntiViren-Programm im
Hintergrund làuft. Ob dieser jedoch einen Zugriffsscan durchführt und MDBs
evtl. ignoriert bin ich im Moment noch am Herausfinden.

Hatte irgendjemand schonmal ein solches Problem? Aus welchem Grund sollte
die Jet Engine plötzlich in den Cache schreiben statt in die DB? Wie kann ich
vom Programm aus dieses Verhalten abschalten/verhindern/erkennen?
Irgendwelche Ideen/Tools die mir helfen könnten, das Problem weiter zu
analysieren?



Zunàchst mal ist das das ganz normale Verhalten der Jet-Engine. Die hat sowohl
einen Lese- wie auch Schreib-Cache.
Würden Datensàtze, die man schreibt, immer gleich und sofort physisch in die
Backend-Datei gespeichert werden, dann hatte das deutliche Performanceprobleme
zurfolge - vor allem im Mehrbenutzerbetrieb. Denn der Server, auf dem die Datei
liegt, müsste dann Teile der Datei alleweil für den Schreibvorgang sperren, was
andere Zugriffe beeintràchtigt und außerdem den Netzwerktraffic erhöhen würde.
Die Seite zu den Parametern der Jet-Engine hast du ja offenbar schon gefunden.
Der Cache làsst sich beeinflussen. Standardmàßig sind es eigentlich 5 Sekunden,
bis in den Cache geschriebene Daten auch tatsàchlich in die Datei gespeichert
werden. Dafür sind diese Parameter der Jet-Engine (SetOption) verantwortlich:
FlushTransactionTimeout und PageTimeout nebst MaxBufferSize.
Erlàuterung siehe hier:
http://office.microsoft.com/de-de/a...01031.aspx

Man kann über DAO aber auch explicit anweisen, dass die Daten sofort in die
Datei geschrieben werden ("Nulltransaktion"):
DbEngine.BeginTrans
DbEngine.CommitTrans dbForceOSFlush

Trotzdem scheint bei dir irgendwas am Code nicht zu stimmen. Denn mehr als ein
paar Sekunden Delay dürften normal nicht zustande kommen. Und schon gar nicht
dürfte das Schreiben vom JET-Cache von deinem Code ("Speichermodul") abhàngen,
weil JETmehrere eigene Threads für solche asynchronen Aktionen laufen hat.

Ciao, Sascha

Ähnliche fragen