rac oracle что это

Oracle RAC. Общее описание / Часть 1

rac oracle что это. Смотреть фото rac oracle что это. Смотреть картинку rac oracle что это. Картинка про rac oracle что это. Фото rac oracle что этоВысоконагруженные сайты, доступность «5 nines». На заднем фоне (backend) куча обрабатываемой информации в базе данных. А что, если железо забарахлит, если вылетит какая-то давно не проявлявшаяся ошибка в ОС, упадет сетевой интерфейс? Что будет с доступностью информации? Из чистого любопытства я решил рассмотреть, какие решения вышеперечисленным проблемам предлагает Oracle. Последние версии, в отличие от Oracle 9i, называются Oracle 10g (или 11g), где g – означает «grid», распределенные вычисления. В основе распределенных вычислений «как ни крути» лежат кластера, и дополнительные технологии репликации данных (DataGuard, Streams). В этой статье в общих чертах описано, как устроен кластер на базе Oracle 10g. Называется он Real Application Cluster (RAC).

Статья не претендует на полноту и всеобъемлемость, также в ней исключены настройки (дабы не увеличивать в объеме). Смысл – просто дать представление о технологии RAC.

Статью хотелось написать как можно доступнее, чтобы прочесть ее было интересно даже человеку, мало знакомому с СУБД Oracle. Поэтому рискну начать описание с аспектов наиболее часто встречаемой конфигурации БД – single-instance, когда на одном физическом сервере располагается одна база данных (RDBMS) Oracle. Это не имеет непосредственного отношения к кластеру, но основные требования и принципы работы будут одинаковы.

Введение. Single-instance.

rac oracle что это. Смотреть фото rac oracle что это. Смотреть картинку rac oracle что это. Картинка про rac oracle что это. Фото rac oracle что это

Во всех современных реляционных БД данные хранятся в таблицах. Таблицы, индексы и другие объекты в Oracle хранятся в логических контейнерах – табличных пространствах (tablespace). Физически же tablespace располагаются в одном или нескольких файлах на диске. Хранятся они следующим образом:
Каждый объект БД (таблицы, индексы, сегменты отката и.т.п.) хранится в отдельном сегменте – области диска, которая может занимать пространство в одном или нескольких файлах. Сегменты в свою очередь, состоят из одного или нескольких экстентов. Экстент – это непрерывный фрагмента пространства в файле. Экстенты состоят из блоков. Блок – наименьшая единица выделения пространства в Oracle, по умолчанию равная 8K. В блоках хранятся строки данных, индексов или промежуточные результаты блокировок. Именно блоками сервер Oracle обычно выполняет чтение и запись на диск. Блоки имеют адрес, так называемый DBA (Database Block Address).

rac oracle что это. Смотреть фото rac oracle что это. Смотреть картинку rac oracle что это. Картинка про rac oracle что это. Фото rac oracle что это

При любом обращении DML (Data Manipulation Language) к базе данных, Oracle подгружает соответствующие блоки с диска в оперативную память, а именно в буферный кэш. Хотя возможно, что они уже там присутствуют, и тогда к диску обращаться не нужно. Если запрос изменял данные (update, insert, delete), то изменения блоков происходят непосредственно в буферном кэше, и они помечаются как dirty (грязные). Но блоки не сразу сбрасываются на диск. Ведь диск – самое узкое место любой базы данных, поэтому Oracle старается как можно меньше к нему обращаться. Грязные блоки будут сброшены на диск автоматически фоновым процессом DBWn при прохождении контрольной точки (checkpoint) или при переключении журнала.

rac oracle что это. Смотреть фото rac oracle что это. Смотреть картинку rac oracle что это. Картинка про rac oracle что это. Фото rac oracle что это

rac oracle что это. Смотреть фото rac oracle что это. Смотреть картинку rac oracle что это. Картинка про rac oracle что это. Фото rac oracle что это

Когда в базу данных поступает запрос на изменение, то Oracle применяет его в буферном кэше, параллельно внося информацию, достаточную для повторения этого действия, в буфер повторного изменения (redo log buffer), находящийся в оперативной памяти. Как только транзакция завершается, происходит ее подтверждение (commit), и сервер сбрасывает содержимое redo buffer log на диск в redo log в режиме append-write и фиксирует транзакцию. Такой подход гораздо менее затратен, чем запись на диск непосредственно измененного блока. При сбое сервера кэш и все изменения в нем потеряются, но файлы redo log останутся. При включении Oracle начнет с того, что заглянет в них и повторно выполнит изменения таблиц (транзакции), которые не были отражены в datafiles. Это называется «накатить» изменения из redo, roll-forward. Online redo log сбрасывается на диск (LGWR) при подтверждении транзакции, при прохождении checkpoint или каждые 3 секунды (default).

С undo немного посложнее. С каждой таблицей в соседнем сегменте хранится ассоциированный с ней сегмент отмены. При запросе DML вместе с блоками таблицы обязательно подгружаются данные из сегмента отката и хранятся также в буферном кэше. Когда данные в таблице изменяются в кэше, в кэше так же происходит изменение данных undo, туда вносятся «противодействия». То есть, если в таблицу был внесен insert, то в сегмент отката вносится delete, delete – insert, update – вносится предыдущее значение строки. Блоки (и соответствующие данные undo) помечаются как грязные и переходят в redo log buffer. Да-да, в redo журнал записываются не только инструкции, какие изменения стоит внести (redo), но и какие у них противодействия (undo). Так как LGWR сбрасывает redo log buffer каждые 3 секунды, то при неудачном выполнении длительной транзакции (на пару минут), когда после минуты сервер упал, в redo будут записи не завершенные commit. Oracle, как проснется, накатит их (roll-forward), и по восстановленным (из redo log) в памяти сегментам отката данных отменит (roll-back) все незафиксированные транзакции. Справедливость восстановлена.

Кратко стоит упомянуть еще одно неоспоримое преимущество undo сегмента. По второму сценарию (из схемы) когда select дойдет до чтения блока (DBA) 500, он вдруг обнаружит что этот блок в кэше уже был изменен (пометка грязный), и поэтому обратится к сегменту отката, для того чтобы получить соответствующее предыдущее состояние блока. Если такого предыдущего состояния (flashback) в кэше не присутствовало, он прочитает его с диска, и продолжит выполнение select. Таким образом, даже при длительном «select count(money) from bookkeeping» дебет с кредитом сойдется. Согласованно по чтению (CR).

Отвлеклись. Пора искать подступы к кластерной конфигурации. =)

Уровень доступа к данным. ASM.

rac oracle что это. Смотреть фото rac oracle что это. Смотреть картинку rac oracle что это. Картинка про rac oracle что это. Фото rac oracle что это

Хранилищем (datastorage) в больших БД почти всегда выступает SAN (Storage Area Network), который предоставляет прозрачный интерфейс серверам к дисковым массивам.
Сторонние производители (Hitachi, HP, Sun, Veritas) предлагают комплексные решения по организации таких SAN на базе ряда протоколов (самым распространенным является Fibre Channel), с дополнительными функциональными возможностями: зеркалирование, распределение нагрузки, подключение дисков на лету, распределение пространства между разделами и.т.п.
Позиция корпорации Oracle в вопросе построения базы данных любого масштаба сводится к тому, что Вам нужно только соответствующее ПО от Oracle (с соответствующими лицензиями), а выбранное оборудование – по возможности (если средства останутся после покупки Oracle :). Таким образом, для построения высоконагруженной БД можно обойтись без дорогостоящих SPARC серверов и фаршированных SAN, используя сервера на бесплатном Linux и дешевые RAID-массивы.

