Sunday, July 22, 2018

Oracle Async и Direct I/O.

На написание этой статьи меня сподвигла тема на одном из форумов Oracle, в который всплыли очередные мифы о возможностях direct и async, их скорости и возможной потери данных в БД.

На эту тему есть старенькая, но отличная статья (на английском): http://mgogala.byethost5.com/directio.pdf?i=2

Рассмотрим ее основные положения.

В обычном режиме Unix disk IO операции выглядят, так:




Т.е. когда используется обычный системный вызов на чтение, данные с диска не отправляются напрямую в user buffer, Unix «вставляет» свой buffer между user buffer и диском. Соответственно, Oracle БД, когда читает из файла, блок сначала помещается в буфер ОС. Это дает ОС возможность кэшировать и распределять общие данные между процессами. Буфер ОС не доступен напрямую из пользовательского кода – это внутренний системный инструмент. При том, вы наверняка знаете, он разделяется на область ядра (kernel space) и пользовательскую (user space). Как именно это разделение происходит зависит от конкретной реализации архитектуры ОС.



Проблемы

В данном подходе имеется несколько проблем. Первое, чтение и запись идет через системный буфер, и пользователь не знает, где закончится его I/O вызов – в буфере или на диске. Это не подходит, например, в случае log writer'а БД Oracle. При commit в БД мы должны быть уверены, что данные точно записаны на диск (в редолог), поэтому log writer использует системные вызовы синхронизации с диском, как например fsync (http://man7.org/linux/man-pages/man2/fdatasync.2.html), независимо от выбранного режима работы с I/O в БД. С процессом записи в датафайлы(DBWR) дело обстоит иначе. Соответственно, при краше бд может понадобится восстановление датафайлов.

Другая проблема работы бд с I/O через буфер ОС – это производительность. Unix’ы используют несколько стратегий оптимизации при работе буфера. К сожалению, ни одна из них не учитывает особенности SQL, транзакционного механизма, согласованного чтения итп. Эти стратегии основаны на файловой парадигме, использующей механизмы file prefetch, LRU list, чтобы горячие блоки не вытеснялись из буфера. File prefetch – это механизм буферизирующий на несколько файловых блоков больше, чем читается, в расчете, что именно они и будут прочитаны следующими. И это никак не пересекается и стратегиями буферизации Оракла, что, зачастую, просто приводит к лишним действиям и расходованию памяти. Бывают и исключения, например, какая либо аналитическая БД, которая в основном и занимается последовательным чтением больших кусков своих датафайлов.

Современные Unix системы имеют динамические буфер кэши и могут использовать всю доступную системе свободную память. Можно наблюдать как Linux, где не используется directIO буферизирует всю свободную память, не смотря на то, что система не нагружена. Под любой процесс ОС, как например пользовательский БД при dedicated server connection, ОС должна выделить какое-то количество памяти, освободив его из буфера. В особо запущенном случае, место буфере придется скинуть в своп. В любом случае ОС потратить какое-то время на работу со своим буфером. Все это перерастает в большую проблему для загруженной БД Оракл лежащей на файловой системе.

В Unix системах есть 2 опции, которые помогают решить эти проблемы – direct IO и asynchronous IO.

Asynchronous IO

Суть процесса состоит в том, что I/O операции передаются специальному процессу ядра и пользовательский процесс запросивший IO операцию передает ее ему и не ждет ее окончания. Когда реально I/O операция будет выполнена, пользовательский процесс получит сигнал о ее окончании. Если ОС не поддерживает asynchronous I/O или есть некоторые недостатки в его реализации, у Оракла есть своя эмуляция – DBWR процессы и, с версии 10, несколько ARCH процессов. 

Direct I/O

Суть простая – данные пересылаются на диск, минуя кэш ОС, если относительно БД Оракл, то - блоки из SGA переносятся напрямую на диск и наоборот, с диска в SGA. С Direct I/O больше сложностей, т.к. его на получится эмулировать на уровне БД, если ОС его не поддерживает. Правда, практически все современные ФС, подходящие под БД Оракл поддерживают direct IO.

В БД за использование Direct и Async IO на ФС отвечает параметр FILESYSTEMIO_OPTIONS. Следует также отметить, что значения этого параметра игнорируются при использовании ASM (см. ASM Inherently Performs Asynchronous I/O Regardless of filesystemio_options Parameter (Doc ID 751463.1)).

Если вы захотите проверить используется Async и Direct IO в вашей БД, как вариант, можно снять трассировку с DBWR процесса.

No comments :

Post a Comment