2013-03-15 19 views
14

Ich arbeite an einer Software, die Dateien in einem Dateisystem speichert, sowie Verweise auf diese Dateien in einer Datenbank. Das Abfragen der hochgeladenen Dateien kann somit in der Datenbank erfolgen, ohne auf das Dateisystem zugreifen zu müssen. Nach dem, was ich in anderen Beiträgen gelesen habe, sagen die meisten Leute, dass es besser ist, ein Dateisystem für die Dateispeicherung zu verwenden, anstatt Binärdaten direkt in einer Datenbank als BLOB zu speichern.Halten Sie meine Datenbank und Dateisystem synchron

Also jetzt versuche ich zu verstehen, die beste Möglichkeit, dies einzurichten, so dass sowohl die Datenbank ein Dateisystem synchron bleiben und ich nicht mit Verweisen auf Dateien, die nicht existieren, oder Dateien zu beenden Speicherplatz im Dateisystem, die nicht referenziert sind. Hier sind ein paar Optionen, die ich in Betracht ziehe.

Option 1: Datei hinzufügen Referenz Erste

//Adds a reference to a file in the database 
database.AddFileRef("newfile.txt"); 

//Stores the file in the file system 
fileStorage.SaveFile("newfile.txt",dataStream); 

Diese Option problematisch wäre, da der Verweis auf die Datei vor der eigentlichen Datei hinzugefügt wird, so kann ein anderer Benutzer eine Datei zum Download am Ende versucht, vor Es ist tatsächlich im System gespeichert. Obwohl der Verweis auf die Datei vor der Hand erstellt wird, kann der Primärschlüsselwert beim Speichern der Datei verwendet werden.

Option 2: Shop erste Datei

//Stores the file 
fileStorage.SaveFile("newfile.txt",dataStream); 

//Adds a reference to the file in the database 
//fails if reference file does not existing in file system 
database.AddFileRef("newfile.txt"); 

Diese Option ist besser, aber wäre es möglich, dass jemand eine Datei in das System zu laden, die nie referenziert wird. Dies könnte jedoch mit einer "Purge" - oder "CleanUpFileSystem" -Funktion behoben werden, die nicht referenzierte Dateien löscht. Diese Option würde auch nicht zulassen, dass die Datei mit dem Primärschlüsselwert aus der Datenbank gespeichert wird.

Option 3: Pending-Status

//Adds a pending file reference to database 
//pending files would be ignored by others 
database.AddFileRef("newfile.txt"); 

//Stores the file, fails if there is no 
//matching pending file reference in the database 
fileStorage.SaveFile("newfile.txt",dataStream); database 

//marks the file reference as committed after file is uploaded 
database.CommitFileRef("newfile.txt"); 

Mit dieser Option kann der Primärschlüssel erstellt werden, bevor die Datei hochgeladen wird, sondern verhindert auch andere Benutzer einen Verweis auf eine Datei zu erhalten, bevor es hochgeladen wird. Es wäre jedoch möglich, dass eine Datei niemals hochgeladen wird und ein Dateiverweis aussteht. Es wäre jedoch auch ziemlich einfach, ausstehende Verweise aus der Datenbank zu entfernen.

Ich neige zu Option 2, weil es einfach ist, und ich muss mich nicht darum kümmern, dass Benutzer versuchen, Dateien anzufordern, bevor sie hochgeladen werden. Speicher ist billig, also ist es nicht das Ende der Welt, wenn ich am Ende einige nicht referenzierte Dateien benötige. Aber das scheint auch ein allgemeines Problem zu sein, und ich würde gerne hören, wie andere es gelöst haben oder andere Überlegungen, die ich treffen sollte.

+1

Sehr intelligente Frage. Viele Menschen denken nie über Konsistenz zwischen ihren unterschiedlichen Datenspeicher nach. – usr

Antwort

2

Ich möchte eine andere Option vorschlagen. Mache den Dateinamen immer gleich dem Hash seines Inhalts. Dann können Sie sicher beliebigen Inhalt schreiben vorausgesetzt, dass Sie es tun, bevor Sie eine Referenz an anderer Stelle hinzufügen.

Da sich der Inhalt niemals ändert, gibt es nie ein Synchronisierungsproblem.

Dies gibt Ihnen Deduplizierung kostenlos. Die Löschung wird jedoch schwieriger. Ich empfehle eine nächtliche Müllsammlung.

+0

Könnten Sie näher ausführen? Ich würde den Hash-Code aus der Datei abrufen und diesen Code verwenden, um zu bestimmen, wie die Datei im Dateisystem gespeichert wird. Dann die Datenbank beim Speichern der Referenz auf die Datei als Hash-Code und nicht den Dateinamen? Muss ich mich dann nicht mit Kollisionspotentialen auseinandersetzen? –

+1

Wenn Sie einen Standard verschlüsselten Hash-Funktion verwenden, müssen Sie sich nicht mit Kollisionen überhaupt beschäftigen (wenn Sie haben Sie bereits in der Lotterie 10 Mal gewonnen habe). Der alte MD5-Algorithmus ist gut genug, überall eingebaut und einer der schnellsten Algorithmen. Sie würden zunächst die Hash bestimmen, dann einen Dateinamen von ihm ('tohex (hashbytes) +„.dat“') ableiten und es schreiben. Dann speichern Sie den Hash (oder den Dateinamen) in der Datenbank. Erledigt. – usr

0

Wie wird die Datenbank wirklich genutzt? Wenn es nur eine Liste von Dateien ist, glaube ich nicht, dass Sie sie überhaupt brauchen, und wenn Sie sie nicht haben, ersparen Sie Ihnen den Aufwand der Synchronisierung.

Wenn Sie überzeugt sind, dass Sie es brauchen, dann sind die Optionen 1 und 2 aus technischer Sicht völlig identisch - die zwei Ressourcen können nicht synchron sein und Sie brauchen einen regelmäßigen Prozess, um sie wieder zu konsolidieren. Hier sollten Sie die Optionen auswählen, die am besten zu der Anwendung passen.

Option 3 hat keinen Vorteil auch immer, aber mehr Ressourcen verwendet.

Beachten Sie, dass unter Verwendung von Hashes, wie usr vorgeschlagen, ein theoretisches Risiko einer Kollision trägt. Und Sie haben auch einen periodischen Konsolidierungsprozess benötigen, wie für die Optionen 1 und 2.

Eines andere Fragen sind, wie Sie mit Teil-Up- und Uploads in Fortschritten befassen. Hier könnte Option 2 nützlich sein, aber Sie können auch eine zweite "Flag" -Datei verwenden, die vor dem Hochladen erstellt und nach dem Hochladen gelöscht wird. Dies würde Ihnen helfen festzustellen, welche Uploads abgebrochen wurden.

+1

Es gibt andere nicht-binäre Informationen in der Datenbank gespeichert, auf die Dateien releated ist, also ja ich es brauche. –

0

Um den von Ihnen erwähnten Nachteil von Option 1 zu beheben, verwende ich etwas wie fileStorage.FileExists("newfile.txt"); und filtere das Ergebnis heraus, für das es ein Negativ zurückgibt.

In Python Kauderwelsch:

import os 
op = os.path 

filter(lambda ref: op.exists(ref.path()), database.AllRefs()) 
Verwandte Themen