fflush, fsync und sync vs. Speicherschichten

Lesezeit: 8 Minuten

Benutzeravatar von Antonino
Antonino

Ich weiß, dass es bereits ähnliche Fragen gibt, und ich habe sie mir angesehen, aber ich konnte keine eindeutige Antwort auf meine Frage finden. Ich habe gerade online über diese Funktionen und ihre Beziehung zu Speicherschichten recherchiert. Besonders dieses fand ich schön Artikel das gab mir einen guten einblick über speicherschichten

Speicherschichten

Es scheint, dass fflush() verschiebt Daten aus der Anwendung in den Kernel-Dateisystempuffer und es ist in Ordnung, in diesem Punkt scheinen sich alle einig zu sein. Das einzige, was mich verwirrte, war, dass sie im selben Artikel von einem Write-Back-Cache ausgingen, der das sagte fsync() “Die Daten werden in der stabilen Speicherschicht gespeichert” und nachdem sie hinzugefügt haben, dass “der Speicher die Daten selbst in einem Write-Back-Cache speichern kann, also fsync() wird weiterhin für Dateien benötigt, die mit O_DIRECT geöffnet wurden, um die Daten in einem stabilen Speicher zu speichern.

Lesen Sie hier und dort es scheint, als ob die Wahrheit so ist fsync() und sync() Lassen Sie die Daten in das Speichergerät gelangen, aber wenn dieses Caching-Schichten hat, werden sie nur hierher verschoben, nicht sofort in den dauerhaften Speicher, und Daten können sogar bei einem Stromausfall verloren gehen. Es sei denn, wir haben ein Dateisystem mit aktivierten Barrieren und dann “sync()/fsync() und einige andere Operationen bewirken, dass die entsprechenden CACHE FLUSH (ATA)- oder SYNCHRONIZE CACHE (SCSI)-Befehle an das Gerät gesendet werden. [from your website answer]

Fragen:

  1. Wenn sich die zu aktualisierenden Daten bereits in den Kernelpuffern befinden und mein Gerät eine flüchtige Cache-Schicht im Write-Back-Modus hat, ist es wahr, wie im Artikel gesagt, dass Operationen wie fsync() [and sync() I suppose] Daten mit der stabilen Speicherschicht synchronisieren und die flüchtige überspringen? Ich denke, das passiert mit einem Write-Through-Cache, nicht mit einem Write-Back-Cache. Nach dem, was ich gelesen habe, habe ich das mit einem Write-Back-Cache verstanden fsync() können einfach Daten an das Gerät senden, das sie in den flüchtigen Cache legt, und sie gelangen erst danach in den permanenten Speicher

  2. Ich habe das gelesen fsync() arbeitet mit einem Dateideskriptor und dann mit einer einzelnen Datei, während sync() bewirkt eine vollständige Bereitstellung für die Puffer, sodass sie für alle zu aktualisierenden Daten gilt. Und daraus Seite auch dass fsync() wartet auf das Ende des Schreibens auf die Platte während sync() wartet nicht auf das Ende des eigentlichen Schreibens auf die Platte. Gibt es weitere Unterschiede im Zusammenhang mit Speicherdatenübertragungen zwischen den beiden?

Danke an diejenigen, die versuchen zu helfen

  • Dieses Video zu PostgreSQL vs. fsync() enthält viele Informationen zu fsync(). Es könnte helfen, einen Teil des Puzzles zu vervollständigen: fosdem.org/2019/schedule/event/postgresql_fsync

    – Jorge Issa

    9. März 2019 um 20:01 Uhr

Benutzeravatar von gstukelj
gstukelj

1. Wie Sie aus Ihrer Recherche richtig geschlossen haben fflush synchronisiert die Userspace gepuffert Daten zu Kernel-Ebene Cache (da es mit funktioniert FILE Objekte, die sich auf Benutzerebene befinden und für den Kernel unsichtbar sind), während fsync oder sync (Arbeite direkt mit Dateideskriptoren) im Kernel zwischengespeicherte Daten mit dem Gerät synchronisieren. Letzteres hat jedoch keine Garantie, dass die Daten tatsächlich auf das Speichergerät geschrieben wurden – da diese normalerweise auch über eigene Caches verfügen. Ich würde erwarten, dass das gleiche gilt für msync mit angerufen MS_SYNC Flagge auch.

Entsprechend finde ich die Unterscheidung zwischen synchronisiert und synchron Operationen sehr nützlich, wenn man über das Thema spricht. Hier ist wie Robert Liebe bringt es auf den Punkt:

