20.5.13

Внезапный direct I/O

На этот пост спровоцировало разбирательство на sql.ru. Там много страниц, можно не читать, здесь я обобщу полученный опыт.

Итак, СУБД Firebird и InterBase обычно используют файловый кэш при работе с БД. Вернее сказать, не "используют кэш", а при открытии файла БД указывают опции, которые включают или выключают этот кэш в определенных случаях.
Одновременно, они используют свой собственный кэш страниц БД.

Самый первый и известный случай изменения режима , это режим Forced Writes, т.е. в терминах CreateFile (Windows) включение (ON) или выключение (OFF) флага FILE_FLAG_WRITE_THROUGH. При ON операционная система осуществляет запись сразу на диск (или в контроллер raid, и т.д.). При OFF операционная система кэширует изменяемые страницы в RAM (подробнее о режимах кэша Windows).
Однако, у Firebird и InterBase существует понятие careful writes, когда изменяемые страницы записываются на диск в таком порядке, чтобы в случае внезапного сбоя (например, reset) база данных осталась максимально целой. Поскольку при OFF (включенном write cache ОС) порядок записи определяется операционной системой, а не СУБД, в случае reset БД может оказаться, скажем, в "физически нецелостном" состоянии.

Например, если добавляется новая запись, а места на страницах БД для этого нет, то создается новая страница, запись размещается на ней, затем ссылка на страницу добавляется в Pointer pages таблицы, после чего в соответствующую inventory pages для новой страницы заносится флаг "занято".
Если все это попадает в кэш ОС, то страница inventory pages может попасть на диск раньше новой страницы с записью, в результате чего при reset окажется, что страница как бы занята, и таблица ссылается на нее, а на деле в этой странице мусор (еще ничего не записано).

Что интересно, до определенного момента в Firebird на Linux режим Forced Writes = ON не поддерживался, т.е. всегда было OFF (исправлено в FB 2.1)

Вторым из режимов кэша, или режимов открытия файлов, является флаг FILE_FLAG_NO_BUFFERING (Windows), который выключает кэш ОС для этого файла вообще, т.е. в том числе и на чтение.
Мы давно экспериментировали с этим флагом в Yaffil, и выяснили, что на обычных дисках производительность резко просаживается (у IB и FB, да и у Yaffil, собственный кэш не умеет делать prefetch, в отличие от ОС), а также, что худший вариант - когда размер страницы не совпадает с размером кластера файловой системы.
В общем, по результатам теста этот флаг было решено оставить в покое.

Со временем кэш дисков, контроллеров и вообще систем хранения сильно вырос, и стал достаточно умным. Так что на некоторых устройствах есть смысл во включении Direct I/O.
Для InterBase возможность отключить кэш ОС была введена в версии XE.
В Firebird такая возможность появилась в 2.5. Для всех баз на сервере direct I/O можно включить путем установки опции FileSystemCacheThreshold=0 в firebird.conf.
Что интересно, режим direct I/O включается не только этим нулем, а и в том случае, если указанный размер кэша БД (DefaultDBCachePages в firebird.conf или page buffers в конкретной БД) больше, чем FileSystemCacheThreshold.
То есть, поскольку FileSystemCacheThreshold по умолчанию 65536, то режим direct I/O включится, если размер кэша в конфиге или БД указан больше этого значения.

Попасть на эти грабли могут разве что пользователи Firebird с архитектурой SuperServer, потому что у Classic и SuperClassic раздельный кэш БД, и выставлять значения кэша больше 65к страниц никому и в голову не придет - сервер тут же начнет отжирать память. Например, для страницы 8к 65к страниц кэша станут 512 мегабайтами RAM, потребляемыми на каждого пользователя.

С другой стороны, у SuperServer кэш БД общий для всех пользователей, и поэтому вполне разумно указать его побольше, особенно если размер БД как минимум 1 гигабайт.
Но как только вы включите такой кэш, "внезапно" для БД отрубится файловый кэш операционной системы (если не изменить параметры по умолчанию в firebird.conf).

Хорошо это или плохо - нужно проверять в конкретном случае. Ваша дисковая подсистема может оказаться настолько крутой, что отключение файлового кэша ОС для БД улучшит производительность, или, по крайней мере, освободит память ОС для других целей.
Но если нет - при задирании размера кэша БД вдруг может случиться и падение производительности.

Дополнения:
  • на Linux указанные режимы открытия файлов это O_SYNC и O_DIRECT.
  • после включения direct I/O режим Forced Writes уже не имеет значения (будет всегда ON)
  • в Firebird 2.5.2 исправлена еще одна проблема с кэшем Windows.