Файл + безопасность транзакций базы данных - PullRequest
3 голосов
/ 24 июня 2010

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

Когда пользователь хочет удалить файл из системы, я хочу обеспечить некоторую безопасность транзакций, то есть, если при удалении файла что-то пойдет не так, запись не будет удалена, и если по какой-либо причине сервер базы данных умрет файл не будет удален. Любое событие произойдет очень маловероятно, но если есть хоть малейшая вероятность возникновения проблемы, я хочу предотвратить ее.

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

О, вот вам и кикер - мой веб-хостинг поддерживает только таблицы MyISAM, поэтому для меня нет транзакций MySQL.

Если это имеет значение, я использую PHP в качестве языка сценариев на стороне сервера.

Ответы [ 3 ]

3 голосов
/ 24 июня 2010

Независимо от того, был ли файл «удален» из БД с помощью ОБНОВЛЕНИЯ или УДАЛЕНИЯ строки, проблема одна и та же - операции базы данных + файла не являются атомарными.Ни ОБНОВЛЕНИЕ, ни УДАЛЕНИЕ не являются более безопасными, чем другие, они обе являются транзакциями в базе данных, тогда как файловая операция - нет.

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

В большинстве случаев база данных является лучшим представлением Истины.

Воттаблица истинности:

File Exists -- DB Record exists -- Truth
    Yes             No             File does not exist
    Yes             Yes            File does exist
    No              Yes            File does exist, but its in error.
    No              No             File does not exist

В оперативном порядке, вот как это работает.

Чтобы создать файл, скопируйте файл в конечный пункт назначения, затем сделайте запись в БД.

Если копирование файла завершится неудачно, вы не обновите БД.Если копирование файла выполнено успешно, но БД не обновлена, файл «не существует», поэтому вернитесь к первому шагу.Если копирование файла выполнено успешно, а обновление базы данных выполнено успешно, то все в порядке: A-OK

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

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

Транзакции с БД помогают сохранять честность.

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

3 голосов
/ 24 июня 2010

В этих обстоятельствах, я думаю, я бы использовал логический механизм удаления, где запись помечается как удаленная, даже если она все еще присутствует в базе данных, а файл все еще присутствует в файловой системе. Я мог бы переместить файл в новое место, когда он логически удален (например, «корзина»), и обновить запись новым местоположением, а также маркером «логически удаленного».

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

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

CREATE VIEW MainTable(...) AS
    SELECT * FROM RenamedTable WHERE DeleteFlag = 'N';

Даже переход на компанию, предоставляющую транзакции MySQL, не очень помогает. Вам понадобится менеджер транзакций, который может запускать протоколы двухфазной фиксации между файловой системой и СУБД, что нетривиально.

2 голосов
/ 24 июня 2010

Вы можете создать столбец состояния (или столбец «is_active») в таблице файлов с двумя значениями: 0 = активный, 1 = удаленный.

  • Когда пользователь удаляет файл, толькополе состояния изменяется, и файл остается неизменным.
  • Когда пользователь просматривает файлы, отображаются только файлы с состоянием = 0.
  • Администратор может просматривать / удалять файлы с состоянием = 1.
...