Eine synchrone Schreiboperation kehrt erst zurück, wenn die geschriebenen Daten – zumindest – im Puffer-Cache des Kernels gespeichert sind. […] Ein synchronisierter Betrieb ist restriktiver und sicherer als ein reiner synchroner Betrieb. Ein synchronisierter Schreibvorgang löscht die Daten auf die Festplatte und stellt sicher, dass die Daten auf der Festplatte immer mit den entsprechenden Kernel-Puffer synchronisiert sind.

In diesem Sinne können Sie anrufen open mit O_SYNC Flag (zusammen mit einem anderen Flag, das die Datei mit einer Schreibberechtigung öffnet), um synchronisierte Schreibvorgänge zu erzwingen. Auch hier, wie Sie richtig angenommen haben, funktioniert dies nur mit WRITE THROUGH Disk-Caching-Richtlinie, die sich effektiv auf deaktivieren Disk-Caching.

In dieser Antwort erfahren Sie, wie Sie das Festplatten-Caching unter Linux deaktivieren. Unbedingt auch prüfen Diese Internetseite die neben ATA-basierten Geräten auch SCSI-basierte Geräte abdeckt (um mehr über verschiedene Festplattentypen zu erfahren, siehe this Seite auf Microsoft SQL Server 2005letzte Aktualisierung: 19.04.2018).

Apropos, es ist sehr aufschlussreich zu lesen, wie das Thema behandelt wird Windows-Maschinen:

Um eine Datei für ungepufferte E/A zu öffnen, rufen Sie die CreateFile-Funktion mit den Flags FILE_FLAG_NO_BUFFERING und FILE_FLAG_WRITE_THROUGH auf. Dadurch wird verhindert, dass der Dateiinhalt zwischengespeichert wird, und die Metadaten werden bei jedem Schreibvorgang auf die Festplatte geleert. Weitere Informationen finden Sie unter CreateFile.

Anscheinend geht das so Microsoft SQL-Server 2005 Familie stellt die Datenintegrität sicher:

Alle Versionen von SQL Server öffnen die Protokoll- und Datendateien mit der Win32-CreateFile-Funktion. Das dwFlagsAndAttributes-Member enthält die FILE_FLAG_WRITE_THROUGH-Option, wenn es von SQL Server geöffnet wird. […]
Diese Option weist das System an, durch jeden Zwischencache zu schreiben und direkt auf die Festplatte zu gehen. Das System kann immer noch Schreibvorgänge zwischenspeichern, aber nicht träge löschen.

Ich sage, dass dies insbesondere deshalb informativ ist Blogbeitrag von 2012 zeigt, dass einige SATA-Festplatten ignorieren Die FILE_FLAG_WRITE_THROUGH! Ich weiß nicht, wie der aktuelle Stand der Dinge ist, aber es scheint, dass Sie Folgendes tun müssen, um sicherzustellen, dass das Schreiben auf eine Festplatte wirklich synchronisiert ist:

  1. Deaktivieren Sie das Festplatten-Caching mit Ihren Gerätetreibern.
  2. Stellen Sie sicher, dass das spezifische Gerät, das Sie verwenden, die Write-Through/No-Caching-Richtlinie unterstützt.

Wenn Sie jedoch nach einer Garantie für die Datenintegrität suchen, können Sie einfach eine Festplatte mit einer eigenen batteriebasierten Stromversorgung kaufen, die über Kondensatoren hinausgeht (was normalerweise nur ausreicht, um die laufenden Schreibvorgänge abzuschließen). Wie im Fazit des oben erwähnten Blogartikels formuliert:

Unterm Strich sollten Sie Datenträger der Enterprise-Klasse für Ihre Daten- und Transaktionsprotokolldateien verwenden. […] Tatsächlich ist die Situation nicht so dramatisch, wie es scheint. Viele RAID-Controller verfügen über einen batteriegestützten Cache und müssen die Write-Through-Anforderung nicht erfüllen.

2. Um die zweite Frage (teilweise) zu beantworten, stammt diese aus den Manpages SYNC(2):

Gemäß der Standardspezifikation (z. B. POSIX.1-2001) plant sync() die Schreibvorgänge, kann jedoch zurückkehren, bevor das eigentliche Schreiben abgeschlossen ist. Seit Version 1.3.20 wartet Linux jedoch tatsächlich. (Dies garantiert immer noch keine Datenintegrität: Moderne Festplatten haben große Caches.)

