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

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

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

Так что мой вопрос конкретно:

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

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

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

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

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

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

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

2 ответа

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам