2012-08-18 9 views
1

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

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

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

Как вы это сделаете в Python?

d = FileWriter.open(['file1', 'file2'], 'wb+') 
d.write('add hello world to files') 
d.close() 

Убедитесь, что d.write является атомарным или, по крайней мере, откатом к исходным файлам, если он не увенчался успехом.

+0

does not file-locking (который реализуется почти каждой файловой системой) обеспечивает атомные операции? 'd = FileWriter.open (['file1', 'file2'], 'wb +')' Я думаю, что этот оператор поместит блокировку записи в этот файл. Единственное, что вы должны убедиться, что другой процесс проверяет статус блокировки файла. –

+0

Я только что сделал FileWriter. Наивно он последовательно записывался в два файла. Если что-то перерывается между вами, вам не повезло. Представьте, что эти файлы представляют собой индекс поисковой системы. Поскольку вы только писали один файл, а не другой, у вас теперь есть поврежденный индекс. –

+0

a ok, я пропустил бит. Вам нужна атомная операция над всеми файлами. –

ответ

0

Вы можете попробовать flock для достижения своей цели. Это может быть достигнуто в python с fcntl.flock. Обратите внимание, что это всего лишь рекомендация. Чтобы действительно гарантировать, что вы хотите, вы должны попробовать и использовать базу данных или файловую систему/ядро, которая поддерживает строгую блокировку.

2

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

  1. Напишите временным файлам: file1 ~, file2 ~ и специальному успеху файла ~ (необходимо записать в первую очередь).
  2. После успешной записи удалите файл с успехом ~.
  3. Переименуйте файлы в файл1 и файл2.

Если что-то сломается:

  1. Проверьте, если успех ~ существует.
  2. Если есть, не беспокойтесь. Откат был выполнен неявно, потому что файлы не обновлялись (без переименований).
  3. Если успех ~ не существует, все пошло после записи и во время переименования. В этом случае восстановление так же просто, как переименование filex ~ в filex.
+1

Зачем проходить через все эти проблемы, когда базы данных поставляются с этим встроенным? –

+0

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

+0

Плюс, это немного напоминает ответ на вопрос о гладильных костюмах с предложением просто носить синие джинсы. Это не дружелюбно, и, конечно, не полезно. – yeoman

1

Ваше требование в его текущем утверждении является настолько общим, что единственным правдоподобным ответом является то, что поддержка уровня ОС необходима, и это даже не вопрос, связанный с Python. Посмотрите, что говорится о Транзакционные файловые системы, например here и here. Небольшая выдержка из предложенных решений:

Обеспечение согласованности действий нескольких операций с файловой системой затруднено, если не невозможно, без транзакций файловой системы. Блокировка файлов может использоваться как механизм контроля параллелизма для отдельных файлов, но обычно не защищает структуру каталогов или метаданные файлов. Например, блокировка файлов не может препятствовать условиям гонки TOCTTOU на символических ссылках. Блокировка файлов также не может автоматически откатить неудачную операцию, такую ​​как обновление программного обеспечения; это требует атомарности.

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

Кстати, если вы думаете о файловой системе, так как компоненты вашей архитектуры необходимо получить доступ к файлам , вы думали о FUSE как способ построения файловой системы, как фасад поверх обычной базы данных ? Использование python-fuse - легкий ветерок.

+0

На самом деле, в моем случае, кажется, что механизма ремонта будет достаточно. Попытайтесь писать в эти файлы, и если что-то пошло не так, исправьте их на более позднем этапе. –

0

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

Они полностью оптимизированы для обеспечения согласованности и производительности.

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

Вы можете, однако, записывать номера транзакций с каждой записью в несколько файлов.

И сделать очевидным, была ли запись полной, например. с блоками стиля xml или json с маркерами начала и конца, например < элемент > ... </элемент > или {...}, & c.

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

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

Использование sync/fsync также делает транзакционные транзакции возможными, то есть гарантируя, что все до сих пор было написано, по крайней мере, с точки зрения файловой системы.

Возможно, ваша система хранения может потерять последнюю запись из-за отключения электроэнергии, будь то жесткий диск или SSD с внутренним кешем, NAS, & c. Гарантии, предоставляемые этими системами, могут сильно различаться, что является проблемой для рассмотрения всеми подходами, независимо от того, используете ли вы файловую систему или традиционную СУБД для хранения.

Использование ИБП, безусловно, отличное дополнение, если вы пишете на встроенный жесткий диск или SSD, особенно если вы закрываете свою систему контролируемым образом, как только USP сигнализирует, что пришло время сделать это^^

Смежные вопросы