Dies würde das implizieren fsync und sync funktionieren anders, beachten Sie jedoch, dass sie beide implementiert sind unistd.h was auf eine gewisse Konsistenz zwischen ihnen hindeutet. Allerdings würde ich folgen Robert Liebe wer empfiehlt die Verwendung nicht sync syscall, wenn Sie Ihren eigenen Code schreiben.

Die einzige wirkliche Verwendung für sync() liegt in der Implementierung des Sync-Dienstprogramms. Anwendungen sollten fsync() und fdatasync() verwenden, um nur die Daten der erforderlichen Dateideskriptoren auf Platte zu übertragen. Beachten Sie, dass sync() auf einem ausgelasteten System mehrere Minuten oder länger dauern kann.

“Ich habe keine Lösung, aber ich bewundere das Problem auf jeden Fall.”

Von allem, was ich aus Ihren guten Referenzen gelesen habe, ist, dass es keinen Standard gibt. Der Standard endet irgendwo im Kernel. Der Kernel steuert den Gerätetreiber und der Gerätetreiber (möglicherweise vom Festplattenhersteller geliefert) steuert die Festplatte über eine API (das Gerät hat einen kleinen Computer an Bord). Der Hersteller hat möglicherweise Kondensatoren/Batterien mit gerade genug Leistung hinzugefügt, um seine Gerätepuffer im Falle eines Stromausfalls zu leeren, oder er hat dies möglicherweise nicht getan. Das Gerät kann eine Sync-Funktion bereitstellen, aber ob dies die Gerätepuffer wirklich synchronisiert (leert), ist nicht bekannt (geräteabhängig). Wenn Sie also kein Gerät gemäß Ihren Spezifikationen auswählen und installieren (und diese Spezifikationen überprüfen), sind Sie sich nie sicher.

Das ist ein faires Problem. Auch nach der Behandlung von Fehlerzuständen sind Sie nicht sicher, ob Daten in Ihrem Speicher vorhanden sind.

Manpage von fsync erklärt dieses Problem deutlich!! 🙂 Für Anwendungen, die strengere Garantien für die Integrität ihrer Daten erfordern, bietet Mac OS X die F_FULLFSYNC-Funktion. Der fcntl F_FULLFSYNC fordert das Laufwerk auf, alle gepufferten Daten in den permanenten Speicher zu spülen.

Anwendungen wie Datenbanken, die eine strenge Schreibreihenfolge erfordern, sollten F_FULLFSYNC verwenden, um sicherzustellen, dass ihre Daten in der erwarteten Reihenfolge geschrieben werden. Weitere Einzelheiten finden Sie unter fcntl(2).

Ja, fflush() stellt sicher, dass die Daten den Prozessspeicherplatz verlassen, aber sie können sich in schmutzigen Seiten des RAM befinden und auf das Zurückschreiben warten. Dies ist sicher gegen App-Abbruch, aber nicht gegen Systemabsturz oder Stromausfall. Selbst wenn die Stromversorgung gesichert ist, könnte das System aufgrund einer Software-Schwachstelle abstürzen! Wie in anderen Antworten/Kommentaren erwähnt, ist das Abrufen der Daten von schmutzigen Seiten, die magnetisch auf die Festplatte geschrieben werden oder was auch immer SSD tun, und nicht in einem flüchtigen Puffer im Festplattencontroller oder Laufwerk stecken, eine Kombination aus den richtigen Aufrufen oder offenen Optionen und den richtigen Controllern und Geräte! Aufrufe geben Ihnen mehr Kontrolle über den Overhead, da am Ende einer Transaktion mehr in großen Mengen geschrieben wird.

RDBMS müssen sich beispielsweise nicht nur um die Datenbankdateien kümmern, sondern noch mehr um die Protokolldateien, die eine Wiederherstellung ermöglichen, sowohl nach einem Festplattenverlust als auch bei jedem RDBMS-Neustart nach einem Absturz. Tatsächlich werden einige im Protokoll möglicherweise stärker synchronisiert als in der Datenbank, um die Geschwindigkeit zu erhalten, da die Wiederherstellung kein häufiger und normalerweise nicht langer Prozess ist. Dinge, die von Transaktionen in das Protokoll geschrieben werden, sind garantiert wiederherstellbar, wenn das Protokoll intakt ist.

1437610cookie-checkfflush, fsync und sync vs. Speicherschichten

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy