понедельник, 17 января 2011 г.

Oracle на ZFS: Учимся готовить кошек, часть I

Вы не любите кошек?
Вы просто не умеете их готовить!

Честно говоря, я устал читать мнения анонимных аналитиков на IT-форумах о том, что-де ZFS медленно работает вообще (в принципе), а с использованием БД - в особенности. Поскольку мой личный опыт противоречит этой, в принципе ничем не обоснованной, точке зрения, давайте обратимся к первоисточникам и прочитаем вам маны вслух за ваши деньги. :)

Вначале мне бы хотелось рассмотреть рекомендации собственно Оракла (кстати, сертифицированного для работы на ZFS) с некоторыми комментариями. В дальнейшем мы расширим эти рекомендации в сторону практического опыта эксплуатации БД Oracle на ZFS и самоочевидных результатов собственных тестов.

Итак, давайте откроем данный официальный документ и начнем его читать вдумчиво.

Во-первых, обратим внимание на то, что в документе говориться о нативной реализации ZFS в Solaris 10 и OpenSolaris. Ни о каких деривативах, типа реализации ZFS на FreeBSD и речи не идет. О Solaris 11 мы тоже пока ничего не говорим, до выхода официального релиза.

Во-вторых, заметим, что собственно Оракл говорит об использовании ZFS на одноинстансных инсталляциях (не кластерных), а использование ZFS на RAC предполагает исключительно ее использование как NFS-шары (что лично мне представляется не лучшей идеей в кластерных архитектурах, а для Оракла в особенности, для RAC лучший вариант - OCFS2 - ASM). Это, в общем-то, достаточно логично, так как ZFS разрабатывалась изначально как локальная не кластерная файловая система (К сведению аналитиков - как замена UFS, которая также не является кластерной).

В-третьих, важнейшее замечание по конфигурированию массивов звучит буквально так - "создавайте столько LUN, сколько имеете шпинделей". Использование нескольких больших LUN ведет к уменьшению количества читающих тредов и падению производительности по чтению. И, наоборот, чрезмерное количество LUNов (по отношению к количеству шпинделей) приводит к затоплению массива большим количеством ожидающих операций чтения. Собственно, данная рекомендация восходит к рекомендациям большинства вендоров "шпиндели, шпиндели и еще раз шпиндели" - что означает, что большее количество относительно небольших дисков работает значительно более эффективно, нежели небольшое количество крупных дисков, обеспечивая значительно более высокий transfer rate и в целом увеличивая количество IOPS. В нашем случае, однако, важно совпадение количества LUNов c количеством шпинделей.

В-четвертых, Оракл прямо дает рекоменданию не создавать ZFS поверх существующей аппаратной или программной RAID-структуры. Что, в общем, совершенно очевидно, поскольку ZFS является volume manager и файловой системой в одном флаконе, имеет собственные средства обеспечения отказоустойчивости (на мой взгляд, гораздо лучшие, чем традиционные RAID). Подобно RAID-10, зеркалированные пулы ZFS обладают выдающейся производительностью, высокой надежностью, несравненно лучшими эксплуатационными показателями и способностью к самовосстановлению данных в случае их акцидентального повреждения. Для аналитиков: проверено на практике, в зеркалированном пуле в случае повреждения данных выполняется синхронизация (частичная или полная) с зеркала (зеркал) в полностью автоматическом режиме, как только файловая система обнаруживает нарушения контрольных сумм данных либо метаданных. При этом база данных, находящаяся на таком пуле, даже скорости работы не снижает.

В-пятых, Оракл явно не рекомендует использование RAIDZ, если производительность и IOPS являются главными критериями, предъявляемыми к системе хранения. Для информации - Оракл точно так же не рекомендует использование RAID-5 в более традиционных системах хранения, особенно с повышенными требованиями к скорости записи.

В-шестых, общее правило - размер recordsize для ZFS и db_block_size должны совпадать для файловых систем, на которых расположены файлы данных БД.

В-седьмых, рекомендуется, как и для традиционных систем хранения, отделять redo logs на отдельные файловые системы (пулы хранения)

