2013-03-15 2 views
14

Я работаю над программным обеспечением, которое хранит файлы в файловой системе, а также ссылки на эти файлы в базе данных. Таким образом, запрос загруженных файлов может быть выполнен в базе данных без необходимости доступа к файловой системе. Из того, что я читал в других сообщениях, большинство людей говорит, что лучше использовать файловую систему для хранения файлов, а не хранить двоичные данные непосредственно в базе данных в виде BLOB.Синхронизация моей базы данных и файловой системы

Итак, теперь я пытаюсь понять, как наилучшим образом установить это, так что обе базы данных файловой системы остаются в синхронизации, и я не получаю ссылки на файлы, которые не существуют, или файлы, принимающие в файловой системе, на которые не ссылаются. Вот несколько вариантов, которые я рассматриваю.

Вариант 1: Добавить Ссылка Файл Первый

//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); 

Этот вариант будет проблематично, так как ссылка на файл добавляется до фактического файла, так как другой пользователь может в конечном итоге пытается загрузить файл перед он фактически хранится в системе. Хотя, поскольку ссылка на файл создается до начала, значение первичного ключа может быть использовано при хранении файла.

Вариант 2: Сохранение файлов Первый

//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"); 

Этот вариант лучше, но сделает возможным для кого-то, чтобы загрузить файл в системе, которая никогда не ссылается. Хотя это можно было бы исправить с помощью функции «Очистить» или «CleanUpFileSystem», которая удаляет любые файлы без ссылок. Этот параметр также не позволит сохранить файл с использованием значения первичного ключа из базы данных.

Вариант 3: В ожидании статуса

//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"); 

Эта опция позволяет первичный ключ должен быть создан до того, как файл будет загружен, но и не позволяет другим пользователям получить ссылку на файл, прежде чем он будет загружен. Хотя, возможно, файл никогда не будет загружен, а ссылка на файл будет приостановлена. Тем не менее, было бы довольно тривиально очищать ожидающие ссылки из базы данных.

Я склоняюсь к варианту 2, потому что это просто, и мне не нужно беспокоиться о том, что пользователи пытаются запросить файлы до их загрузки. Хранение дешево, так что это не конец света, если я получаю некоторые ненужные файлы, занимающие место. Но это также кажется общей проблемой, и я хотел бы услышать, как другие решили это или другие соображения, которые я должен делать.

+1

Очень умный вопрос. Многие люди никогда не думают о согласованности между своими разрозненными хранилищами данных. – usr

ответ

2

Я хочу предложить другой вариант. Сделайте имя файла всегда равным хешу его содержимого. Тогда вы можете смело писать любой контент во все времена при условии, что вы сделаете это, прежде чем добавлять ссылку на него в другом месте.

Поскольку содержимое никогда не меняется, никогда не возникает проблема синхронизации.

Это дает вам дедупликацию бесплатно. Однако удаление становится сложнее. Я рекомендую ночной сбор мусора.

+0

Не могли бы вы уточнить? Я бы получил хэш-код из файла и использовал этот код, чтобы определить, как файл хранится в файловой системе? Затем база данных хранит ссылку на файл как хэш-код, а не имя файла? Разве я не должен был бы иметь дело с потенциалом столкновения? –

+1

Если вы используете стандартную криптографическую хеш-функцию, вам вообще не придется иметь дело с коллизиями (если бы вы выиграли лотерею уже 10 раз). Старый алгоритм MD5 достаточно хорош, построен повсюду и один из самых быстрых алгоритмов; Сначала вы определяете хэш, затем извлекаете из него имя файла («tohex (hashbytes) +« .dat ») и записываете его. Затем вы храните хеш (или имя файла) в базе данных. Готово. – usr

0

Что такое реальное использование базы данных? Если это всего лишь список файлов, я не думаю, что вам это нужно вообще, и это не избавляет вас от синхронности.

Если вы уверены, что вам это нужно, варианты 1 и 2 полностью идентичны с технической точки зрения - 2 ресурса могут быть не синхронизированы, и вам нужен регулярный процесс для их консолидации. Поэтому здесь вы должны выбрать наиболее подходящие для приложения варианты.

Вариант 3 не имеет никакого преимущества, но использует больше ресурсов.

Обратите внимание, что использование хешей, как было предложено usr, несет теоретический риск столкновения. И вам также понадобится периодический процесс консолидации, как и для вариантов 1 и 2.

Другие вопросы касательно того, как вы работаете с частичными загрузками и загрузками. Здесь вариант 2 может быть полезен, но вы также можете использовать второй файл «флаг», который создается до начала загрузки, и удаляется при завершении загрузки. Это поможет вам определить, какие загрузки были прерваны.

+1

Существует другая небиная информация, хранящаяся в базе данных, которая отсылается к файлам, так что да, мне это нужно. –

0

Чтобы устранить недостаток, который вы упомянули о option 1 Я использую что-то вроде fileStorage.FileExists("newfile.txt"); и отфильтровываю результат, для которого он возвращает отрицательный.

В Python жаргоне:

import os 
op = os.path 

filter(lambda ref: op.exists(ref.path()), database.AllRefs()) 
Смежные вопросы