Discussion:
Datei flushen
(zu alt für eine Antwort)
Matthias Frey
2016-10-31 15:01:22 UTC
Permalink
Hallo,
wie kann ich es erzwingen (so lange warten) bis Windows alle
Daten einer Datei auf Festplatte geschreiben hat?

Gefunden habe ich FlushFileBuffers, jedoch muss man da ein Handle
einer Datei angeben. Also muss ich diese Datei offen haben.

In meinem Fall ist die Datei jedoch zu (gerade eben). Ist es richtig,
dass ich diese Datei aufmachen muss um FlushFileBuffers zu verwenden?
Oder gibt es einen besseren Weg?

Bei der procedure Flush von Delphi selber werden ja nur die Buffers
von Delphi gellert, aber nicht die Caches von Windows.

Hindergrund:
Es wird von einer Datenbank ein Backup erzeugt und danach die
Datenbank komprimiert. Wenn man beim Komprimieren den Stecker zieht
ist sowohl das Backup als auch die zu komprimierende korrupt.
Mein Vermutung ist, dass noch nicht alle Daten vom Backup auf
Festplatte sind.

Grüssle
Matthias
Peter Below
2016-11-01 06:50:19 UTC
Permalink
Post by Matthias Frey
Hallo,
wie kann ich es erzwingen (so lange warten) bis Windows alle
Daten einer Datei auf Festplatte geschreiben hat?
Gefunden habe ich FlushFileBuffers, jedoch muss man da ein Handle
einer Datei angeben. Also muss ich diese Datei offen haben.
In meinem Fall ist die Datei jedoch zu (gerade eben). Ist es richtig,
dass ich diese Datei aufmachen muss um FlushFileBuffers zu verwenden?
Oder gibt es einen besseren Weg?
Eigentich nicht. Was Dir hier den Ärger macht ist das File caching von
Windows, und das ist transparent für deine Anwendung.
Post by Matthias Frey
Bei der procedure Flush von Delphi selber werden ja nur die Buffers
von Delphi gellert, aber nicht die Caches von Windows.
Es wird von einer Datenbank ein Backup erzeugt und danach die
Datenbank komprimiert. Wenn man beim Komprimieren den Stecker zieht
ist sowohl das Backup als auch die zu komprimierende korrupt.
Mein Vermutung ist, dass noch nicht alle Daten vom Backup auf
Festplatte sind.
Da hilft nur Erziehung des Benutzers, fürchte ich. Wer den Stecker
zieht ohne den Rechner vorher ordnungsgemäß 'runterzufahren bekommt was
er verdient ;-)...
--
Peter Below
TeamB
Matthias Frey
2016-11-01 13:21:04 UTC
Permalink
Post by Peter Below
Post by Matthias Frey
Hallo,
wie kann ich es erzwingen (so lange warten) bis Windows alle
Daten einer Datei auf Festplatte geschreiben hat?
Gefunden habe ich FlushFileBuffers, jedoch muss man da ein Handle
einer Datei angeben. Also muss ich diese Datei offen haben.
In meinem Fall ist die Datei jedoch zu (gerade eben). Ist es richtig,
dass ich diese Datei aufmachen muss um FlushFileBuffers zu verwenden?
Oder gibt es einen besseren Weg?
Eigentich nicht. Was Dir hier den Ärger macht ist das File caching von
Windows, und das ist transparent für deine Anwendung.
Und uneigentlich? ;-)
Post by Peter Below
Post by Matthias Frey
Bei der procedure Flush von Delphi selber werden ja nur die Buffers
von Delphi gellert, aber nicht die Caches von Windows.
Es wird von einer Datenbank ein Backup erzeugt und danach die
Datenbank komprimiert. Wenn man beim Komprimieren den Stecker zieht
ist sowohl das Backup als auch die zu komprimierende korrupt.
Mein Vermutung ist, dass noch nicht alle Daten vom Backup auf
Festplatte sind.
Da hilft nur Erziehung des Benutzers, fürchte ich. Wer den Stecker
zieht ohne den Rechner vorher ordnungsgemäß 'runterzufahren bekommt was
er verdient ;-)...
Es gibt auch noch sowas wie Stromausfall...
Das Steckerziehen ist der Testfall

Ich probiers mal aus:

procedure FlushFile(const AFileName: String);
var
hwnd: THandle;
begin
hwnd := CreateFile(PChar(AFileName), GENERIC_READ, 0, nil,
OPEN_EXISTING, 0, 0);
if hwnd <> INVALID_HANDLE_VALUE then begin
FlushFileBuffers(hwnd);
CloseHandle(hwnd);
end;
end;

