Совместим ли write() с O_DIRECT ACID?

Мой механизм базы данных записывает записи размером 64 байта, выполняя системный вызов write() всего блока диска. Устройство открывается в режиме O_DIRECT. Например, третья запись в блоке начинается с байта 128 и заканчивается в позиции 192, когда я делаю ОБНОВЛЕНИЕ, записывается весь блок диска (который по умолчанию составляет 512 байт).

У меня вопрос, могу ли я проверить соответствие ACID, если я записываю запись поверх себя каждый раз, когда происходит ОБНОВЛЕНИЕ? Обычно движки баз данных делают это в 2 шага, записывая измененный блок диска в другое (свободное) место, а затем обновляя индекс до нового блока с одной (атомарной) записью сразу после первой успешной записи. Но я не делаю этого, я перезаписываю текущие данные новыми, ожидая, что запись будет успешной. Есть ли у моего метода потенциальные проблемы? Это ACID-совместимый? Что если аппаратная часть записывает только половину блока, а моя запись находится точно посередине? Или аппаратное обеспечение уже выполняет описанный мной двухэтапный процесс записи, но на уровне блоков, поэтому мне не нужно повторять то же самое в программном обеспечении?

(примечание: ни одна запись не превышает размер блока физического диска (по умолчанию 512 байт), а fsync идет после каждой записи (), только для Linux)

2 ответа

ACID предвидит сбои и предлагает способы их устранения. Двухфазные фиксации и трехфазные фиксации - это два довольно распространенных и хорошо понятых подхода.

Хотя я работаю в базе данных, dbms освобождает меня от необходимости слишком много думать о подобных вещах. Но я бы сказал, что перезапись записи без принятия каких-либо других мер предосторожности может привести к сбою свойств "C" и "D" ("непротиворечивый" и "длительный").

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

Потом. , ,

Я прочитал стенограмму Твиди. Он не говорит о прямом доступе к базе данных; он говорит о файловой системе журналирования. Журналируемая файловая система также выполняет двухфазную фиксацию.

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

Открытие с помощью O_DIRECT означает " Попытаться минимизировать эффекты кэширования ввода-вывода в этот файл и из этого файла" (выделение добавлено). Я думаю, вам также понадобится O_SYNC. (Но связанные документы ядра предупреждают, что большинство файловых систем Linux не поддерживают POSIX-семантику O_SYNC. И известно, что и файловые системы, и диски лгут о том, попала ли запись в диск.)

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

Во-вторых,

"Что меня всегда беспокоило в O_DIRECT, так это то, что весь интерфейс просто глупый и, вероятно, был разработан ненормальной обезьяной на некоторых серьезных веществах, контролирующих разум". - Линус

У SQLite есть читабельная статья о том, как они обрабатывают атомарные коммиты. Атомная фиксация в SQLite

Нет.

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

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

Вот почему системы ACID используют как минимум две копии данных.

является write() с участием O_DIRECT КИСЛОТА совместима?

Нет, в общем случае это не гарантируется. Вот несколько контрпримеров долговечности:

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

У меня вопрос: могу ли я снизить соответствие [sic] ACID, если я записываю запись поверх себя каждый раз, когда происходит ОБНОВЛЕНИЕ?

В общем случае нет. Например, SCSI-диск, совместимый со спецификацией, не должен гарантировать семантику получения только старых или только новых данных, если сбой происходит во время записи (для него законно возвращать ошибку чтения этих данных до тех пор, пока область не станет безоговорочно перезаписаны). Если вы выполняете запись в файл в файловой системе, все становится еще сложнее. Успешныйfsync() после write() Перед запуском нового ввода-вывода вы узнаете, что запись была стабильной, но этого недостаточно для обеспечения атомарности (только старых или новых данных) в общем случае нерегулярно рассчитанной потери мощности.

Имеет ли мой метод [при условии, что перезапись совершенно атомарна] [sic] потенциальные проблемы?

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

См. Этот ответ на тему "Что на самом деле означает O_DIRECT?" для дальнейшего обсуждения.

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