На уровне доступа к данным и дискам Oracle предлагает свое решение – ASM (Automatic Storage Management). Это отдельно устанавливаемый на каждый узел кластера мини-экземпляр Oracle (INSTANCE_TYPE = ASM), предоставляющий сервисы работы с дисками.

Oracle старается избегать обращений к диску, т.к. это является, пожалуй, основным bottleneck любой БД. Oracle выполняет функции кэширования данных, но ведь и файловые системы так же буферизуют запись на диск. А зачем дважды буферизировать данные? Причем, если Oracle подтвердил транзакцию и получил уведомления том, что изменения в файлы внесены, желательно, чтобы они уже находились там, а не в кэше, на случай «падения» БД. Поэтому рекомендуется использовать RAW devices (диски без файловой системы), что делает ASM.

Таким образом, кластер теперь может хранить и читать данные с общего файлового хранилища.

Пора на уровень повыше.

Clusterware. CRS.

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

CRS (Cluster-Ready Services) – набор сервисов, обеспечивающий совместную работу узлов, отказоустойчивость, высокую доступность системы, восстановление системы после сбоя. CRS выглядит как «мини-экземпляр» БД (ПО) устанавливаемый на каждый узел кластера. Устанавливать CRS – в обязательном порядке для построения Oracle RAC. Кроме того, CRS можно интегрировать с решениями clusterware от сторонних производителей, таких как HP или Sun.

Опять немного «терминологии»…

Как уже стало ясно из таблички, самым главным процессом, «самым могущественным демоном», является CRSD (Cluster Ready Services Daemon). В его обязанности входит: запуск, остановка узла, генерация failure logs, реконфигурация кластера в случае падения узла, он также отвечает за восстановление после сбоев и поддержку файла профилей OCR. Если демон падает, то узел целиком перезагружается. CRS управляет ресурсами OCR: Global Service Daemon (GSD), ONS Daemon, Virtual Internet Protocol (VIP), listeners, databases, instances, and services.

Информатором в кластере выступает EVMD (Event Manager Daemon), который оповещает узлы о событиях: о том, что узел запущен, потерял связь, восстанавливается. Он выступает связующим звеном между CRSD и CSSD. Оповещения также направляются в ONS (Oracle Notification Services), универсальный шлюз Oracle, через который оповещения можно рассылать, например, в виде SMS или e-mail.

Стартует кластер примерно по следующей схеме: CSSD читает из общего хранилища OCR, откуда считывает кластерную конфигурацию, чтобы опознать, где расположен voting disk, читает voting disk, чтобы узнать сколько узлов (поднялось) в кластере и их имена, устанавливает соединения с соседними узлами по протоколу IPC. Обмениваясь heartbeat, проверяет, все ли соседние узлы поднялись, и выясняет, кто в текущей конфигурации определился как master. Ведущим (master) узлом становится первый запустившийся узел. После старта, все запущенные узлы регистрируются у master, и впоследствии будут предоставлять ему информацию о своих ресурсах.

Уровнем выше CRS на узлах установлены экземпляры базы данных.
Друг с другом узлы общаются по private сети – Cluster Interconnect, по протоколу IPC (Interprocess Communication). К ней предъявляются требования: высокая ширина пропускной способности и малые задержки. Она может строиться на основе высокоскоростных версий Ethernet, решений сторонних поставщиков (HP, Veritas, Sun), или же набирающего популярность InfiniBand. Последний кроме высокой пропускной способности пишет и читает непосредственно из буфера приложения, без необходимости в осуществлении вызовов уровня ядра. Поверх IP Oracle рекомендует использовать UDP для Linux, и TCP для среды Windows. Также при передаче пакетов по interconnect Oracle рекомендует укладываться в рамки 6-15 ms для задержек.

Источник

Oracle RAC. Общее описание / Часть 2

Продолжение статьи про Real Application Cluster (RAC). Окончание.

Считаем, что кластер поднялся и все закрутилось.

Взаимодействие узлов. Cache-fusion.

Много экземпляров БД, много дисков. Хлынули пользовательские запросы… вот они, клиенты, которых мы так ждали. =)

Самым узким местом любой БД являются дисковый ввод-вывод. Поэтому все базы данных стараются как можно реже обращаться к дискам, используя отложенную запись. В RAC все так же, как и для single-instance БД: у каждого узла в RAM располагается область SGA (System Global Area), внутри нее находится буферный кэш (database buffer cache). Все блоки, некогда прочитанные с диска, попадают в этот буфер, и хранятся там как можно дольше. Но кэш не бесконечен, поэтому, чтобы оценить важность хранимого блока, используется TCA (Touch Count Algorithm), считающий количество обращений к блокам. При первом попадании в кэш, блок размещается в его cold-end. Чем чаще к блоку обращаются, тем ближе он к hot-end. Если же блок «залежался», он постепенно утрачивает свои позиции в кэше и рискует быть замещенным другой записью. Перезапись блоков начинается с наименее используемых. Кэш узла – крайне важен для производительности узлов, поэтому для поддержания высокой производительности в кластере кэшем нужно делиться (как завещал сами-знаете-кто). Блоки, хранимые в кэше узла кластера, могут иметь роль локальных, т.е. для его собственного пользования, но некоторые уже будут иметь пометку глобальные, которыми он, поскрипев зубами дисками, будет делится с другими узлами кластера.

Технология общего кэша в кластере называется Cache-fusion (синтез кэша). CRS на каждом узле порождает синхронные процессы LMSn, общее их название как сервиса — GCS (Global Cache Service). Эти процессы копируют прочитанные на этом экземпляре блоки (глобальные) из буферного кэша к экземпляру, который за ними обратился по сети, и также отвечают за откат неподтвержденных транзакций. На одном экземпляре их может быть до 36 штук (GCS_SERVER_PROCESSES). Обычно рекомендуется по одному LMSn на два ядра, иначе они слишком сильно расходуют ресурсы. За их координацию отвечает сервис GES (Global Enqueue Service), представленный на каждом узле процессами LMON и LMD. LMON отслеживает глобальные ресурсы всего кластера, обращается за блоками к соседним узлам, управляет восстановлением GCS. Когда узел добавляется или покидает кластер, он инициирует реконфигурацию блокировок и ресурсов. LMD управляет ресурсами узла, контролирует доступ к общим блоками и очередям, отвечает за блокировки запросов к GCS и управляет обслуживанием очереди запросов LMSn. В обязанности LMD также входит устранение глобальных взаимоблокировок в рамках нескольких узлов кластера.

rac oracle что это. Смотреть фото rac oracle что это. Смотреть картинку rac oracle что это. Картинка про rac oracle что это. Фото rac oracle что это

Таблица GRD распределена между узлами кластера. Каждый узел принимает участие в распределении ресурсов кластера, обновляя свою часть GRD. Часть таблицы GRD относится к ресурсам – объектам: таблицы, индексы и.т.п. Она постоянно синхронизируется (обновляется) между узлами.
Когда узел прочел блок данных с диска, он становится master-ом этого ресурса и делает соответствующую отметку в своей части таблицы GRD. Блок помечается как локальный, т.к. узел пока использует его в одиночку. Если же этот блок потребовался другому узлу, то процесс GCS пометит этот блок в таблице как глобальный («опубликован» для кластера) и передаст затребовавшему узлу.

DBAlocationmoderoleSCNPI/XI
500узел №3sharedlocal99960

Без необходимости никаких записей на диск не происходит. Всегда копия блока хранится на узле, на котором он чаще используется. Если определенного блока пока еще нет в глобальном кэше, то при запросе master попросит соответствующий узел прочитать блок с диска и поделиться им с остальными узлами (по мере надобности).

Taking fire, need assistance! Workload distribution.

Описанное устройство Cache-fusion, предоставляет кластеру возможность самому (автоматически) реагировать на загрузку узлов. Вот как происходит workload distribution или resource remastering (перераспределение вычислительных ресурсов):
Если, скажем, через узел №1 1500 пользователей обращается к ресурсу A, и примерно в это же время 100 пользователей обращается к тому же ресурсу A через узел №2, то очевидно, что первый узел имеет большее количество запросов, и чаще будет читать с диска. Таким образом узел №1 будет определен как master для запросов к ресурсу A, и GRD будет создано и координироваться начиная с узла №1. Если узлу №2 потребуются те же самые ресурсы, то для получения доступа к ним он должен будет согласовать свои действия с GCS и GRD узла №1, для получения ресурсов через interconnect.
Если же распределение ресурсов поменяется в пользу узла №2, то процессы №2 и №1 скоординируются свои действия через interconnect, и master-ом ресурса A станет узел №2, т.к. теперь он будет чаще обращаться к диску.
Это называется родственность (affinity) ресурсов, т.е. ресурсы будут выделяться тому узлу, на котором происходит больше действий по получению и их блокированию. Политика родственности ресурсов скоординирует деятельность узлов, чтобы ресурсы более доступны были там, где это более необходимо. Вот, кратко, и весь workload distribution.

Перераспределение (remastering) также происходит, когда какой-то узел добавляется или покидает кластер. Oracle перераспределяет ресурсы по алгоритму называемому «ленивое перераспределение» (lazy remastering), т.к. Oracle почти не принимает активных действий по перераспределению ресурсов. Если какой-то узел упал, то все, что предпримет Oracle – это перекинет ресурсы, принадлежавшие обвалившемуся узлу, на какой-то один из оставшихся (менее загруженный). После стабилизации нагрузки GCS и GES заново (автоматически) перераспределят ресурсы (workload distribution) по тем позициям, где они более востребованы. Аналогичное действие происходит при добавлении узла: примерно равное количество ресурсов отделяется от действующих узлов и назначается вновь прибывшему. Потом опять произойдет workload distribution.
Как правило, для инициализации динамического перераспределения, загруженность на определенном узле должна превышать загруженность остальных в течение более 10 минут.

Вот пуля пролетела, и… ага? Recovery.

Но пока все эти процессы происходят, нетерпеливому клиенту есть что предложить.

Пока узлы спасают друг друга… Failover.

Virtual IP (VIP) – логический сетевой адрес, назначаемый узлу на внешнем сетевом интерфейсе. Он предоставляет возможность CRS спокойно запускать, останавливать и переносить работу с этим VIP на другой узел. Listener (процесс, принимающий соединения) на каждом узле будет прослушивать свой VIP. Как только какой-то узел становится недоступным, его VIP подхватывает на себя другой узел в кластере, таким образом, временно обслуживая свои и запросы упавшего узла.

Если узел восстановится и выйдет в online, CRS опознает это и попросит сбросить в offline на подменяющем его узле и вернет VIP адрес обратно владельцу. VIP относится к CRS, и может не перебросится если выйдет из строя именно экземпляр БД.

Важно отметить, что при failover переносятся только запросы select, вместе и открытыми курсорами (возвращающими результат). Транзакции не переносятся (PL/SQL, temp tables, insert, update, delete), их всегда нужно будет запускать заново.

Туда не ходи, сюда ходи… Load-balancing.

При выполнении любых операций, информацию, относящуюся к производительности запросов (наподобие «отладочной»), Oracle собирает в AWR (Automatic Workload Repository). Она хранится в tablespace SYSAUX. Сбор статистики запускается каждые 60 минут (default): I/O waits, wait events, CPU used per session, I/O rates on datafiles (к какому файлу чаще всего происходит обращение).

Необходимость в Load-balancing (распределении нагрузки) по узлам в кластере определяется по набору критериев: по числу физических подключений к узлу, по загрузке процессора (CPU), по трафику. Жаль что нельзя load-balance по среднему времени выполнения запроса на узлах, но, как правило, это некоторым образом связано с задействованными ресурсами на узлах, а следовательно оставшимися свободными ресурсам.

О Client load-balancing было немного сказано выше. Он просто позволяет клиенту подключаться к случайно выбранному узлу кластера из списка в конфигурации. Для осуществления же Server-side load-balancing отдельный процесс PMON (process monitor) собирает информацию о загрузке узлов кластера. Частота обновления этой информации зависит от загруженности кластера и может колебаться в пределе от приблизительно 1 минуты до 10 минут. На основании этой информации Listener на узле, к которому подключился клиент, будет перенаправлять его на наименее загруженный узел.

Если в приложении реализован connection pool, Oracle предоставляет вариант Runtime Connection Load Balancing (RCLB). Вместо обычного варианта, когда мы пытаемся предугадать, который из узлов будет менее загружен, и направить запрос туда, будет использован механизм оповещений (events) приложения о загрузке на узлах. И теперь уже само приложение будет определять куда отправить запрос, опираясь на эти данные. Оповещение происходит через ONS (Oracle Notification Service). RCLB регулярно получает данные (feedback) от узлов кластера, и connection pool будет раздавать подключения клиентам, опираясь на некоторое относительное число, отображающее какой процент подключений каждый экземпляр может выполнить. Эти метрики (средняя загрузка узла), которые пересылает RAC, каждый узел строит сам в AWR. На их основании формируется required load advisory и помещается в очередь AQ (advanced querying), откуда данные пересылаются через ONS клиенту.

Источник

Oracle RAC: как обеспечить целостность данных в кластере и избежать краха?

В этой статье мы рассмотрим следующие идеи:

Существует всего две функциональные особенности, которые нужно рассмотреть, чтобы ответить на все эти вопросы – глобальные блокировки и поддержка непротиворечивости кэша (cache coherency) – и эти две особенности будут главными темами в данной статье. Их исследование даст возможность проверить и закрепить наши знания о блокировках и защелках, сосредоточившись при этом на важнейших изменениях, которые могут вызывать проблемы в Oracle RAC.

