Существуют ли какие-либо гарантии сохранности при использовании файлов с отображенной памятью или простого Stream.Write - PullRequest
0 голосов
/ 16 января 2019

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

  1. У меня много маленьких файлов (например, запись на диск каждую минуту илитак) - в случае сбоя я теряю только последний файл.Однако производительность будет хуже.
  2. У большого файла (например, открытие, изменение, закрытие) - наилучшая производительность последовательного чтения после этого, но в случае сбоя я могу получитьповрежденный файл.

Поэтому мой вопрос, в частности:

Если я выберу вариант большого файла и открою его как файл с отображенной памятью (или используя Stream.Position и Stream.Write), и есть потеря мощности, есть ли гарантии того, что может случиться с файлом?

  1. Можно ли потерять весь большой файл или просто завершитьс поврежденными данными в середине?

  2. Обеспечивает ли NTFS, что блок определенного размера (4 КБ) всегда записывается полностью?

  3. Результат лучше / хуже на Unix / ext4?

Я бы хотел избежать использования NTFS TxF, поскольку Microsoft уже упоминала, что планирует удалить его.Я использую C #, но язык, вероятно, не имеет значения.

(дополнительное уточнение)

Кажется, что должна быть определенная гарантия, потому что - если я неЯ ошибаюсь - если бы было возможно потерять весь файл (или получить действительно странное повреждение) при записи в него, то ни одна из существующих БД не была бы ACID, если только они 1) не используют TxF или 2) не делают копию всего файла допишу?Я не думаю, что журнал поможет вам, если вы потеряете части файла, который вы даже не планировали трогать.

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Вы можете позвонить FlushViewOfFile, который инициирует грязную запись страницы, а затем FlushFileBuffers, который согласно этой статье , гарантирует, что страницы были написаны.

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

Полагаю, можно открыть файл отображения памяти с помощью FILE_FLAG_NO_BUFFERING и FILE_FLAG_WRITE_THROUGH, но это снизит вашу пропускную способность. Я не делаю этого Я открываю отображенные в память файлы для асинхронного ввода-вывода, позволяя ОС оптимизировать пропускную способность за счет собственной реализации портов завершения асинхронного ввода-вывода. Это самая быстрая пропускная способность. Я могу терпеть потенциальную потерю, и смягчил соответственно. Мои отображенные в память данные представляют собой данные резервного копирования файлов ... и, если я обнаружу потерю, я смогу обнаружить и сделать резервную копию потерянных данных после устранения аппаратной ошибки.

Очевидно, что файловая система должна быть достаточно надежной, чтобы работать с приложением базы данных, но я не знаю ни одного поставщика, который бы предлагал вам резервное копирование. Плохие вещи произойдут . План потери. Одна вещь, которую я делаю, это то, что я никогда не пишу в середину данных. Мои данные являются неизменяемыми и версионными, и каждый файл «данных» ограничен 2 ГБ, но каждое приложение использует разные стратегии.

0 голосов
/ 18 января 2019

Файловая система NTFS (и ext3-4) использует журнал транзакций для управления изменениями. Каждое изменение сохраняется в журнале, а затем сам журнал используется для эффективного изменения. За исключением катастрофических сбоев диска, файловая система спроектирована так, чтобы она была согласованной в своих своих структурах данных, а не в вашей: в случае сбоя процедура восстановления решит, что откатиться, чтобы сохранить согласованность , В случае отката ваши «еще не записанные, но подлежащие записи» данные будут потеряны. Файловая система будет согласованной, а ваши данные - нет.

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

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

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

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

Чтобы быть ACID, вам необходимо спроектировать свои структуры данных и / или способ их использования, чтобы не полагаться на детали реализации. Например, Mercurial (инструмент управления версиями) всегда добавляет свои собственные данные в свой собственный журнал изменений. Существует множество возможных шаблонов, однако, чем больше гарантий вам нужно, тем больше технологий вы получите (и к которым привязаны).

...