В-восьмых, рекомендуется устанавливать режим ZIL параметром файловой системы logbias в значение throughput для большинства компонентов БД, исключая redo logs; а также управлять кэшированием данных в ARC L1 параметром primarycache, устанавливая его в значение metadata для UNDO и archived logs. Это логично - дабы не допускать чрезмерного перегрева кэша данными, которые в основном пишутся на диск и редко читаются (подобно буферному пулу RECYCLE в БД).

В-девятых, использование кэша ARC L2 позволяет повысить производительность, если произвольные чтения происходят в большом количестве и перегружают основную систему хранения. Одно но - рекомендуется создавать кэш L2 как отдельную структуру пула хранения для данных базы. И включение secondarycache не рекомендуется для redo logs в данный момент.

Далее в документе подробно рассматривается конфигурирование файловых систем и пулов хранения для работы под БД. Хочу обратить внимание на одну тонкость, прямо проистекающую из природы ZFS.

ZFS работает в идеологии COW (Copy-On-Write). Что означает, что при записи создается копия изменяемых данных в свободном пространстве, при сохранении предыдущей версии блоков данных.

При высоком заполнении пулов хранения/файловых систем (обычно свыше 80%) будет происходить резкое снижение производительности, поскольку ФС будет пытаться найти свободное пространство для записи копий.

Это нормальное естественное поведение ZFS. На практике есть два способа минимизировать влияние данной проблемы:

  1. Не допускать чрезмерного заполнения файловых систем установкой квот и резерваций.
  2. Попытаться оптимизировать выполнение записей на полных файловых системах установкой глобального системного параметра metaslab_df_free_pct в /etc/system:

Adjusting the metaslab_df_free_pct parameter to 4 in the /etc/system file
might help the write activity on full pools.
set zfs:metaslab_df_free_pct=4

Оракл также рекомендует ограничивать максимальный размер кэша ARC, что снижает нагрузку на память и позволяет снизить конкуренцию за оную:

You can reduce Oracle Solaris ZFS memory consumption by tuning the zfs_arc_max
parameter to a low value, but we still recommend provisioning enough memory to cache
metadata for the actively used portion of the database, which is estimated at 1.5% with an 8 KB
Oracle Solaris ZFS record size and proportionately less or more with larger or smaller records.
The file system that hold index files is the one that has the largest benefit from file system
caching because it is the last one to invalidate in case of lack of memory.
The zfs_arc_max parameter is in bytes and accepts decimal or hexadecimal values.
The following example sets this parameter to 2 GB:
set zfs:zfs_arc_max=2147483648
or
set zfs:zfs_arc_max=0x80000000

Опыт показывает, что уменьшать максимальный размер кэша ARC в значительной степени не стоит, поскольку как минимум метаданные ФС кэшировать все-таки необходимо. В большинстве случаев достаточно ограничить его максимальную величину значением 1/4-1/2 всей доступной оперативной памяти системы.

И последнее. Относится к администраторам любых систем, но в особенности систем с огромным количеством оперативной памяти. Приведу данную рекомендацию дословно:

To prevent applications from failing due to lack of memory, you must configure some amount of
swap space. The amount of swap equivalent to all of system memory is always enough for this
purpose. This swap space is not expected to be used, but is needed as a reservation area.
For information about increasing swap space, see the Oracle Solaris ZFS Administration Guide.

Говоря простым языком: Solaris не Windows, при большой памяти без свопа вообще работать не способна. Как минимум, один объем физической памяти должен быть отдан под подкачку, сколько бы этой памяти не было установлено (выделено мной).

Вот вкратце основные рекомендации Oracle, касающиеся производительности БД на ZFS.

Педантичное следование данным рекомендациям (а до их официального выхода - некоторым самоочевидным требованиям, описанным в документе) позволяло лично мне не раз достигать вполне выдающихся скоростных результатов (разумеется, в рамках оптимального дизайна БД и тщательной оптимизации запросов - впрочем, это позволяет добиваться выдающихся скоростных показателей на любых файловых системах, включая NTFS, при условии отсутствия очевидных бутылочных горлышек на уровне оборудования).