Но, прежде чем углубиться в исследования, мы потратим некоторое время на общее знакомство с технологией RAC, с причинами, которые могут побудить вас использовать ее, и с проблемами, с которыми столкнулись разработчики Oracle при создании продукта. Попутно мы посмотрим, насколько хорошо укладываются в RAC механизмы восстановления, позволяющие одному экземпляру перехватывать управление, когда другой терпит аварию. Так как обсуждение RAC по большей части будет вестись на абстрактном уровне, я взял на вооружение широко используемый прием, заключающийся в выдаче конкретных рекомендаций, касающихся разработки приложений, которые учитывают особенности работы с Oracle RAC.

Примечание. Я выбрал для этой статьи не совсем обычный заголовок, чтобы подчеркнуть, насколько легко можно все разрушить, не понимая, хотя бы чуть-чуть, как действует RAC; но использование RAC не обязательно ведет к краху.

Общая картина

На мой взгляд понять, как действует RAC, совсем несложно, когда все настроено и работает. Установить и запустить этот продукт – вот главная сложность. В процессе установки придется настроить множество разных уровней. Неважно, сколько сил приложили разработчики Oracle, чтобы упростить работу со своими продуктами – некоторые из них в принципе являются сложнейшими агрегатами, в которых каждый отдельный компонент должен быть настроен безупречно, чтобы весь комплекс действовал слаженно. И каждый раз, когда вы делаете это (или каждый раз, когда это делаю я), появляются какие-то новые тонкости, о которых нужно позаботиться.