Matthias
Peter Below
2016-11-02 07:34:58 UTC
Permalink
Post by Matthias Frey
Post by Peter Below
Post by Matthias Frey
Hallo,
wie kann ich es erzwingen (so lange warten) bis Windows alle
Daten einer Datei auf Festplatte geschreiben hat?
Gefunden habe ich FlushFileBuffers, jedoch muss man da ein Handle
einer Datei angeben. Also muss ich diese Datei offen haben.
In meinem Fall ist die Datei jedoch zu (gerade eben). Ist es
richtig, dass ich diese Datei aufmachen muss um FlushFileBuffers
zu verwenden? Oder gibt es einen besseren Weg?
Eigentich nicht. Was Dir hier den Ärger macht ist das File caching
von Windows, und das ist transparent für deine Anwendung.
Und uneigentlich? ;-)
Änderung der Strategie. Kopiere die Datenbank, komprimiere die Kopie,
nicht das Orginal. Damit sollte eigentlich nichts mehr katastrophal
schief gehen können.
--
Peter Below
TeamB
Steffen Christgau
2016-11-08 19:04:07 UTC
Permalink
Post by Peter Below
Änderung der Strategie. Kopiere die Datenbank, komprimiere die Kopie,
nicht das Orginal. Damit sollte eigentlich nichts mehr katastrophal
schief gehen können.
ACK. Die andere Datei in-place zu ändern (so verstehe ich den OP),
erscheint mir auch nicht sinnvoll. Ggf. zum Schluss ein ReplaceFile
aufrufen.

Falls es trotzdem hilft: Man kann die Pufferungsmechanismen von Windows
beim Schreiben einer Datei teilweise oder auch ganz umgehen. Siehe dazu
CreateFile-Dokumentation. Die interessanten Flags sind
FILE_FLAG_WRITE_THROUGH und FILE_FLAG_NO_BUFFERING. Wobei das erstere
angenehmer zu benutzen ist als letzteres:

https://msdn.microsoft.com/en-us/library/windows/desktop/cc644950(v=vs.85).aspx

Allerdings: "Not all hard disk hardware supports this write-through
capability" und der Hardware-Cache der Geräte lässt sich von den
Routinen wohl auch nicht beeindrucken.

Außerdem ist
https://msdn.microsoft.com/en-us/library/windows/desktop/aa364218(v=vs.85).aspx
in dem Zusammenhang noch lesenswert.

Eventueller Nachteil des ganzen Geschichte (je nachdem, was man bisher
für die Dateioperationen verwendet hat): Man muss mit dem Dateihandle
arbeiten, das Windows zurückgegeben hat. Also weiter mit WriteFile und
Co arbeiten.

Damit bekommt man dann mit etwas höherer Wahrscheinlichkeit
sichergestellt, dass die Daten auf der Festplatte gelandet sind. Das
alles schützt aber nicht davor, das mittendrin ein Verlust der
Betriebsspannung die Komprimierung unterbricht und ein
halb-komprimiertes Backup hinterlässt. Womit ich wieder bei Peters
Vorschlag wäre und es KISS umsetzen würde. :-)

Gruß, Steffen
Matthias Frey
2016-11-09 16:50:51 UTC
Permalink
Post by Steffen Christgau
Post by Peter Below
Änderung der Strategie. Kopiere die Datenbank, komprimiere die Kopie,
nicht das Orginal. Damit sollte eigentlich nichts mehr katastrophal
schief gehen können.
Sehe ich es richtig, dass dann das Orginal nie komprimiert ist?
Post by Steffen Christgau
ACK. Die andere Datei in-place zu ändern (so verstehe ich den OP),
erscheint mir auch nicht sinnvoll. Ggf. zum Schluss ein ReplaceFile
aufrufen.
Falls es trotzdem hilft: Man kann die Pufferungsmechanismen von Windows
beim Schreiben einer Datei teilweise oder auch ganz umgehen. Siehe dazu
CreateFile-Dokumentation. Die interessanten Flags sind
FILE_FLAG_WRITE_THROUGH und FILE_FLAG_NO_BUFFERING. Wobei das erstere
Nein, das hilft nicht. Wie ich schon schrieb handelt es sich um eine
Datenbank. Da habe ich keinen direkten Einfluss.
Post by Steffen Christgau
https://msdn.microsoft.com/en-us/library/windows/desktop/cc644950(v=vs.85).aspx
Allerdings: "Not all hard disk hardware supports this write-through
capability" und der Hardware-Cache der Geräte lässt sich von den
Routinen wohl auch nicht beeindrucken.
Das ist sicherlich richtig. Ich denke aber der Cache ist doch deutlich
kleiner als der von Windows.
Post by Steffen Christgau
Außerdem ist
https://msdn.microsoft.com/en-us/library/windows/desktop/aa364218(v=vs.85).aspx
in dem Zusammenhang noch lesenswert.
Habe sie nochmals gelesen.
Hm, wenn ich die Datenbankdatei nachdem sie von der Datenbank
geschlossen wurde nochmals selber mit FILE_FLAG_NO_BUFFERING
öffne - flushed Windows dann die Daten vorher?
Post by Steffen Christgau
...
Gruß, Steffen
Danke und Gruss
Matthias
Peter Below
2016-11-10 17:36:40 UTC
Permalink
Post by Matthias Frey
Post by Peter Below
Änderung der Strategie. Kopiere die Datenbank, komprimiere die
Kopie, nicht das Orginal. Damit sollte eigentlich nichts mehr
katastrophal schief gehen können.
Sehe ich es richtig, dass dann das Orginal nie komprimiert ist?
Sicher, aber warum sollte das ein Problem sein? Komprimiert kann man
die Datei eh nicht direkt verwenden. Wenn sie nicht mehr gebraucht wird
kannst Du sie also nach erfolgreichem Komprimieren der Kopie löschen,
genau wie die Kopie selbst.
--
Peter Below
TeamB
Matthias Frey
2016-11-11 13:17:42 UTC
Permalink
Post by Peter Below
Post by Matthias Frey
Post by Peter Below
Änderung der Strategie. Kopiere die Datenbank, komprimiere die
Kopie, nicht das Orginal. Damit sollte eigentlich nichts mehr
katastrophal schief gehen können.
Sehe ich es richtig, dass dann das Orginal nie komprimiert ist?
Sicher, aber warum sollte das ein Problem sein? Komprimiert kann man
die Datei eh nicht direkt verwenden. Wenn sie nicht mehr gebraucht wird
kannst Du sie also nach erfolgreichem Komprimieren der Kopie löschen,
genau wie die Kopie selbst.
Ah, da habe ich bislang wohl zu wenig (deutlich) geschrieben.

Doch die Datei kann man direkt verwende. Wie ich schon schrieb geht es
um eine Datenbankdatei. Die Datenbank übernimmt auch das Komprimieren
und kann mit der Datei dann auch weiterarbeiten.
Das Komprimieren mache nicht ich (wir) in dem Sinne dass wir die Datei
direkt bearbeiten. Das Komprimieren wird an die Datenbank deliegiert.
Es geht nicht um ein Zippen o.ä.

Matthias
Steffen Christgau
2016-11-10 20:55:12 UTC
Permalink
Post by Matthias Frey
Post by Steffen Christgau
Post by Peter Below
Änderung der Strategie. Kopiere die Datenbank, komprimiere die Kopie,
nicht das Orginal. Damit sollte eigentlich nichts mehr katastrophal
schief gehen können.
Sehe ich es richtig, dass dann das Orginal nie komprimiert ist?
Peter hat ja auch schon geantwortet. Ich kann ihm nur beipflichten. So
wie ich dich bisher verstanden habe, komprimierst du das existierende
Backup in place. Also werden die existierenden Daten an Ort und Stelle
(vmtl. blockweise) überschrieben. Das garantierte Schreiben der
komprimierten Daten auf die Platte bringt dir an dieser Stelle aber doch
eigentlich keinen Gewinn:

Wenn der entsprechende Komprimierungsprozess unverhofft abbricht (im
schlimmsten Fall durch "Strom weg"), dann ist der Inhalt der Backupdatei
ohnehin teilweise komprimiert (vorne), teilweise auch nicht (hinten -
unterstelle ich mal). Also auch kaputt. Durch die Pufferung von Windows
wird die Stelle zwischen diesen beiden Abschnitten aber nur verschoben.
Dein bisheriges Problem scheint gewesen zu sein, dass das Webschreiben
des Puffers durch "Strom weg" verhindert wird. Aber ob "Strom weg" nun
beim Schreiben des Puffers (durch Windows) oder beim Komprimieren und
ungepufferten Schrieben kommt läuft letztlich auf das gleiche hinaus:
Kaputtes Backup.

Eine vollständige Integrität des (komprimierten) Backups wirst du durch
das Flushen oder ungepuffertes Schreiben nie vollständig garantieren
können. Das in-place-Komprimieren sehe ich da eher noch als zusätzliches
Problem, weil du damit das Risiko der Beschädigung des unkomprimierten
Backups erhöhst.

Ich würde, wie schon von Peter und mir angedeutet, folgendes machen:

1. Backup wie bisher erstellen lassen
2. Backup komprimieren aber in andere Datei und ungepuffert schreiben
(letzteres sehe ich aber als Optimierung)
3. mit ReplaceFile unkomprimiertes Backup durch komprimierte Version
(fast) atomar überschreiben.
Post by Matthias Frey
Post by Steffen Christgau
Allerdings: "Not all hard disk hardware supports this write-through
capability" und der Hardware-Cache der Geräte lässt sich von den
Routinen wohl auch nicht beeindrucken.
Das ist sicherlich richtig. Ich denke aber der Cache ist doch deutlich
kleiner als der von Windows.
Ajo, aber einige MB sind auch nicht zu verachten.
Und außerdem: Wo das Zwischenspeichern erfolgt, ist dir letztlich auch
egal, wenn die betreffende Datei bei Stromausfall kaputt geht.
Post by Matthias Frey
Habe sie nochmals gelesen.
Hm, wenn ich die Datenbankdatei nachdem sie von der Datenbank
geschlossen wurde nochmals selber mit FILE_FLAG_NO_BUFFERING
öffne - flushed Windows dann die Daten vorher?
Davon würde ich nicht ausgehen. Faustregel: Wenn's nicht so dokumentiert
ist, sollte man sich nicht darauf verlassen.


Gruß, Steffen
Matthias Frey
2016-11-11 13:26:06 UTC
Permalink
Post by Steffen Christgau
Post by Matthias Frey
Post by Peter Below
Änderung der Strategie. Kopiere die Datenbank, komprimiere die Kopie,
nicht das Orginal. Damit sollte eigentlich nichts mehr katastrophal
schief gehen können.
Sehe ich es richtig, dass dann das Orginal nie komprimiert ist?
Peter hat ja auch schon geantwortet.
Ja, siehe dort.
Post by Steffen Christgau
Ich kann ihm nur beipflichten. So
wie ich dich bisher verstanden habe, komprimierst du das existierende
Backup in place.
Nein. derzeit wird aus der Datenbankdatei A ein Backup B erstellt. Das
Backup B ist eine seperate Datei die u.U. auch woanders liegt.
Post by Steffen Christgau
Also werden die existierenden Daten an Ort und Stelle
(vmtl. blockweise) überschrieben. Das garantierte Schreiben der
komprimierten Daten auf die Platte bringt dir an dieser Stelle aber doch
Komprimiert wird die existierende Datenbankdatei A inplace.

Durch das Flushen will ich ja nur erreichen, dass das Backup sicher
auf der Platte ist.

Ich habe zwei Dateien und wenigstens eine sollte ganz bleiben.

Jetzt klarer?

Gruss
Matthias
Marc Santhoff
2016-11-11 15:33:31 UTC
Permalink
Post by Matthias Frey
Ich habe zwei Dateien und wenigstens eine sollte ganz bleiben.
Stell eine USV mit ausreichend großem Akku neben den Rechner.

CNR,
Marc

Achim Kalwa
2016-11-01 14:56:17 UTC
Permalink
Moin,
Post by Matthias Frey
wie kann ich es erzwingen (so lange warten) bis Windows alle
Daten einer Datei auf Festplatte geschreiben hat?
[...]
Post by Matthias Frey
Es wird von einer Datenbank ein Backup erzeugt und danach die
Datenbank komprimiert. Wenn man beim Komprimieren den Stecker zieht
ist sowohl das Backup als auch die zu komprimierende korrupt.
Mein Vermutung ist, dass noch nicht alle Daten vom Backup auf
Festplatte sind.
Es gibt ein "Sync"-Tool von Sysinternals:
https://technet.microsoft.com/de-de/sysinternals/bb897438.aspx

Leider ohne Source-Code, sonst könnte man nachsehen was Mark Russinovich
da so veranstaltet.

Aber möglicherweise kannst Du zwischen Backup und Kompression mit
CreateProcess() das sync.exe aufrufen.

HTH
Achim
=?utf-8?Q?J=F6rg_Achtenhagen?=
2016-11-02 14:56:10 UTC
Permalink
Matthias Frey wrote:

vielleicht ist das was.
https://www.delphitools.info/2013/11/29/flush-windows-file-cache/


--
Loading...