К счастью, я избавлен от тяжкого труда рассказывать, как установить Oracle RAC, благодаря множеству статей в блогах (таких как серия статей Тима Холла (Tim Hall) на сайте http://www.oracle-base.com), объемным инструкциям по установке на Oracle Technet (OTN) и целым книгам (таким как «Pro Oracle Database 11g RAC on Linux» Мартина Баха (Martin Bach) и Стива Шоу (Steve Shaw) (Apress, 2010)), детально описывающим эту процедуру. Я расскажу лишь о некоторых особенностях времени выполнения, чтобы показать, почему нужно проявлять осторожность при использовании этого продукта.

Итак, взгляните на рис. 1, где изображена общая схема RAC.

rac oracle что это. Смотреть фото rac oracle что это. Смотреть картинку rac oracle что это. Картинка про rac oracle что это. Фото rac oracle что это

Рис. 1. Схема RAC

Ниже приводятся некоторые ключевые замечания, касающиеся схемы на рис. 1:

Ниже перечислено, что не показано на схеме:

Виртуальные IP-адреса и SCAN

При настройке системы RAC, одной из ваших задач на уровне операционной системы будет присвоить каждой машине «виртуальный» IP-адрес («Virtual» IP address, VIP). Сразу после запуска, служба организации кластера вставляет свой код уровнем выше фактического IP-адреса и машины переходят на взаимодействия с использованием адресов VIP.

Самое большое отличие между действительным и виртуальным IP- адресами состоит в том, что действительный IP-адрес логически связан с конкретным аппаратным элементом (технически – с MAC-адресом сетевой карты), тогда как VIP-адрес управляется программно и его логическая связь с конкретной аппаратурой может динамически меняться.

Если машина с базой данных прекратит работу, когда клиентская машина подключена к ней через действительный IP, клиентская программа будет очень долго ждать (от десятков до сотен секунд) ответа от сервера, пока поймет, что сервер недоступен по каким-то причинам. Так как Oracle использует виртуальные IP-адреса, в случае выхода машины из строя один из других экземпляров очень быстро обнаружит этот факт и присвоит виртуальный IP прекратившей работу машины себе, чтобы обработать текущие запросы. Система будет автоматически перенастроена так, что она прекратит принимать новые запросы по проблемному VIP (пока машина и экземпляр не будут запущены вновь). Это означает, что клиентам не придется долго ждать в случае появления каких-то проблем.

Как еще одно средство уменьшить длительность ожиданий, вызываемых проблемами в сети, в Oracle 11.2 был реализован новый механизм SCAN (Single Client Access Name – единый адрес для доступа со стороны клиентов), как часть инфраструктуры Grid Infrastructure. Прежде чем вы сможете использовать механизм SCAN, вам потребуется попросить своего системного администратора настроить несколько новых записей DNS (Domain Name Service) или помочь вам настроить подраздел DNS для использования Oracle GNS (Grid Naming Service). После этого любая клиентская программа сможет ссылаться на систему по единому адресу SCAN и вам не придется перенастраивать клиентов, если вдруг потребуется перенести систему на другую машину или добавить (удалить) узлы.

Бесперебойная работа

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

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

Защита на уровне машины

Служба поддержки кластера на каждой машине постоянно поддерживает контакт с другими машинами в сети, но она также поддерживает контакт с дисками кворума (voting disc), изображенными на рис. 1, что дает дополнительные возможности в преодолении проблем, связанных с нарушениями в работе сети.

Все машины каждую секунду выполняют запись на диск «кворума» – в файл на диске, каждый блок которого соответствует конкретной машине, и каждая машина просто наращивает счетчик в блоке. В простейшем случае машина может обнаружить, что не в состоянии выполнить запись в файл – тогда она сама удалит себя из кластера и может отправиться на перезагрузку. (Разумеется, в этот момент соответствующий экземпляр внезапно завершит работу и один из других экземпляров выполнит процедуру восстановления за него.)

Записывая новое значение счетчика в свой блок, каждая машина проверяет также блоки, принадлежащие другим машинам в кластере, чтобы выявить ситуации, когда другим машинам не удалось обновить счетчики в недавнем прошлом. (Возможно, что какая-то машина находится в неустойчивом состоянии из-за некорректной работы ПО поддержки кластера, но при этом действует и на ней выполняется экземпляр – подобные ситуации угрожают целостности данных в базе.) В этом случае машина, обнаружившая неполадки, может завершить работу подозрительной машины.

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

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

Защита на уровне Oracle

Аналогичная стратегия применяется на уровне Oracle. Запускаясь, каждый экземпляр сообщает о своем присутствии другим экземплярам, поэтому каждый экземпляр всегда знает, сколько других экземпляров должно существовать. Точно так же, завершаясь (корректно), экземпляр говорит всем «до свидания». В короткий период, во время запуска и завершения, последнее состояние экземпляра распространяется между членами группы и выполняется «перераспределение» нагрузки с учетом изменившегося числа экземпляров. С момента запуска экземпляры непрерывно взаимодействуют друг с другом по сети (в частности, обмениваются сообщениями типа «я живой» с помощью процесса LMON).

Поддерживается также проверка работоспособности экземпляров на основе файлов. Как было показано в ранее в блогах нашего портала, процесс выполнения контрольных точек (CKPT) обновляет управляющий файл примерно каждые три секунды. В конфигурации RAC каждый экземпляр имеет собственный процесс CKPT, поэтому управляющий файл может действовать как признак работоспособности экземпляра Oracle. Если вывести дамп файла с уровнем 3 (см. приложение), можно увидеть в нем раздел для записей обработки контрольных точек (Checkpoint Progress Records) – этот критически важный раздел управляющего файла содержит по одной записи для каждого экземпляра, которая должна постоянно обновляться соответствующим экземпляром.

Поэтому, если экземпляр обнаруживает, что больше не в состоянии осуществлять запись в управляющий файл, он может завершить себя, чтобы обезопасить систему. Также может сложиться ситуация, когда какой-то другой экземпляр заметит, что данный экземпляр «завис» (и, как будет показано ниже, если один экземпляр завис, тогда любой другой экземпляр, заметивший это, должен прервать его ожидание). То есть, можно надеяться, что в Oracle имеется механизм, позволяющий одному экземпляру (если он в кворуме, конечно) завершить другой экземпляр. К сожалению, я не уверен, что подобное возможно в версиях до 11.2, где появился новый процесс мониторинга LMHB (Lock Manager Heart Beat Monitor), очень быстро определяющий, что какой-то процесс приостановился, ожидая пока будет обслужен его запрос на приобретение блокировки.

Итак, у нас есть возможность собрать воедино имеющееся оборудование и создать нечто, что будет работать как единая, большая система; и у нас есть возможность защитить всю систему от проблем, возникающих в отдельных ее частях. Но это сложно и почему у нас должно появиться желание возиться с чем-то сложным?

Для чего это надо?

Всякий раз, знакомясь с новой технологией или с какой-то ее функцией, мы должны задавать себе вопрос: зачем нам это надо – какие преимущества или выгоды мы получим? Если у вас не получится объяснить, что вы надеетесь получить, тогда вы не сможете решить, как лучше использовать технологию и как измерить степень успеха.

В пользу продвижения RAC есть два основных аргумента – масштабируемость и отказоустойчивость, причем аргумент масштабируемости делится на два более мелких подаргумента: высокая пропускная способность и короткое время отклика. То есть, прежде чем начать прикручивать RAC, нужно решить, какой из двух аргументов наиболее важен и как лучше реализовать RAC в своих условиях, чтобы сказку сделать былью.

Отказоустойчивость

Согласно теории отказоустойчивости систем, если на одном из узлов RAC произойдет сбой, один из оставшихся узлов должен мгновенно выполнить восстановление транзакций, подтвержденных на узле, где случился сбой, и произвести перераспределение нагрузки между узлами. Восстановление должно выполняться прозрачно для приложений (однако, такая прозрачность невозможна в отношении незавершенных транзакций без переделки приложений). Обычно этот аргумент влечет за собой четыре вопроса:

К числу альтернативных технологий можно отнести горячее резервирование на уровне операционной системы, которое может предусматриваться ее поставщиком, или создание резервной базы данных, что может устроить тех, кто желает ограничиться исключительно технологиями Oracle – оба варианта поддерживают возможность включения в работу резервной машины в роли сервера баз данных. Недостатки этих альтернатив заключается в более длинном периоде времени, необходимом для перехода с основной машины на резервную; резервная машина будет в основном простаивать и может даже ухудшать время отклика системы в целом. Настроить резервный сервер можно очень быстро, только нужно предусмотреть, чтобы приложения могли быстро находить его.

Теперь о слабых звеньях – отказы каких компонентов вы собираетесь учитывать? Мы легко можем поставить две сетевых карты в машину и продублировать сетевые коммутаторы, но продублировать хранилище или кабель сети намного сложнее – и какая стратегия реагирования на пропадание электропитания используется в вашем вычислительном центре? Можно также принять во внимание сложность всего стека RAC и задаться вопросом: сколько времени вы готовы выделить на обслуживание и обновление ПО. В Oracle Corp. постоянно выпускают обновления и кто-то, когда-то должен эти обновления накладывать.

Масштабируемость

Существует два преобладающих представления о масштабируемости:

О первом варианте лучше размышлять в терминах отдельных больших заданий, а о втором – в терминах большого числа маленьких заданий. Если, к примеру, пакетная обработка информации занимает 40 минут, ее распределение по двум экземплярам может уменьшить время обработки до 20 минут, распределение по четырем узлам – до 10 минут. Такое представление несет на себе отпечаток представлений о параллельном выполнении, и такая ассоциация вполне оправданна. Если вы надеетесь уменьшить время обработки, не переписывая алгоритм, вы, вероятно, сможете получить выгоды от добавления узлов и за счет параллельной обработки. Часто параллельная обработка позволяет решить проблему производительности, но она влечет увеличение накладных расходов на обмен служебными сообщениями между параллельно действующими подчиненными процессами, и эти накладные расходы становятся особенно заметными, когда подчиненные процессы выполняются в разных экземплярах. Если требуется ускорить выполнение больших заданий (не изменяя код реализации), возможно стоит подумать об увеличении объема памяти, числа процессоров или более быстрых процессоров, прежде чем увеличивать сложность организации системы.

Если ваша цель состоит в том, чтобы выполнить больше заданий за единицу времени, например, ваше предприятие расширяется и требуется дать возможность работать с системой большему числу сотрудников, тогда добавление новых экземпляров позволит увеличившемуся числу сотрудников работать одновременно. Если, скажем, в вашей организации 50 сотрудников успешно работают с одним экземпляром, тогда, возможно, вы сможете организовать плодотворную работу 100 сотрудникам на двух экземплярах, а 200 сотрудникам – на четырех. Вам достаточно будет просто добавлять новые экземпляры с увеличением штата.

В пользу этой стратегии говорит тот факт, что каждый экземпляр имеет свой процесс записи в журнал (lgwr) и свой набор файлов журнала (redo log files) – как известно, скорость создания и обработки записей повторения является наиболее узким местом в Oracle. К недостаткам можно отнести увеличение числа процессов (разбросанных по разным экземплярам), выполняющих похожие задания, из-за чего могут возникать чрезмерно активные области в данных. В RAC появление таких областей означает увеличение трафика между экземплярами, а это влечет специфические проблемы производительности.

И снова вы можете спросить: почему бы с ростом числа сотрудников просто не увеличить мощность единственной машины. Дело в том, что «увеличить мощность» машины не так-то просто, особенно в сравнении с покупкой другой машины и включением ее в сеть. На самом деле, одно из рекламируемых преимуществ RAC заключается в простоте планирования наращивания возможностей – вам не нужно сразу покупать большую машину и использовать ее не на полную мощность пару лет. Вы можете начать с недорогой машины и постепенно наращивать кластер по мере необходимости.

Oracle Grid

Существует еще один аспект, говорящий в пользу создания кластера вместо использования отдельных мощных машин, и этот аспект – инфраструктура Grid и некоторые ее улучшения в Oracle 11.2. Если у вас имеется кластер с большим числом маленьких машин (на которых пока нет действующих экземпляров Oracle), вы сможете разместить множество баз данных на своей дисковой ферме, определить число экземпляров на каждой машине для каждого приложения и распределять рабочую нагрузку динамически. На рис. 2 показана схема организации подобного кластера с двумя конфигурациями.

Одна – для использования в обычные рабочие дни, когда на каждой машине действует отдельный экземпляр базы данных (исключая экземпляры управления хранилищем, ASM). И другая, с двумя машинами GL, начинающими действовать как WEB-экземпляры в выходные дни, когда нагрузка на систему учета, скорее всего, снизится, а на веб-приложение увеличится.

rac oracle что это. Смотреть фото rac oracle что это. Смотреть картинку rac oracle что это. Картинка про rac oracle что это. Фото rac oracle что это

Рис. 2. Динамическое перераспределение нагрузки

Если внимательно рассмотреть эту схему, можно заметить, что я предпочитаю следовать стратегии (предложенной Джеймсом Морли (James Morle)) хранения множества баз данных в единой сети хранения данных.

Этот сценарий можно также расширить возможностью запуска дополнительного экземпляра GL на машине HR в конце месяца; а для большей отказоустойчивости можно даже запустить два экземпляра HR (второй – на одной из машин GL) в специальном режиме активный/пассивный (см. примечание) на случай, если один экземпляр HR выйдет из строя по каким-то причинам.

Примечание. Я упоминал, что взаимодействия между экземплярами являются важнейшим аспектом работы RAC. Существует реализация особого случая для RAC с двумя узлами, избавляющая от лишних накладных расходов, когда один экземпляр работает, а другой ничего не делает, ожидая пока первый выйдет из строя. Этот вариант известен как режим активный/пассивный и может быть интересен тем, кому требуется держать две или более базы данных на небольшом кластере с высокой скоростью восстановления после отказов.

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

Как это работает?

При рассмотрении схемы кластера из восьми машин, где выполняются экземпляры Oracle, работающие с одной и той же базой данных, невольно возникает вопрос: как один экземпляр, желающий изменить блок, может быть уверенным, что этот же блок не будет одновременно изменен другими семью экземплярами, и данная проблема не будет разрастаться с увеличением числа экземпляров. Такую уверенность дает гений реализации – в кластерах, с числом экземпляров три или больше, уровень накладных расходов перестает увеличиваться. Чтобы убедиться в этом, познакомимся сначала с глобальным каталогом ресурсов (Global Resource Directory, GRD) – распределенным механизмом управления доступом к «вещам» и технологией общего кэша в кластере (Cache Fusion), позволяющей своевременно перемещать по кластеру наиболее важные «вещи» (блоки данных).

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

В RAC предусмотрено два основных механизма для решения проблем координации работы нескольких экземпляров.

Примечание. Начиная обсуждение таких механизмов, как GCS и Cache Fusion, стоит упомянуть, что экземпляры не имеют прямого доступа к SGA друг друга – они обмениваются сообщениями, запрашивая информацию посредством LMSn и LMD.

Вот в этой мы исследовали создание в Oracle ресурсов для представления объектов. В RAC требуется создавать еще больше ресурсов для представления еще большего числа объектов – и у нас должен быть механизм блокировки (постановки в очередь) этих ресурсов и обеспечения доступа к ним всем экземплярам. Это ведет нас к двум представлениям – v$dlm_ress (распределенный диспетчер блокировки ресурсов) и v$ges_enqueue (блокировки, известные глобальной службе очередей, ранее носило имя v$dlm_locks) – и стратегии GRD (Global Resource Directory – глобальный каталог ресурсов).

Существует две основные проблемы, которые Oracle решает с применением GRD. Первая: хранение информации об очень большом числе объектов – каждом элементе в кэше словаря, каждом блоке данных в памяти и т. д. – поэтому данная проблема намного масштабнее и имеет значительно больше аспектов, чем проблема, обсуждавшаяся нами в связи с блокировкой таблиц, файлов и других объектов. Вторая: наличие множества экземпляров – не может не вызывать беспокойства необходимость постоянного копирования информации о блокировках в каждый узел, что влечет за собой рост объема передаваемой информации в геометрической прогрессии с увеличением числа экземпляров в кластере. К счастью, вторая проблема просто не существует – нет необходимости клонировать тот же самый каталог GRD во все экземпляры, потому что они могут совместно использовать единственную копию, хотя способ совместного использования выглядит весьма нетривиальным, как мы вскоре убедимся в этом.

Примечание. В ранних версиях RAC (и в предшествующей технологии Oracle Parallel Server, OPS) использовалась единственная блокировка, охватывающая либо диапазон, либо группу блоков, соответствующих некоторому «шаблону», а механизм «избирательного блокирования» применялся в особых случаях. В новейших версиях избирательное блокирование (одна блокировка = один блок) используется по умолчанию, возможность блокирования группы блоков единственной блокировкой превратилась в особый случай. Принципиальным исключением являются табличные пространства, доступные только для чтения, которые требуют единственной блокировки для каждого файла.

Помимо обзора самих представлений, масштаб этих структур можно оценить еще двумя способами – в v$sgastat и в v$resource_limit.

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

В представлении v$sgastat намного больше строк, чем я показал, но я оставил только те результаты, которые могут послужить отправной точкой в экскурс по GRD. Обратите внимание, что представление v$sgastat отражает только очереди GES, а v$resource_limit – блокировки GES. В них отсутствует информация об очередях и или блокировках GCS. Механизм очередей/блокировок, реализованный в службе GES, применяет блокировки к кэшированным и к традиционным ресурсам.

Также большой интерес представляет информация о теневых ресурсах GCS (GCS shadows). Oracle отделяет обслуживание обычных очередей от обслуживания кэша, так как при работе с кэшем частота операций и размеры пакетов, которые должны передаваться через соединения, намного больше, соответственно для глобального кэша ресурсов была создана отдельная структура. Но существует еще одна причина создания отдельной структуры. Когда экземпляр завершается в результате аварии, можно особо не беспокоиться о том, что какие-либо блокировки не будут освобождены. Большее беспокойство должны вызывать блоки данных, оставшиеся в его кэше, и их состояние – чтобы отследить местоположение и состояние блоков, служба GCS реализует очень сложный алгоритм, требующий дополнительной инфраструктуры. Поэтому в Oracle имеется отдельная структура для поддержки глобального кэша ресурсов, даже при том, что некоторые объекты v$ скрывают это разделение.

Но кроме отдельного списка ресурсов существует еще кое-что – представление отображает значения gcs RESOURCES и gcs SHADOWS. И это именно те значения, которые подсказывают нам, как Oracle обслуживает глобальный каталог ресурсов. Oracle разделяет ответственность за управление ресурсами между всеми экземплярами в кластере. Но каждый экземпляр, использующий ресурс в настоящий момент, хранит теневой ресурс, содержащий критически важное подмножество информации из ведущего (master) ресурса – и в случае с кэшем ресурсов мы имеем явное представление занимаемой им памяти.

Ведущие и теневые ресурсы

Прежде чем переходить к обсуждению тонкостей управления глобальным кэшем, я хочу сделать несколько замечаний о том, как Oracle поддерживает владение ресурсами. По сути этот механизм основан на случайном распределении с применением функции хэширования. Если экземпляр хочет получить информацию о глобальном состоянии ресурса, он вычисляет хэш-значение идентичности ресурса и затем определяет, какой экземпляр является владельцем этого ресурса. Так, например, если экземпляру потребуется применить блокировку к таблице XYZ, он должен произвести некоторые арифметические вычисления с идентификатором (id) таблицы и узнать, какой узел владеет ресурсом TM для этой таблицы. Затем он должен обратиться к этому экземпляру и узнать, не заблокировал ли эту таблицу какой-то другой экземпляр в несовместимом режиме.

Переподчинение

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

Если Oracle обнаруживает, что объект данных используется в некотором экземпляре намного чаще, чем в других, он может игнорировать обычный способ определения владельца ресурса на основе арифметических вычислений и сделать экземпляр владельцем ресурса для всех блоков этого объекта. (Реализация этого процесса претерпела три стадии: (а) вообще отсутствовала, (б) поддерживала переподчинение на уровне файла, (в) поддерживала переподчинение на уровне объекта (сегмента данных)).

Так как число объектов данных в базе данных относительно невелико, в сравнении с числом блоков, каждый экземпляр может хранить карту с информацией обо всех объектах данных и соответствующих им владельцах, и всегда иметь возможность быстро найти владельца объекта данных, прежде чем выполнять обычные вычисления для отдельного блока. Основное влияние на алгоритм заключается в возможности динамического переподчинения объектов – при этом на короткое время может блокироваться каталог GRD (что означает блокировку всех экземпляров), чтобы ведущие ресурсы для объекта могли быть перемещены в нужный экземпляр. Это может занять несколько секунд – и если вам не повезет, вы обнаружите, что природа обработки результатов в нескольких объектах будет приводить к
постоянному их переподчинению. Последние версии Statspack и AWR предусматривают возможность получения статистики с числом событий переподчинения и списка переподчиняемых объектов, которые могут помочь в поисках потенциальных проблем.

В данном случае результаты показывают, что на всех трех узлах был ресурс ( v$dlm_ress ) с соответствующим именем; но только узел 1 содержит очереди ( gv$ges_enqueue ). Иными словами, узел 1 является владельцем – он знает все, что происходит с ресурсом TM – но два других узла тоже имеют некоторую информацию о состоянии ресурса, потому что в настоящий момент они являются заинтересованными сторонами. Ниже приводятся значения нескольких столбцов (расположенных по вертикали с помощью замечательной процедуры print_table Тома Кайта (Tom Kyte)) из представления gv$ges_enqueue :

Примечание. Динамические представления из Oracle с единственным экземпляром часто упоминаются как «представления v$», потому что их имена начинаются с префикса v$. Эти представления часто определяются внутри, как подмножества глобальных представлений, имена которых начинаются с префикса gv$, и ограничиваются единственным экземпляром. Если в действующей системе RAC выполнить запрос к одному из представлений gv$, экземпляр, которому передан запрос для выполнения, вызовет подчиненные процессы параллельного запроса в других экземплярах, обычно с именами, таким как PZ99 (вместо более привычного Pnnn). И даже если попытаться запретить параллельные запросы установкой параметра parallel_max_servers в нулевое значение, подчиненные процессы все равно останутся доступными в RAC.

Результаты показывают, что эти блокировки обслуживаются экземпляром с номером 1 – то есть, он является владельцем ресурса TM – а два других экземпляра ( owner_node ) в настоящий момент проявляют интерес. Из представленных выше результатов неочевидно, но нумерация inst_id начинается с единицы, а owner_node –
с нуля! В данном конкретном примере узел-владелец не имеет блокировки для ресурса, даже при том, что он является владельцем ресурса (о чем можно судить по номерам).

Обратите также внимание, что блокировки имеют параметры grant_level и request_level – в данном случае оба параметра содержат значение KJUSERCW (concurrent write (одновременная запись) – эквивалент блокировки в режиме монопольного владения строкой (row-exclusive lock), которые часто можно наблюдать в v$lock при изменении записей в таблице). Хотя ни одна из структур поддержки не видна ни в представлении, ни даже в базовой структуре x$, глобальные очереди (блокировки) поддерживают те же самые шаблоны хэш-таблиц, указателей и связанных списков, что и очереди в системах с единственным экземпляром.

Возможно, что ресурсы разных типов ведут себя немного по-разному (а ресурсы для кэша буферов – это вообще отдельный случай), и возможно, что разные уровни блокировок приводят к разным результатам, но как бы то ни было, вы увидите теневые ресурсы с присоединенными блокировками. В этом случае блокировки присоединяются к теневым ресурсам только в теневых узлах. Ниже, например, приводится список глобальных блокировок для конкретного ресурса (ресурс QQ – это один из типов ресурсов кэша словаря, имеющий отношение к гистограммам):

rac oracle что это. Смотреть фото rac oracle что это. Смотреть картинку rac oracle что это. Картинка про rac oracle что это. Фото rac oracle что это

Рис. 3. Графическое представление ведущих и теневых ресурсов в кластере с тремя узлами

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

GCS и GES

Еще одно важное замечание – Oracle обслуживает огромное число ресурсов. Ниже приводятся результаты выполнения пары запросов, которые я выполнил на одном из узлов в кластере с тремя узлами, спустя всего несколько минут после запуска экземпляров. Функции instr () и substr () я использовал, только чтобы получить типы ресурсов (двухсимвольные коды из v$locktype ), а кроме того я сократил вывод, оставив только ресурсы с наибольшими значениями счетчика:

Как видите, ресурсы Qx – представляющие кэш словаря – весьма многочисленны, и их число увеличивается еще больше при наличии таблиц секционированных таблиц (partitioned tables) с большим числом секций и большого числа гистограмм. Еще одной многочисленной разновидностью ресурсов являются ресурсы типа BL type – блоки. В данном примере число ресурсов BL значительно меньше числа ресурсов Qx, но в процессе работы базы данных их число будет расти.

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

На практике базы данных обычно имеют некоторые «популярные» области с несколькими копиями каждого блока в каждом экземпляре – то есть, число ведущих ресурсов BL часто оказывается значительно меньше общего числа буферов. С другой стороны, значительная доля буферов данных в экземпляре хранит блоки, которые должны быть защищены, а экземпляр, не владеющий ведущим ресурсом блока, будет хранить его теневой ресурс, поэтому общее число ресурсов BL (ведущих и теневых) будет примерно равно общему числу буферов. К счастью, для теневого ресурса выделяется значительно меньше памяти, чем для ведущего.

Примечание. Следя за обсуждением кэша буферов, старайтесь разделять блоки и буферы. Буферы используются для временного хранения копий (текущих, устаревших или согласованных) блоков, и операции обычно выполняются со связанными списками буферов. Однако, когда выполняется поиск данных, используются адреса блоков на диске, которые никак не связаны с адресами буферов в памяти. Ресурсы типа BL используются в RAC для защиты блоков – значения id1/id2, которые поставляются вместе с ресурсом BL, определяют адрес блока – но не для защиты буферов.

Несмотря на то, что число ресурсов Qx может быть очень большим и даже сопоставимо с числом ресурсов BL – между этими двумя типами ресурсов существуют два важных отличия. Во-первых, кэш словаря (Qx) остается достаточно стабильным; спустя несколько минут после запуска в кэш словаря будет загружена почти вся необходимая информация и будет изменяться, например, только при попытках получить новые статистики для объектов. Такое постоянство означает, что размер кэша никак не угрожает производительности. Исключение составляют только гистограммы, чрезвычайно большое число существенно сказывается на размере кэша словаря и может вызывать проблемы.

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

И еще одно, по-настоящему важное отличие – ресурсы BL связаны с объектами (блоками), которые фактически передаются между экземплярами. Большинство ресурсов всего лишь играют роль защитного механизма, но если какому-то экземпляру потребуется установить блокировку BL, он должен получить сам блок. Именно для этого был создан механизм GCS с процессами LMS – служба GES выдает право на доступ к блоку, а GCS – позволяет получить фактический блок.

Cache Fusion

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

Каждый раз, когда экземпляр в RAC читает блок с диска в память, он запускает процедуру создания ресурса, который будет представлять состояние блока. Фактически, перед тем, как экземпляр прочитает блок с диска, он определит, где должен находиться соответствующий ресурс, и пошлет запрос экземпляру-владельцу, чтобы узнать – не находится ли нужный блок в кэше, потому что в этом случае он сможет запросить у текущего владельца переслать ему требуемый блок. Экземпляр-читатель должен выполнить одну из двух последовательностей шагов. Первая последовательность:

Вторая последовательность (см. рис. 4):

Когда экземпляр-читатель получает блок, он отправляет сообщение экземпляру-владельцу, извещая, что блок получен, и создает теневой ресурс с блокировкой.

rac oracle что это. Смотреть фото rac oracle что это. Смотреть картинку rac oracle что это. Картинка про rac oracle что это. Фото rac oracle что это

Рис. 4. Трехсторонний способ передачи блока в кластере с четырьмя узлами

На рис. 4, где изображен кластер RAC с четырьмя узлами, можно увидеть наиболее важные особенности реализации RAC – совершенно неважно, сколько узлов имеется в кластере, в худшем случае в процедуру перемещения блока будет вовлечено не более трех узлов:

Несмотря на то, что последовательность работы единого кэша (Cache Fusion) никогда не превышает трех шагов, влияние на производительность увеличивается с увеличением числа узлов, потому что увеличивается вероятность выполнения трехшаговой последовательности.

Рассмотрим следующую ситуацию: В системе RAC с тремя узлами вероятность, что данный узел будет владельцем требуемого ему ресурса, равна одной трети – то есть, один шанс из трех, что сеанс сможет прочитать его по своему требованию или по требованию другого узла (двусторонний сценарий). Если данный узел не является владельцем, он должен послать сообщение экземпляру-владельцу. Если блок уже находится где-то в памяти, есть вероятность 50/50, что владелец хранит блок и может передать его запрашивающему узлу (двусторонний сценарий), иначе ему придется в свою очередь обратиться к другому (третьему) узлу с просьбой переслать блок данному узлу (трехсторонний сценарий).

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

Возможно, лучше понять вышесказанное вам помогут некоторые числа (полученные в ходе выполнения строго контролируемого сценария). Я настроил кластер RAC с тремя узлами и запустил по одному сеансу на каждом узле, в рамках которых выполнялось по 100 запросов на выборку и изменение (с подтверждением) единственного блока в быстром цикле. Ниже приводится три набора статистик для событий ожидания (я оставил только наиболее интересные), полученные в результате:

Нетрудно заметить, что результаты получились несимметричными, и немного подумав, нетрудно понять, что первый набор значений получен из узла, который хранит ведущий ресурс для запрашиваемого блока. Всякий раз, когда ему требуется получить последнюю версию блока обратно, в свой кэш, он знает, кто хранит эту копию, поэтому всегда использует двусторонний сценарий. (Статистика gc cr block 2-way соответствует операции выборки ( SELECT ), а статистика gc current block 2-way – операции изменения ( UPDATE ).) Другие два узла, напротив, вынуждены обращаться к первому узлу, чтобы получить нужный блок. В половине случаев первый узел отвечает: «я храню последнюю копию», – и мы наблюдаем двусторонний сценарий; а в другой половине случаев первый узел отвечает: «последнюю копию хранит другой узел», – и мы наблюдаем трехсторонний сценарий.

Если аналогичный тест выполнить в кластере с четырьмя узлами, вы все еще будете видеть, что узел-владелец в худшем случае выполняет двусторонний сценарий, но другие три узла в 33 случаях из 100 будут выполнять двусторонний сценарий, и в 66 случаях из 100 – трехсторонний. Вы также можете заметить, что трехсторонние операции выполняются медленнее двусторонних.

Примечание. Рассматривая механизм обмена данными в кластере RAC, в частности механизм передачи блоков данных между экземплярами, его работу можно оценивать с двух точек зрения. Кто-то может сказать, что дает определенные выгоды, потому что блоки передаются по сети, а это быстрее, чем читать их с диска. Кто-то, напротив, может сказать что он дает лишнюю нагрузку, и почему бы не отказаться от идеи создания кластера и просто не увеличить объем ОЗУ? Если вы считаете, что создание кластера RAC влечет дополнительные накладные расходы, тогда спросите себя: зачем вам вообще использовать его? Если ваш выбор сделан на основании веских причин, тогда нет смысла рассматривать трафик между узлами как накладные расходы. (Я не призываю вас полностью игнорировать эту проблему – всегда есть смысл избавиться от лишней работы, если есть такая возможность – и в RAC есть множество ее решений, одним из которых является минимизация числа блоков, нужных всем узлам.)

Следствия

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

CUR или CR

Когда один узел запрашивает у другого переслать ему блок, влияние этого запроса во многом зависит от того, требуется ли получить согласованную копию блока или текущий блок. Если нужен текущий блок, тогда другой узел закрепляет соответствующий буфер в монопольном режиме и перед отправкой блока выталкивает текущее содержимое буфер журнала на диск, что отражается на статистиках gc current block pin time и gc current block flush time (оба значения измеряются в сантисекундах (сотые доли секунды)). Однако, после отправки блока, его буфер перестает быть текущим – текущим становится буфер в узле, получившем блок, – но несколько лучше, чем создание согласованной копии, потому что эта версия блока действительно была текущей какое-то время, поэтому Oracle дает ей статус PI (Past Image – прошлый образ).

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

С другой стороны, если экземпляр, получивший блок, запишет измененную копию на диск, как тогда следует поступить с прошлым образом в другом экземпляре? Он стал ненужным, что с ним следует сделать? Посмотрим на ситуацию с другого конца. Если другому экземпляру потребуется удалить прошлый образ (PI) из памяти, чтобы использовать буфер для другого блока, должен ли он предпринять какие-то особые шаги, учитывая, что имеет дело с прошлым образом (PI) – и имеет ли значение тот факт, что прошлый образ может быть «грязным» или «чистым»? Интересно было бы также узнать, может ли еще какой-то узел создать согласованную версию блока на основе прошлого образа (PI), не требуя от другого сконструировать эту версию из текущей версии блока.

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

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

Чтение текущих версий

Через соединения между узлами передаются не только сообщения, касающиеся блоков данных. Мы уже видели, что наличие прошлых образов может вызывать передачу дополнительных сообщений между экземплярами. Необходимо также посмотреть, что происходит с состоянием (в x$bh.state ) блока, когда выполняется его чтение в буфер.

Примечание. Имея привилегии SYS, вы можете выполнить следующий запрос, чтобы узнать, сколько блоков имеет такой статус: select state, count(*) from x$bh group by state ;. Чаще всего встречаются состояния: 0 – свободный, 1 – XCUR (исключительная текущая версия), 2 – SCUR (разделяемая текущая версия), 3 – CR (доступен только для согласованного чтения), 8 – PI (прошлый образ). Это довольно тяжелый запрос, поэтому я не рекомендую выполнять его на промышленной системе с большим кэшем буферов.

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

Только один блок может быть текущим, но может существовать масса прошлых образов и согласованными копиями, появление которых может быть вызвано самыми разными действиями.

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *