Oracle для профессионалов. Глава 2. Часть 1Источник: CITFORUM Том Кайт
АрхитектураOracle проектировалась как максимально переносимая СУБД, - она доступна на всех распространенных платформах. Поэтому физическая архитектура Oracle различна в разных операционных системах. Например, в ОС UNIX СУБД Oracle реализована в виде нескольких отдельных процессов операционной системы - практически каждая существенная функция реализована отдельным процессом. Для UNIX такая реализация подходит, поскольку основой многозадачности в ней является процесс. Для Windows, однако, подобная реализация не подходит и работала бы не слишком хорошо (система получилась бы медленной и плохо масштабируемой). На этой платформе СУБД Oracle реализована как один многопоточный процесс, т.е. с использованием подходящих для этой платформы механизмов реализации. На мэйнфреймах IBM, работающих под управлением OS/390 и zOS, СУБД Oracle использует несколько адресных пространств OS/390, совместно образующих экземпляр Oracle. Для одного экземпляра базы данных можно сконфигурировать до 255 адресных пространств. Более того, СУБД Oracle взаимодействует с диспетчером загрузки OS/390 WorkLoad Manager (WLM) для установки приоритетности выполнения определенных компонентов Oracle по отношению друг к другу и к другим задачам, работающим в системе OS/390. В ОС Netware тоже используется многопоточная модель. Хотя физические средства реализации СУБД Oracle на разных платформах могут отличаться, архитектура системы - достаточно общая, чтобы можно было понять, как СУБД Oracle работает на всех платформах. В этой главе мы рассмотрим три основных компонента архитектуры Oracle.
СерверТрудно решить, с какого компонента сервера начать описание. Процессы используют область SGA, поэтому рассматривать SGA до процессов не имеет смысла. С другой стороны, при описании процессов и их функционирования придется ссылаться на компоненты SGA. Они тесно взаимосвязаны. С файлами работают процессы, и их нет смысла описывать, пока не объяснено, что делают процессы. Ниже определены некоторые термины и сделан общий обзор сервера Oracle, после чего подробно рассматриваются отдельные компоненты. Два термина в контексте Oracle вызывают большую путаницу. Речь идет о терминах "база данных" и "экземпляр". В соответствии с принятой в Oracle терминологией, эти понятия определяются так:
Эти два термина иногда взаимозаменяемы, но представляют принципиально разные концепции. Взаимосвязь между ними такова, что база данных может быть смонтирована и открыта в нескольких экземплярах. Экземпляр может смонтировать и открыть только одну базу данных в каждый момент времени. Не обязательно отрывать и монтировать одну и ту же базу данных при каждом запуске экземпляра. Стало еще непонятнее? Вот ряд примеров, которые помогут прояснить ситуацию. Экземпляр - это набор процессов операционной системы и используемая ими память. Все эти процессы могут работать с базой данных, которая представляет собой просто набор файлов (файлов данных, временных файлов, файлов журнала повторного выполнения, управляющих файлов). В каждый момент времени с экземпляром связан только один набор файлов. В большинстве случаев обратное утверждение тоже верно; с базой данных работает только один экземпляр. В случае же использования параллельного сервера Oracle (Oracle Parallel Server - OPS), опции Oracle, позволяющей серверу функционировать на нескольких компьютерах в кластерной среде, одна и та же база данных может быть одновременно смонтирована и открыта несколькими экземплярами. Это делает возможным доступ к базе данных одновременно с нескольких компьютеров. Oracle Parallel Server позволяет создавать системы с высокой доступностью данных и, при условии правильной реализации, очень масштабируемые. Рассмотрение опции OPS здесь не предусмотрено, поскольку для описания особенностей ее реализации потребовалась бы отдельная книга. Итак, в большинстве случаев между базой данных и экземпляром имеется отношение один к одному. Это, вероятно, и является причиной путаницы при использовании этих терминов. По опыту большинства пользователей, база данных - это экземпляр, а экземпляр - это база данных. Во многих тестовых средах это, однако, не так. На моем диске, например, может быть пять отдельных баз данных. На тестовой машине СУБД Oracle установлена в одном экземпляре. В каждый момент времени работает только один экземпляр, но обращаться он может к разным базам данных, в зависимости от задач, которые я решаю. Создав несколько конфигурационных файлов, я могу монтировать и открывать любую из этих баз данных. В данном случае у меня один "экземпляр", но несколько баз данных, лишь одна из которых доступна в каждый момент времени. Итак, теперь под термином "экземпляр" мы будем понимать процессы и память сервера Oracle. Термин "база данных" означает физические файлы, в которых находятся данные. База данных может быть доступна многим экземплярам, но экземпляр в каждый момент времени обеспечивает доступ только к одной базе данных. Теперь можно приступать к рассмотрению абстрактной схемы СУБД Oracle. Упрощенно, СУБД Oracle включает большую область памяти - SGA, - содержащую внутренние структуры данных, доступ к которым необходим всем процессам для кеширования данных с диска, кеширования данных повторного выполнения перед записью на диск, хранения планов выполнения разобранных операторов SQL и т.д. Имеется также набор процессов, подключенных к этой области SGA, причем механизм подключения в каждой операционной системе другой. В среде UNIX процессы физически подключаются к большому сегменту разделяемой памяти - выделенному ОС фрагменту памяти, к которому может одновременно обращаться несколько процессов. В ОС Windows для выделения памяти процессы используют библиотечную функцию malloc() языка C, поскольку они сами являются потоками одного большого процесса. В СУБД Oracle также имеется набор файлов, читаемых и записываемых процессами/потоками базы данных (причем читать и записывать эти файлы имеют право только процессы Oracle). В этих файлах хранятся данные таблиц, индексов, временное пространство, журналы повторного выполнения и т.д. Если запустить СУБД Oracle в UNIX-системе и выполнить команду ps (для просмотра состояния процессов), можно увидеть количество работающих процессов и их имена. Например: $ /bin/ps -aef / grep ora816 ora816 20827 1 0 Feb 09 ? 0:00 ora_d000_ora816dev ora816 20821 1 0 Feb 09 ? 0:06 ora_smon_ora816dev ora816 20817 1 0 Feb 09 ? 0:57 ora_lgwr_ora816dev ora816 20813 1 0 Feb 09 ? 0:00 ora_pmon_ora816dev ora816 20819 1 0 Feb 09 ? 0:45 ora_ckpt_ora816dev ora816 20815 1 0 Feb 09 ? 0:27 ora_dbw0_ora816dev ora816 20825 1 0 Feb 09 ? 0:00 ora_s000_ora816dev ora816 20823 1 0 Feb 09 ? 0:00 ora_reco_ora816dev Я еще опишу назначение каждого из этих процессов, но часто их в совокупности называют просто фоновыми процессами Oracle. Это - постоянно работающие процессы, образующие экземпляр; они появляются при запуске СУБД и работают до тех пор, пока она не будет остановлена. Интересно отметить, что все это - процессы, а не программы. СУБД Oracle реализуется одной программой в UNIX, но программа эта многолика. Программа, которая запускалась для реализации процесса ora_lgwr_ora816dev, была использована и для запуска процесса ora_ckpt_ora816dev. Есть только один двоичный файл с именем oracle. Просто он выполняется несколько раз с разными именами. В ОС Windows с помощью программы tlist, входящей в Windows resource toolkit, можно обнаружить только один процесс - Oracle.exe. В случае NT тоже есть всего одна двоичная программа. Этот процесс создает несколько потоков, представляющих фоновые процессы Oracle. С помощью утилиты tlist (или любого из множества подобных средств) можно увидеть эти потоки: C:\Documents and Settings\Thomas Kyte\Desktop>tlist 1072 1072 ORACLE.EXE CWD: C:\oracle\DATABASE CmdLine: c:\oracle\bin\ORACLE.EXE TKYTE816 VirtualSize: 144780 KB PeakVirtualSize: 154616 KB WorkingSetSize: 69424 KB PeakWorkingSetSize: 71208 KB NumberOfThreads: 11 0 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Initialized 5 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Initialized 5 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Initialized 5 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Initialized 5 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Initialized 5 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Initialized 5 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Initialized 5 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Initialized 5 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Initialized 5 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Initialized 5 Win32StartAddr:0x00000000 LastErr:0x00000000 State:Initialized 0.0.0.0 shp 0x00400000 ORACLE.EXE 5.0.2163.1 shp 0x77f80000 ntdll.dll 0.0.0.0 shp 0x60400000 oraclient8.dll 0.0.0.0 shp 0x60600000 oracore8.dll 0.0.0.0 shp 0x60800000 oranls8.dll ... В данном случае имеется 11 потоков, выполняющихся в рамках одного процесса Oracle. Если подключиться к базе данных, количество потоков увеличится до 12. В ОС UNIX к существующим процессам oracle просто добавился бы еще один. Теперь можно представить следующую схему. Предыдущая схема представляла концептуальный вид СУБД Oracle сразу после запуска. Теперь, если подключиться к СУБД Oracle в наиболее типичной конфигурации, схема будет выглядеть примерно так: ... Обычно СУБД Oracle при подключении пользователя создает новый процесс. Это принято называть конфигурацией выделенного сервера , поскольку на все время сеанса ему выделяется отдельный серверный процесс. Сеансы и выделенные серверы находятся в отношении один к одному. Клиентский процесс (любая программа, пытающаяся подключиться к СУБД) будет непосредственно взаимодействовать с соответствующим выделенным сервером по сети, например, через сокет TCP/IP. Именно этот сервер будет получать и выполнять SQL-операторы. Он будет читать файлы данных, а также искать необходимые данные в кеше. Он будет выполнять операторы UPDATE и PL/SQL-код. Единственное его назначение - отвечать на получаемые SQL-запросы. СУБД Oracle также может работать в режиме многопоточного сервера (multi-threaded server - MTS), в котором при подключении не создается дополнительный поток или процесс UNIX. В режиме MTS СУБД Oracle использует пул "разделяемых серверов" для поддержки большого количества пользователей. Разделяемые серверы - это просто механизм организации пула подключений. Вместо запуска 10000 выделенных серверов (это действительно много, если речь идет о процессах или потоках) для 10000 сеансов режим MTS позволяет обслуживать их с помощью гораздо меньшего количества разделяемых серверов, которые (как следует из названия) будут совместно использоваться всеми сеансами. Это позволяет СУБД Oracle поддерживать намного больше сеансов, чем в режиме выделенного сервера. Машина, на которой работает сервер, может не справиться с поддержкой 10000 процессов, но управление 100 или 1000 процессами для нее вполне реально. В режиме MTS разделяемые серверные процессы обычно запускаются сразу при старте СУБД и отображаются в списке, выдаваемом командой ps (в представленных выше результатах выполнения команды ps процесс ora_s000_ora816dev представляет собой разделяемый серверный процесс). Принципиальное отличие режима MTS от режима выделенного сервера состоит в том, что клиентский процесс, подключившийся к СУБД, никогда не взаимодействует непосредственно с разделяемым сервером, как это происходит в случае выделенного сервера. Он не может взаимодействовать с разделяемым сервером, так как соответствующий процесс используется совместно. Чтобы обеспечить совместное использование этих процессов, необходим другой механизм взаимодействия. Для этого в СУБД Oracle используется процесс (или набор процессов), которые называют диспетчерами . Клиентский процесс взаимодействует по сети с процессом-диспетчером. Процесс-диспетчер помещает запрос клиента в очередь запросов в SGA (это одно из многих назначений области SGA). Первый же свободный разделяемый сервер выберет и обработает этот запрос (например, запрос может иметь вид UPDATE T SET X = X+5 WHERE Y = 2). По завершении выполнения команды разделяемый сервер поместит ответ в очередь ответов. Процесс-диспетчер следит за очередью и немедленно передает полученный результат клиенту. Концептуально поток информации в режиме MTS выглядит следующим образом: ... Клиентское подключение посылает запрос диспетчеру. Диспетчер поместит этот запрос в очередь запросов в области SGA (1). Первый свободный разделяемый сервер выберет этот запрос (2) из очереди и обработает его. Когда разделяемый сервер закончит выполнение, ответ (коды возврата, данные и т.д.) помещается в очередь ответов (3), после чего выбирается диспетчером (4) и возвращается клиенту. С точки зрения разработчика нет никакой разницы между подключением к серверу в режиме MTS и подключением к выделенному серверу. Теперь, когда стало понятно, как происходит подключение к выделенному и разделяемому серверу, возникают вопросы: а как вообще подключиться; как запускается выделенный сервер и как связываться с процессом-диспетчером? Ответы зависят от платформы, но в принципе все происходит так, как описано ниже. Мы рассмотрим наиболее общий случай: запрос на подключение по сети с использованием протоколов TCP/IP. В этом случае клиент находится на одной машине, а сервер - на другой, причем эти машины связаны сетью на базе семейства протоколов TCP/IP. Все начинается с клиента. Он посылает запрос клиентскому ПО Oracle на подключение к базе данных. Например, выполняется команда: C:\> sqlplus scott/tiger@ora816.us.oracle.com Здесь клиентом является утилита SQL*Plus. scott/tiger - имя пользователя и пароль, а ora816.us.oracle.com - имя службы TNS. TNS - сокращение от Transparent Network Substrate (прозрачная сетевая среда), которое обозначает "базовое" программное обеспечение, встроенное в клиент Oracle и обеспечивающее удаленное подключение (двухточечное взаимодействие клиента и сервера). Строка подключения TNS указывает программному обеспечению Oracle, как подключаться к удаленной базе данных. В общем случае клиентское программное обеспечение обращается к файлу TNSNAMES.ORA. Это обычный текстовый файл конфигурации, обычно находящийся в каталоге [ORACLE_HOME]\network\admin и содержащий записи вида: ORA816.US.ORACLE.COM = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = aria.us.oracle.com)(PORT = 1521)) ) (CONNECT_DATA = (ORACLE_SID = ora816) ) ) Именно эти параметры конфигурации позволяют клиентскому ПО Oracle преобразовать строку ora816.us.oracle.com в необходимые для подключения данные: имя хоста; порт на этом хосте, прослушиваемый процессом, который принимает подключения; идентификатор SID (Site IDentifier) базы данных на хосте, к которой необходимо подключиться, и т.д. Эта строка, ora816.us.oracle.com, может преобразовываться в необходимые данные и по-другому. Например, она может преобразовываться с помощью службы Oracle Names - распределенного сервера имен для СУБД, аналогичного по назначению службе DNS, используемой для преобразования имен хостов в IP-адреса. Однако в большинстве небольших и средних серверов, где количество копий конфигурационных файлов невелико, чаще всего используется именно файл TNSNAMES.ORA. Теперь, когда клиентскому ПО известно, куда подключаться, оно открывает соединение через сокет TCP/IP к порту 1521 машины aria.us.oracle.com. Если администратор базы данных соответствующего сервера настроил службу Net8 и запустил процесс прослушивания, это подключение может быть принято. В сетевой среде на сервере работает процесс TNS Listener. Это процесс прослушивания, обеспечивающий физическое подключение к базе данных. Получив запрос на подключение, он проверяет его, используя собственные файлы конфигурации, и либо отвечает отказом (например, не существует запрашиваемой базы данных или IP-адрес подключающегося содержится в списке тех, кому не разрешено подключение к хосту), либо обеспечивает подключение клиента. При подключении к выделенному серверу процесс прослушивания автоматически запустит выделенный сервер. В ОС UNIX это делается с помощью системных вызовов fork() и exec() (единственный способ создать новый процесс после инициализации ОС UNIX - использовать системный вызов fork()). Теперь мы физически подключены к базе данных. В Windows процесс прослушивания требует от серверного процесса создания нового потока для подключения. После создания этого потока клиент "перенаправляется" на него, и тем самым обеспечивается физическое подключение. В случае ОС UNIX это можно представить следующей схемой4: ... В режиме MTS процесс прослушивания работает иначе. Ему известно, какие процессы-диспетчеры работают в составе экземпляра. При получении запроса на подключение процесс прослушивания выбирает процесс-диспетчер из пула доступных диспетчеров. Затем он посылает клиенту информацию, позволяющую подключиться к процессу-диспетчеру. Это необходимо, поскольку процесс прослушивания работает на известном порту соответствующего хоста, а вот диспетчеры будут принимать подключения через произвольно выделенные порты. Процессу прослушивания известны эти выделенные порты, поэтому он автоматически выбирает свободный диспетчер. Затем клиент отключается от процесса прослушивания и подключается непосредственно к диспетчеру. В результате устанавливается физическое соединение с СУБД. Графически это можно представить так: ... Итак, обзор архитектуры Oracle закончен. Мы описали, что такое экземпляр Oracle, что такое база данных и как можно подключиться к базе данных через выделенный и разделяемый сервер. На следующей схеме показано взаимодействие с сервером Oracle клиента, подключенного к разделяемому серверу, и клиента, работающего с выделенным серверным процессом. Один экземпляр Oracle может поддерживать оба типа подключений одновременно: ... Теперь подробно рассмотрим процессы, образующие сервер, их назначение и взаимодействие друг с другом, а также содержимое области SGA и назначение ее компонентов. Но начнем мы с описания различных типов файлов, которые сервер Oracle использует для управления данными. ФайлыВ состав базы данных и экземпляра входит шесть типов файлов. С экземпляром связаны файлы параметров. По этим файлам экземпляр при запуске определяет свои характеристики, например размер структур в памяти и местонахождение управляющих файлов. Базу данных образуют следующие файлы.
Наиболее важны первые два типа файлов, поскольку именно в них хранятся накопленные данные. В случае потери остальных файлов хранящиеся данные не пострадают. Если будут потеряны файлы журнала повторного выполнения, некоторые данные могут быть потеряны. Если же будут потеряны файлы данных и все их резервные копии, данные, безусловно, будут потеряны навсегда. Теперь давайте детально рассмотрим все типы файлов и их содержимое. Файлы параметровС базой данных Oracle связано много файлов параметров: от файла TNSNAMES.ORA на клиентской рабочей станции (используемого для поиска сервера) и файла LISTENER.ORA на сервере (для запуска процесса прослушивания Net8) до файлов SQLNET.ORA, PROTOCOL.ORA, NAMES.ORA, CMAN.ORA и LDAP.ORA. Наиболее важным является файл параметров инициализации экземпляра, потому что без него не удастся запустить экземпляр. Остальные файлы тоже важны; они связаны с поддержкой сети и обеспечением подключения к базе данных. Однако рассматриваться в этом разделе они не будут. Сведения об их конфигурировании и настройке можно найти в руководстве Oracle Net8 Administrators Guide . Обычно разработчик не настраивает эти файлы - они создаются администратором. Файл параметров инициализации экземпляра обычно называют файлом init или файлом init.ora. Это название происходит от стандартного имени этого файла, - init<ORACLE_SID>.ora. Например, экземпляр со значением SID, равным tkyte816, обычно имеет файл параметров инициализации inittkyte816.ora. Без файла параметров инициализации нельзя запустить экземпляр Oracle. Поэтому файл этот достаточно важен. Однако, поскольку это обычный текстовый файл, который можно создать в любом текстовом редакторе, сохранять его ценой собственной жизни не стоит. Для тех, кому незнаком термин SID или параметр ORACLE_SID, представлю полное определение. SID - это идентификатор экземпляра (сайта). В ОС UNIX он хешируется совместно со значением ORACLE_HOME (задающим каталог, в котором установлено ПО Oracle) для создания уникального ключа при подсоединении области SGA. Если значение ORACLE_SID или ORACLE_HOME задано неправильно, выдается сообщение об ошибке ORACLE NOT AVAILABLE, поскольку невозможно подключиться к сегменту разделяемой памяти, определяемому этим "магическим" ключом. В ОС Windows разделяемая память используется не так, как в ОС UNIX, но параметр SID все равно важен. В одном и том же базовом каталоге ORACLE_HOME может быть несколько баз данных, так что необходимо иметь возможность уникально идентифицировать их и соответствующие конфигурационные файлы. В Oracle файл init.ora имеет очень простую конструкцию. Он представляет собой набор пар имя параметра/значение. Файл init.ora может иметь такой вид: db_name = "tkyte816" db_block_size = 8192 control_files = ("C:\oradata\control01.ctl", "C:\oradata\control02.ctl") Фактически это почти минимальный файл init.ora, с которым уже можно работать. В нем указан размер блока, стандартный для моей платформы (стандартный размер блока различен для разных платформ), так что я могу эту строку удалить. Файл параметров инициализации используется для получения имени базы данных и местонахождения управляющих файлов. Управляющие файлы содержат информацию о местонахождении всех остальных файлов, так что они нужны в процессе начальной загрузки при запуске экземпляра. В файле параметров инициализации обычно содержится и много других параметров. Количество и имена параметров меняются с каждой новой версией. Например, в Oracle 8.1.5 был параметр plsql_load_without_compile. Его не было ни в одной из предыдущих версий и нет в последующих. В моих базах данных версий 8.1.5, 8.1.6 и 8.1.7 имеется, соответственно, 199, 201 и 203 различных параметра инициализации. Большинство параметров, например db_block_size, существует очень давно (они были во всех версиях), но со временем необходимость во многих параметрах отпадает, так как меняется реализация. Если захочется прочитать об этих параметрах и разобраться, что они позволяют установить, обратитесь к руководству Oracle8i Reference . В первой главе этого руководства представлены официально поддерживаемые параметры инициализации. Обратите внимание на слова "официально поддерживаемые" в предыдущем абзаце. Не поддерживаются (и не описаны в руководстве) параметры, имена которых начинаются с символа подчеркивания. Вокруг этих параметров много спекуляций: поскольку они не поддерживаются официально, значит, имеют "магические" свойства. Многие полагают, что эти параметры хорошо известны "посвященным" сотрудникам корпорации Oracle и используются ими. По моему мнению, все как раз наоборот. Их мало кто вообще знает и редко использует. Большинство из неописанных параметров - лишние, представляют устаревшие возможности или обеспечивают обратную совместимость. Другие помогают при восстановлении данных, но не всей базы данных: они позволяют запустить экземпляр в определенных экстремальных ситуациях, но лишь для извлечения данных - базу данных затем придется пересоздавать. Я не вижу смысла использовать неописанные параметры файла init.ora в реальной базе данных, если только этого не требует служба технической поддержки. Многие из них имеют побочные эффекты, которые могут оказаться разрушительными. В базе данных, которую я использую для разработки, установлен только один неописанный параметр: _TRACE_FILES_PUBLIC = TRUE Это делает трассировочные файлы доступными всем, а не только членам группы dba. Я хочу, чтобы разработчики как можно чаще использовали установки SQL_TRACE, TIMED_STATISTICS и утилиту TKPROF (более того, я это требую), поэтому всем им необходимо читать трассировочные файлы. В производственной базе данных я неописанных параметров не использую. Неописанные параметры должны использоваться только по указанию службы технической поддержки Oracle. При их использовании можно повредить базу данных, да и реализация меняется от версии к версии. Теперь, когда известно, что представляют собой файлы параметров и где можно более подробно прочитать о параметрах, которые в них можно устанавливать, осталось узнать, где эти файлы искать на диске. Файлы параметров инициализации экземпляра принято именовать так: init$ORACLE_SID.ora (переменная среды Unix) init%ORACLE_SID%.ora (переменная среды Windows) Как правило, они находятся в каталогах $ORACLE_HOME/dbs (в ОС Unix) %ORACLE_HOME%\DATABASE (в ОС Windows) Часто в файле параметров содержится всего одна строка примерно такого вида: IFILE='C:\oracle\admin\tkyte816\pfile\init.ora' Директива IFILE работает аналогично директиве препроцессора #include в языке C. Она вставляет в данном месте текущего файла содержимое указанного файла. В данном случае включается содержимое файла init.ora из нестандартного каталога. Следует отметить, что файл параметров не обязательно должен находится в одном и том же стандартном месте. При запуске экземпляра можно использовать параметр pfile = имя_файла. Это особенно полезно при попытке проверить результаты установки других значений для параметров. Файлы данныхФайлы данных вместе с файлами журнала повторного выполнения являются наиболее важными в базе данных. Именно в них хранятся все данные. В каждой базе данных есть хотя бы один файл данных, но обычно их намного больше. Только самые простые, "тестовые" базы данных имеют один файл данных. В любой реальной базе данных должно быть минимум два файла данных: один - для системных данных (табличное пространство SYSTEM), другой - для пользовательских (табличное пространство USER). В этом разделе мы рассмотрим организацию файлов данных в Oracle и способы хранения данных в этих файлах. Но прежде надо разобраться, что такое табличное пространство, сегмент, экстент и блок. Все это - единицы выделения пространства под объекты в базе данных Oracle. Начнем с сегментов. Сегменты - это области на диске, выделяемые под объекты - таблицы, индексы, сегменты отката и т.д. При создании таблицы создается сегмент таблицы. При создании секционированной таблицы создается по сегменту для каждой секции. При создании индекса создается сегмент индекса и т.д. Каждый объект, занимающий место на диске, хранится в одном сегменте. Есть сегменты отката, временные сегменты, сегменты кластеров, сегменты индексов и т.д. Сегменты, в свою очередь, состоят из одного или нескольких экстентов. Экстент - это непрерывный фрагмент пространства в файле. Каждый сегмент первоначально состоит хотя бы из одного экстента, причем для некоторых объектов требуется минимум два экстента (в качестве примера можно назвать сегменты отката). Чтобы объект мог вырасти за пределы исходного экстента, ему необходимо выделить следующий экстент. Этот экстент не обязательно должен выделяться рядом с первым; он может находиться достаточно далеко от первого, но в пределах экстента в файле пространство всегда непрерывно. Размер экстента варьируется от одного блока до 2 Гбайт. Экстенты состоят из блоков. Блок - наименьшая единица выделения пространства в Oracle. В блоках и хранятся строки данных, индексов или промежуточные результаты сортировок. Именно блоками сервер Oracle обычно выполняет чтение и запись на диск. Блоки в Oracle бывают размером 2 Кбайта, 4 Кбайта или 8 Кбайт (хотя допустимы также блоки размером 16 Кбайт и 32 Кбайта). Сегмент состоит из одного или более экстентов, а экстент - это группа следующих подряд блоков. Размер блока в базе данных с момента ее создания - величина постоянная, поэтому все блоки в базе данных одного размера. Формат блока представлен ниже. +---------------+ / / <---- заголовок +---------------+ / / <---- каталог таблиц +---------------+ /\\\\\\\\\\\\\\\/ <---- каталог строк +---------------+ / / / / <---- свободное пространство / ... / +---------------+ /010101010101010/ /010101010101010/ /010101010101010/ <---- данные /010101010101010/ /010101010101010/ +---------------+ Заголовок блока содержит информацию о типе блока (блок таблицы, блок индекса и т.д.), информацию о текущих и прежних транзакциях, затронувших блок, а также адрес (местонахождение) блока на диске. Каталог таблиц содержит информацию о таблицах, строки которых хранятся в этом блоке (в блоке могут храниться данные нескольких таблиц). Каталог строк содержит описание хранящихся в блоке строк. Это массив указателей на строки, хранящиеся в области данных блока. Вместе эти три части блока называются служебным пространством блока. Это пространство недоступно для данных и используется сервером Oracle для управления блоком. Остальные две части блока вполне понятны: в блоке имеется занятое пространство, в котором хранятся данные, и может быть свободное пространство. Теперь, получив общее представление о сегментах, состоящих из экстентов, которые, в свою очередь, состоят из блоков, можно переходить к понятию "табличное пространство" и разбираться, где же в этой структуре место для файлов. Табличное пространство - это контейнер с сегментами. Каждый сегмент принадлежит к одному табличному пространству. В табличном пространстве может быть много сегментов. Все экстенты сегмента находятся в табличном пространстве, где создан сегмент. Сегменты никогда не переходят границ табличного пространства. С табличным пространством, в свою очередь, связан один или несколько файлов данных. Экстент любого сегмента табличного пространства целиком помещается в одном файле данных. Однако экстенты сегмента могут находиться в нескольких различных файлах данных. Графически это можно представить следующим образом: ... Итак, здесь представлено табличное пространство USER_DATA. Оно состоит из двух файлов данных - user_data01 и user_data02. В нем выделено три сегмента: T1, T2 и I1 (вероятно, две таблицы и индекс). В табличном пространстве выделены четыре экстента, причем каждый показан как непрерывный набор блоков базы данных. Сегмент T1 состоит из двух экстентов (по одному экстенту в каждом файле). Сегменты T2 и I1 состоят из одного экстента. Если для табличного пространства понадобится больше места, можно либо увеличить размер файлов данных, уже выделенных ему, либо добавить третий файл данных. Табличные пространства в Oracle - это логические структуры хранения данных. Разработчики создают сегменты в табличных пространствах. Они никогда не переходят на уровень файлов - нельзя указать, что экстенты должны выделяться из определенного файла. Объекты создаются в табличных пространствах, а об остальном заботится сервер Oracle. Если в дальнейшем администратор базы данных решит перенести файлы данных на другой диск для более равномерного распределения операций ввода-вывода по дискам, никаких проблем для приложения это не создаст. На работе приложения это никак не отразится. Итак, иерархия объектов, обеспечивающих хранение данных в Oracle, выглядит так.
Прежде чем завершить описание файлов данных, давайте разберемся, как происходит управление экстентами в табличном пространстве. До версии 8.1.5 в Oracle был только один метод управления выделением экстентов в табличном пространстве. Этот метод называется управление табличным пространством по словарю . Т.е. место в табличном пространстве отслеживается в таблицах словаря данных (аналогично тому, как отслеживаются движения средств на банковских счетах с помощью пары таблиц DEBIT и CREDIT). В качестве дебета можно рассматривать выделенные объектам экстенты, в качестве кредита - свободные для использования экстенты. Когда для объекта необходим очередной экстент, он запрашивается у системы. При получении такого запроса сервер Oracle обращается к соответствующим таблицам словаря данных, выполняет ряд запросов, находит (или не находит) свободное место нужного размера, а затем изменяет строку в одной таблице (или удаляет ее) и вставляет строку в другую. При этом сервер Oracle управляет пространством примерно так же, как работают обычные приложения: он изменяет данные в таблицах. Соответствующие SQL-операторы для получения дополнительного пространства, выполняемые в фоновом режиме от имени пользователя, называют рекурсивными. Выполненный пользователем SQL-оператор INSERT вызывает выполнение других рекурсивных SQL-операторов для получения пространства на диске. При частом выполнении рекурсивные SQL-операторы создают весьма существенную дополнительную нагрузку на систему. Подобные изменения словаря данных должны выполняться последовательно, делать их одновременно нельзя. По возможности их следует избегать. В прежних версиях Oracle этот метод управления пространством (и связанные с ним дополнительные расходы ресурсов на выполнение рекурсивных SQL-операторов) приводил к проблемам при работе с временными табличными пространствами (до появления "настоящих" временных табличных пространств). Речь идет о табличных пространствах, в которых необходимо часто выделять место (при этом надо удалить строку из одной таблицы словаря данных и вставить в другую) и освобождать его (помещая только что перенесенные строки туда, где они ранее были). Эти операции выполняются последовательно, что существенно снижает возможности одновременной работы и увеличивает время ожидания. В версии 7.3 СУБД Oracle для решения этой проблемы добавили временные пространства. Во временном табличном пространстве пользователь не мог создавать постоянные объекты. Это было единственным новшеством: управление пространством все равно выполнялось с помощью таблиц словаря данных. Однако после выделения экстента во временном табличном пространстве система его уже не освобождала. При следующем запросе экстента из временного табличного пространства сервер Oracle искал уже выделенный экстент в соответствующей структуре данных в памяти и, найдя, использовал повторно. В противном случае экстент выделялся как обычно. При этом после запуска и работы СУБД в течение некоторого времени соответствующий временный сегмент выглядел как заполненный, но фактически был просто "выделен". Свободными экстентами в нем управляли по-другому. При запросе сеансом временного пространства сервер Oracle искал его в структурах данных в памяти, а не выполнял дорогостоящие рекурсивные SQL-операторы. В версиях Oracle, начиная с 8.1.5, был сделан следующий шаг по сокращению расхода ресурсов на управление пространством. Кроме табличных пространств, управляемых по словарю данных, появились локально управляемые табличные пространства. Для всех табличных пространств стало можно делать то, что в Oracle 7.3 делалось для временных, т.е. не использовать словарь данных для управления свободным местом в табличном пространстве. В локально управляемом табличном пространстве для отслеживания экстентов используется битовая карта, хранящаяся в каждом файле данных. Теперь для получения экстента достаточно установить значение 1 для соответствующего бита в битовой карте. Для освобождения экстента - сбросить бит обратно в 0. По сравнению с обращениями к словарю данных, это выполняется молниеносно. Больше не требуется ждать завершения длительно выполняемой операции, на уровне базы данных последовательно выделяющей место во всех табличных пространствах. Очередность на уровне табличного пространства остается только для очень быстро выполняемой операции. Локально управляемые табличные пространства имеют и другие положительные качества, например устанавливают одинаковый размер всех экстентов, но это имеет значение только для администраторов баз данных. Временные файлыВременные файлы в Oracle - это специальный тип файлов данных. Сервер Oracle использует временные файлы для хранения промежуточных результатов сортировки большого объема данных или результирующих множеств, если для них не хватает оперативной памяти. Постоянные объекты данных, такие как таблицы или индексы, во временных файлах никогда не хранятся, в отличие от содержимого временных таблиц и построенных по ним индексов. Так что создать таблицы приложения во временном файле данных нельзя, а вот хранить в нем данные можно, если использовать временную таблицу. Сервер Oracle обрабатывает временные файлы специальным образом. Обычно все изменения объектов записываются в журналы повторного выполнения. Эти журналы транзакций в дальнейшем можно использовать для повторного выполнения транзакций. Это делается, например, при восстановлении после сбоя. Временные файлы в этом процессе не участвуют. Для них не генерируются данные повторного выполнения, хотя и генерируются данные отмены (UNDO) при работе с глобальными временными таблицами, чтобы можно было откатить изменения, сделанные в ходе сеанса. Создавать резервные копии временных файлов данных нет необходимости, а если кто-то это делает, то напрасно теряет время, поскольку данные во временном файле восстановить все равно нельзя. Рекомендуется конфигурировать базу данных так, чтобы временные табличные пространства управлялись локально. Убедитесь, что ваш администратор базы данных использует команду CREATE TEMPORARY TABLESPACE. Никому не нужно еще одно обычное табличное пространство, используемое под временные данные, поскольку не удастся получить преимущества временных файлов данных. Убедитесь также, что в качестве временного используется локально управляемое табличное пространство с экстентами одинакового размера, соответствующего значению параметра инициализации sort_area_size. Создаются такие временные табличные пространства примерно так: tkyte@TKYTE816> create temporary tablespace temp 2 tempfile 'c:\oracle\oradata\tkyte816\temp.dbf' 3 size 5m 4 extent management local 5 uniform size 64k; Tablespace created. Поскольку мы опять вторгаемся в сферу деятельности администратора базы данных, переходим к следующей теме. Управляющие файлыУправляющий файл - это сравнительно небольшой файл (в редких случаях он может увеличиваться до 64 Мбайт), содержащий информацию обо всех файлах, необходимых серверу Oracle. Из файла параметров инициализации (init.ora) экземпляр может узнать, где находятся управляющие файлы, а в управляющем файле описано местонахождение файлов данных и файлов журнала повторного выполнения. В управляющих файлах хранится и другие необходимые серверу Oracle сведения, в частности время обработки контрольной точки, имя базы данных (которое должно совпадать со значением параметра инициализации db_name), дата и время создания базы данных, хронология архивирования журналов повторного выполнения (именно она приводит к увеличению размера управляющего файла в некоторых случаях) и т.д. Управляющие файлы надо мультиплексировать либо аппаратно (располагать на RAID-массиве), либо с помощью средств сервера Oracle, когда RAID-массив или зеркалирование использовать нельзя. Необходимо поддерживать несколько копий этих файлов, желательно на разных дисках, чтобы предотвратить потерю управляющих файлов в случае сбоя диска. Потеря управляющих файлов - не фатальное событие, она только существенно усложнит восстановление. С управляющими файлами разработчику скорее всего сталкиваться никогда не придется. Для администратора базы данных это - важная часть базы данных, но для разработчика эти файлы не особенно нужны. Файлы журнала повторного выполненияФайлы журнала повторного выполнения принципиально важны для базы данных Oracle. Это журналы транзакций базы данных. Они используются только для восстановления при сбое экземпляра или носителя или при поддержке резервной базы данных на случай сбоев. Если на сервере, где работает СУБД, отключится питание и вследствие этого произойдет сбой экземпляра, для восстановления системы в состояние, непосредственно предшествующее отключению питания, сервер Oracle при повторном запуске будет использовать оперативные журналы повторного выполнения. Если диск, содержащий файлы данных, полностью выйдет из строя, для восстановления резервной копии этого диска на соответствующий момент времени сервер Oracle, помимо оперативных журналов повторного выполнения, будет использовать также архивные. Кроме того, при случайном удалении таблицы или какой-то принципиально важной информации, если эта операция зафиксирована, с помощью оперативных и архивных журналов повторного выполнения можно восстановить данные из резервной копии на момент времени, непосредственно предшествующий удалению. Практически каждое действие, выполняемое в СУБД Oracle, генерирует определенные данные повторного выполнения, которые надо записать в оперативные файлы журнала повторного выполнения. При вставке строки в таблицу конечный результат этой операции записывается в журналы повторного выполнения. При удалении строки записывается факт удаления. При удалении таблицы в журнал повторного выполнения записываются последствия этого удаления. Данные из удаленной таблицы не записываются, но рекурсивные SQL-операторы, выполняемые сервером Oracle при удалении таблицы, генерируют определенные данные повторного выполнения. Например, при этом сервер Oracle удалит строку из таблицы SYS.OBJ$, и это удаление будет отражено в журнале. Некоторые операции могут выполняться в режиме с минимальной генерацией данных повторного выполнения. Например, можно создать индекс с атрибутом NOLOGGING. Это означает, что первоначальное создание этого индекса не будет записываться в журнал, но любые инициированные при этом рекурсивные SQL-операторы, выполняемые сервером Oracle, - будут. Например, вставка в таблицу SYS.OBJ$ строки, соответствующей индексу, в журнал записываться не будет. Однако последующие изменения индекса при выполнении SQL-операторов INSERT, UPDATE и DELETE, будут записываться в журнал. Есть два типа файлов журнала повторного выполнения: оперативные и архивные. В главе 5 мы еще раз затронем тему журналов повторного выполнения и сегментов отката, чтобы понять, как они влияют на разработку приложений. Пока же мы опишем, что собой представляют журналы повторного выполнения и их назначение. Оперативный журнал повторного выполненияВ каждой базе данных Oracle есть как минимум два оперативных файла журнала повторного выполнения. Эти оперативные файлы журнала повторного выполнения имеют фиксированный размер и используются циклически. Сервер Oracle выполняет запись в файл журнала 1, а когда доходит до конца этого файла, - переключается на файл журнала 2 и переписывает его содержимое от начала до конца. Когда заполнен файл журнала 2, сервер переключается снова на файл журнала 1 (если имеется всего два файла журнала повторного выполнения; если их три, сервер, разумеется, переключится на третий файл). Переход с одного файла журнала на другой называется переключением журнала . Важно отметить, что переключение журнала может вызвать временное "зависание" плохо настроенной базы данных. Поскольку журналы повторного выполнения используются для восстановления транзакций в случае сбоя, перед повторным использованием файла журнала необходимо убедиться, что его содержимое не понадобится в случае сбоя. Если сервер Oracle "не уверен", что содержимое файла журнала не понадобится, он приостанавливает на время изменения в базе данных и убеждается, что данные, "защищаемые" этой информацией повторного выполнения, записаны на диск. После этого обработка возобновляется, и файл журнала переписывается. Мы затронули ключевое понятие баз данных - обработку контрольной точки . Чтобы понять, как используются оперативные журналы повторного выполнения, надо разобраться с обработкой контрольной точки, использованием буферного кеша базы данных и рассмотреть функции процесса записи блоков базы данных (Database Block Writer - DBWn). Буферный кеш и процесс DBWn подробно рассматриваются ниже, но мы все равно забегаем вперед, так что имеет смысл поговорить о них. В буферном кеше базы данных временно хранятся блоки базы данных. Это структура в области SGA разделяемой памяти экземпляра Oracle. При чтении блоки запоминаются в этом кеше (предполагается, что в дальнейшем их не придется читать с диска). Буферный кеш - первое и основное средство настройки производительности сервера. Он существует исключительно для ускорения очень медленного процесса ввода-вывода. При изменении блока путем обновления одной из его строк изменения выполняются в памяти, в блоках буферного кеша. Информация, достаточная для повторного выполнения этого изменения, записывается в буфер журнала повторного выполнения - еще одну структуру данных в области SGA. При фиксации изменений с помощью оператора COMMIT сервер Oracle не записывает на диск все измененные блоки в области SGA. Он только записывает в оперативные журналы повторного выполнения содержимое буфера журнала повторного выполнения. Пока измененный блок находится в кеше, а не на диске, содержимое соответствующего оперативного журнала может быть использовано в случае сбоя экземпляра. Если сразу после фиксации изменения отключится питание, содержимое буферного кеша пропадет. Если это произойдет, единственная запись о выполненном изменении останется в файле журнала повторного выполнения. После перезапуска экземпляра сервер Oracle будет по сути повторно выполнять транзакцию, изменяя блок точно так же, как мы это делали ранее, и фиксируя это изменение автоматически. Итак, если измененный блок находится в кеше и не записан на диск, мы не можем повторно записывать соответствующий файл журнала повторного выполнения. Тут и вступает в игру процесс DBWn. Это фоновый процесс сервера Oracle, отвечающий за освобождение буферного кеша при заполнении и обработку контрольных точек. Обработка контрольной точки состоит в сбросе грязных (измененных) блоков из буферного кеша на диск. Сервер Oracle делает это автоматически, в фоновом режиме. Обработка контрольной точки может быть вызвана многими событиями, но чаще всего - переключением журнала повторного выполнения. При заполнении файла журнала 1, перед переходом на файл журнала 2, сервер Oracle инициирует обработку контрольной точки. В этот момент процесс DBWn начинает сбрасывать на диск все грязные блоки, защищенные файлом журнала 1. Пока процесс DBWn не сбросит все блоки, защищаемые этим файлом, сервер Oracle не сможет его повторно использовать. Если попытаться использовать его прежде, чем процесс DBWn завершит обработку контрольной точки, в журнал сообщений (alert log) будет выдано следующее сообщение: ... Thread 1 cannot allocate new log, sequence 66 Checkpoint not complete Current log# 2 seq# 65 mem# 0: C:\ORACLE\ORADATA\TKYTE816\REDO02.LOG ... Журнал сообщений - это файл на сервере, содержащий информационные сообщения сервера, например, о запуске и останове, а также уведомления об исключительных ситуациях, вроде незавершенной обработки контрольной точки. Итак, в момент выдачи этого сообщения обработка изменений была приостановлена до завершения процессом DBWn обработки контрольной точки. Для ускорения обработки сервер Oracle отдал все вычислительные мощности процессу DBWn. При соответствующей настройке сервера это сообщение в журнале появляться не должно. Если оно все же есть, значит, имеют место искусственные, ненужные ожидания, которых можно избежать. Цель (в большей степени администратора базы данных, чем разработчика) - иметь достаточно оперативных файлов журнала повторного выполнения. Это предотвратит попытки сервера использовать файл журнала, прежде чем будет закончена обработка контрольной точки. Если это сообщение выдается часто, значит, администратор базы данных не выделил для приложения достаточного количества оперативных журналов повторного выполнения или процесс DBWn не настроен как следует. Разные приложения генерируют различные объемы информации повторного выполнения. Системы класса DSS (системы поддержки принятия решений, выполняющие только запросы), естественно, будут генерировать намного меньше информации повторного выполнения, чем системы OLTP (системы оперативной обработки транзакций). Система, манипулирующая изображениями в больших двоичных объектах базы данных, может генерировать во много раз больше информации повторного выполнения, чем простая система ввода заказов. В системе ввода заказов со 100 пользователями генерируется в десять раз меньше информации повторного выполнения, чем в системе с 1000 пользователей. "Правильного" размера для журналов повторного выполнения нет, - он просто должен быть достаточным. При определении размера и количества оперативных журналов повторного выполнения необходимо учитывать много факторов. Они, в общем, выходят за рамки книги, но я перечислю хотя бы отдельные, чтобы вы поняли, о чем речь.
Архивный журнал повторного выполненияБаза данных Oracle может работать в двух режимах - NOARCHIVELOG и ARCHIVELOG. Я считаю, что система, используемая в производственных условиях, обязательно должна работать в режиме ARCHIVELOG. Если база данных не работает в режиме ARCHIVELOG, данные рано или поздно будут потеряны. Работать в режиме NOARCHIVELOG можно только в среде разработки или тестирования. Эти режимы отличаются тем, что происходит с файлом журнала повторного выполнения до того как сервер Oracle его перепишет. Сохранять ли копию информации повторного выполнения или разрешить серверу Oracle переписать ее, потеряв при этом навсегда - очень важный вопрос. Если не сохранить этот файл, мы не сможем восстановить данные с резервной копии до текущего момента. Предположим, резервное копирование выполняется раз в неделю, по субботам. В пятницу вечером, после того как за неделю было сгенерировано несколько сотен журналов повторного выполнения, происходит сбой диска. Если база данных не работала в режиме ARCHIVELOG, остается только два варианта дальнейших действий.
Оба варианта непривлекательны, поскольку приводят к потере данных. Работая же в режиме ARCHIVELOG, достаточно найти другой диск и восстановить на него соответствующие файлы с субботней резервной копии. Затем применить к ним архивные журналы повторного выполнения и, наконец, - оперативные журналы повторного выполнения (то есть повторить все накопленные за неделю транзакции в режиме быстрого наката). При этом ничего не теряется. Данные восстанавливаются на момент сбоя. Часто приходится слышать, что в производственных системах режим ARCHIVELOG не нужен. Это глубочайшее заблуждение. Если не хотите в один момент потерять данные, сервер должен работать в режиме ARCHIVELOG. "Мы используем дисковый массив RAID-5 и абсолютно защищены" - вот типичное оправдание. Я сталкивался с ситуациями, когда по вине изготовителя все пять дисков массива одновременно останавливались. Я видел поврежденные аппаратным контроллером файлы данных, которые в поврежденном виде надежно защищались дисковым массивом. Если имеется резервная копия данных на момент, предшествующий сбою оборудования, и архивы не повреждены, - восстановление возможно. Поэтому нет разумных оснований для того, чтобы не использовать режим ARCHIVELOG в системе, где данные представляют хоть какую-нибудь ценность. Производительность - не основание. При правильной настройке на архивирование расходуется незначительное количество ресурсов системы. Это, а также тот факт, что быстро работающая система, в которой данные теряются, - бесполезна, заставляет сделать вывод, что, даже если бы архивирование журналов замедляло работу системы в два раза, оно в любом случае должно выполняться. Не поддавайтесь ни на какие уговоры и не отказывайтесь от режима ARCHIVELOG. Вы потратили много времени на разработку приложения, поэтому надо, чтобы пользователи ему доверяли. О доверии можно забыть, если их данные будут потеряны. Итак, мы рассмотрели основные типы файлов, используемых сервером Oracle: от небольших файлов параметров инициализации (без которых не удастся даже запустить экземпляр) до принципиально важных файлов журнала повторного выполнения и файлов данных. Обсудили структуры хранения данных в Oracle: от табличных пространств, сегментов и экстентов до блоков базы данных - наименьшей единицы хранения. Была описана обработка контрольной точки в базе данных и даже (несколько преждевременно) затронута работа физических процессов или потоков, составляющих экземпляр Oracle. В последующих разделах этой главы мы более детально рассмотрим эти процессы и структуры памяти. Структуры памятиТеперь пришло время рассмотреть основные структуры памяти сервера Oracle. Их три.
Рассмотрим кратко области PGA и UGA, затем перейдем к действительно большой структуре - области SGA. Области PGA и UGAКак уже было сказано, PGA - это область памяти процесса. Эта область памяти используется одним процессом или одним потоком. Она недоступна ни одному из остальных процессов/потоков в системе. Область PGA обычно выделяется с помощью библиотечного вызова malloc() языка C и со временем может расти (или уменьшаться). Область PGA никогда не входит в состав области SGA - она всегда локально выделяется процессом или потоком. Область памяти UGA хранит состояние сеанса, поэтому всегда должна быть ему доступна. Местонахождение области UGA зависит исключительно от конфигурации сервера Oracle. Если сконфигурирован режим MTS, область UGA должна находиться в структуре памяти, доступной всем процессам, следовательно, в SGA. В этом случае сеанс сможет использовать любой разделяемый сервер, так как каждый из них сможет прочитать и записать данные сеанса. При подключении к выделенному серверу это требование общего доступа к информации о состоянии сеанса снимается, и область UGA становится почти синонимом PGA, - именно там информация о состоянии сеанса и будет располагаться. Просматривая статистическую информацию о системе, можно обнаружить, что при работе в режиме выделенного сервера область UGA входит в PGA (размер области PGA будет больше или равен размеру используемой памяти UGA - размер UGA будет учитываться при определении размера области PGA). Размер области PGA/UGA определяют параметры уровня сеанса в файле init.ora: SORT_AREA_SIZE и SORT_AREA_RETAINED_SIZE. Эти два параметра управляют объемом пространства, используемым сервером Oracle для сортировки данных перед сбросом на диск, и определяют объем сегмента памяти, который не будет освобожден по завершении сортировки. SORT_AREA_SIZE обычно выделяется в области PGA, а SORT_AREA_RETAINED_SIZE - в UGA. Управлять размером областей UGA/PGA можно с помощью запроса к специальному представлению V$ сервера Oracle. Эти представления называют также представлениями динамической производительности. Подробнее эти представления V$ рассматриваются в главе 10. С помощью представлений V$ можно определить текущее использование памяти под области PGA и UGA. Например, запущен небольшой тестовый пример, требующий сортировки большого объема данных. Просмотрев несколько первых строк данных, я решил не извлекать остальное результирующее множество. После этого можно сравнить использование памяти "до" и "после": tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 / NAME VALUE ------------------------------ ---------- session uga memory 67532 session uga memory max 71972 session pga memory 144688 session pga memory max 144688 4 rows selected. Итак, перед началом сортировки в области UGA было около 70 Кбайт данных, а в PGA - порядка 140 Кбайт. Первый вопрос: сколько памяти используется в области PGA помимо UGA? Вопрос нетривиальный и на него нельзя ответить, не зная, подключен ли сеанс к выделенному или к разделяемому серверу; но даже зная это нельзя ответить однозначно. В режиме выделенного сервера область UGA входит в состав PGA. В этом случае порядка 140 Кбайт выделено в области памяти процесса или потока. В режиме MTS область UGA выделяется из SGA, а область PGA относится к разделяемому серверу. Поэтому при работе в режиме MTS к моменту получения последней строки из представленного выше запроса разделяемый серверный процесс уже может использоваться другим сеансом. Соответственно, область PGA уже не принадлежит нам, так что мы используем всего 70 Кбайт памяти (если только не находимся в процессе выполнения запроса, когда областями PGA и UGA суммарно используется 210 Кбайт памяти). Теперь разберемся, что происходит в областях PGA/UGA нашего сеанса: tkyte@TKYTE816> show parameter sort_area NAME TYPE VALUE ------------------------------------ ------- -------------------------- sort_area_retained_size integer 65536 sort_area_size integer 65536 tkyte@TKYTE816> set pagesize 10 tkyte@TKYTE816> set pause on tkyte@TKYTE816> select * from all_objects order by 1, 2, 3, 4; ...(Нажмите Control-C после первой страницы данных) ... tkyte@TKYTE816> set pause off tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 / NAME VALUE ------------------------------ ---------- session uga memory 67524 session uga memory max 174968 session pga memory 291336 session pga memory max 291336 4 rows selected. Как видите, памяти использовано больше, поскольку данные сортировались. Область UGA временно увеличилась примерно на размер SORT_AREA_RETAINED_SIZE, а область PGA - немного больше. Для выполнения запроса и сортировки сервер Oracle выделил дополнительные структуры, которые оставлены в памяти сеанса для других запросов. Давайте выполним ту же операцию, изменив значение SORT_AREA_SIZE: tkyte@TKYTE816> alter session set sort_area_size=1000000; Session altered. tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 / NAME VALUE ------------------------------ ---------- session uga memory 63288 session uga memory max 174968 session pga memory 291336 session pga memory max 291336 4 rows selected. tkyte@TKYTE816> show parameter sort_area NAME TYPE VALUE ------------------------------------ ------- -------------------------- sort_area_retained_size integer 65536 sort_area_size integer 1000000 tkyte@TKYTE816> select * from all_objects order by 1, 2, 3, 4; ...(Нажмите Control-C после первой страницы данных) ... tkyte@TKYTE816> set pause off tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 / NAME VALUE ------------------------------ ---------- session uga memory 67528 session uga memory max 174968 session pga memory 1307580 session pga memory max 1307580 4 rows selected. Как видите, в этот раз область PGA увеличилась существенно. Примерно на 1000000 байт, в соответствии с заданным значением SORT_AREA_SIZE. Интересно отметить, что в этот раз размер области UGA вообще не изменился. Для ее изменения надо задать другое значение SORT_AREA_RETAINED_SIZE, как показано ниже: tkyte@TKYTE816> alter session set sort_area_retained_size=1000000; Session altered. tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 / NAME VALUE ------------------------------ ---------- session uga memory 63288 session uga memory max 174968 session pga memory 1307580 session pga memory max 1307580 4 rows selected. tkyte@TKYTE816> show parameter sort_area NAME TYPE VALUE ------------------------------------ ------- -------------------------- sort_area_retained_size integer 1000000 sort_area_size integer 1000000 tkyte@TKYTE816> select * from all_objects order by 1, 2, 3, 4; ...(Нажмите Control-C после первой страницы данных) ... tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 / NAME VALUE ------------------------------ ---------- session uga memory 66344 session uga memory max 1086120 session pga memory 1469192 session pga memory max 1469192 4 rows selected. Теперь мы видим, что существенное увеличение размера области UGA связано с необходимостью дополнительно принять данные размером SORT_AREA_RETAINED_SIZE. В ходе обработки запроса 1 Мбайт сортируемых данных "кеширован в памяти". Остальные данные были на диске (где-то во временном сегменте). По завершении выполнения запроса это дисковое пространство возвращено для использования другими сеансами. Обратите внимание, что область PGA не уменьшилась до прежнего размера. Этого следовало ожидать, поскольку область PGA используется как "куча" и состоит из фрагментов, выделенных с помощью вызовов malloc(). Некоторые процессы в сервере Oracle явно освобождают память PGA, другие же оставляют выделенную память в куче (область для сортировки, например, остается в куче). Сжатие кучи при этом обычно ничего не дает (размер используемой процессами памяти только растет). Поскольку область UGA является своего рода "подкучей" (ее "родительской" кучей является область PGA либо SGA), она может сжиматься. При необходимости можно принудительно сжать область PGA: tkyte@TKYTE816> exec dbms_session.free_unused_user_memory; PL/SQL procedure successfully completed. tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 / NAME VALUE ------------------------------ ---------- session uga memory 73748 session uga memory max 1086120 session pga memory 183360 session pga memory max 1469192 Учтите, однако, что в большинстве систем это действие - пустая трата времени. Можно уменьшить размер кучи PGA в рамках экземпляра Oracle, но память при этом операционной системе не возвращается. В зависимости от принятого в ОС метода управления памятью, суммарное количество используемой памяти даже увеличится. Все зависит от того, как на данной платформе реализованы функции malloc(), free(), realloc(), brk() и sbrk() (стандартные функции управления памятью в языке C). Итак, мы рассмотрели две структуры памяти, области PGA и UGA. Теперь понятно, что область PGA принадлежит процессу. Она представляет собой набор переменных, необходимых выделенному или разделяемому серверному процессу Oracle для поддержки сеанса. Область PGA - это "куча" памяти, в которой могут выделяться другие структуры. Область UGA также является кучей, в которой определяются связанные с сеансом структуры. Область UGA выделяется из PGA при подключении к выделенному серверу Oracle и - из области SGA при подключении в режиме MTS. Это означает, что при работе в режиме MTS необходимо задать такой размер области SGA, чтобы в ней хватило места под области UGA для предполагаемого максимального количества одновременно подключенных к базе данных пользователей. Поэтому область SGA в экземпляре, работающем в режиме MTS, обычно намного больше, чем область SGA аналогично сконфигурированного экземпляра, работающего в режиме выделенного сервера. Область SGAКаждый экземпляр Oracle имеет одну большую область памяти, которая называется SGA, System Global Area - глобальная область системы. Это большая разделяемая структура, к которой обращаются все процессы Oracle. Ее размер варьируется от нескольких мегабайт в небольших тестовых системах до сотен мегабайт в системах среднего размера и множества гигабайт в больших системах. В ОС UNIX область SGA - это физический объект, которую можно "увидеть" с помощью утилит командной строки. Физически область SGA реализована как сегмент разделяемой памяти - отдельный фрагмент памяти, к которому могут подключаться процессы. При отсутствии процессов Oracle вполне допустимо иметь в системе область SGA; память существует отдельно от них. Однако наличие области SGA при отсутствии процессов Oracle означает, что произошел тот или иной сбой экземпляра. Эта ситуация - нештатная, но она бывает. Вот как "выглядит" область SGA в ОС UNIX: $ ipcs -mb IPC status from <running system> as of Mon Feb 19 14:48:26 EST 2001 T ID KEY MODE OWNER GROUP SEGSZ Shared Memory: m 105 0xf223dfc8 --rw-r----- ora816 dba 186802176 В ОС Windows увидеть область SGA, как в ОС UNIX, нельзя. Поскольку на этой платформе экземпляр Oracle работает как единый процесс с одним адресным пространством, область SGA выделяется как приватная память процесса ORACLE.EXE. С помощью диспетчера задач Windows (Task Manager) или другого средства контроля производительности можно узнать, сколько памяти выделено процессу ORACLE.EXE, но нельзя определить, какую часть по отношению к другим выделенным структурам памяти занимает область SGA. В самой СУБД Oracle можно определить размер области SGA независимо от платформы. Есть еще одно "магическое" представление V$, именуемое V$SGASTAT. Вот как его можно использовать: tkyte@TKYTE816> compute sum of bytes on pool tkyte@TKYTE816> break on pool skip 1 tkyte@TKYTE816> select pool, name, bytes 2 from v$sgastat 3 order by pool, name; POOL NAME BYTES ----------- ------------------------------ ---------- java pool free memory 18366464 memory in use 2605056 *********** ---------- sum 20971520 large pool free memory 6079520 session heap 64480 *********** ---------- sum 6144000 shared pool Checkpoint queue 73764 KGFF heap 5900 KGK heap 17556 KQLS heap 554560 PL/SQL DIANA 364292 PL/SQL MPCODE 138396 PLS non-lib hp 2096 SYSTEM PARAMETERS 61856 State objects 125464 VIRTUAL CIRCUITS 97752 character set object 58936 db_block_buffers 408000 db_block_hash_buckets 179128 db_files 370988 dictionary cache 319604 distributed_transactions- 180152 dlo fib struct 40980 enqueue_resources 94176 event statistics per sess 201600 file # translation table 65572 fixed allocation callback 320 free memory 9973964 joxlod: in ehe 52556 joxlod: in phe 4144 joxs heap init 356 library cache 1403012 message pool freequeue 231152 miscellaneous 562744 processes 40000 sessions 127920 sql area 2115092 table columns 19812 transaction_branches 368000 transactions 58872 trigger defini 2792 trigger inform 520 *********** ---------- sum 18322028 db_block_buffers 24576000 fixed_sga 70924 log_buffer 66560 *********** ---------- sum 24713484 43 rows selected. Область SGA разбита на несколько пулов.
Поэтому графически область SGA можно представить следующим образом: +----------------------------------------------------------------------+ / SGA / / +-----------------+ +----------+ +---------------+ +---------------+ / / / / / Java-пул / / Фиксированная / / Буфер журнала / / / / Разделяемый пул / / / / область SGA / / повторного / / / / / +----------+ +---------------+ / выполнения / / / +-----------------+ +---------------+ / / +-----------------------------------------+ +----------------------+ / / / Буферный кеш / / Большой пул / / / +-----------------------------------------+ +----------------------+ / +----------------------------------------------------------------------+ На общий размер SGA наиболее существенно влияют следующие параметры init.ora.
За исключением параметров SHARED_POOL_SIZE и LOG_BUFFER, имеется однозначное соответствие между значением параметров в файле init.ora и объемом памяти, выделяемой соответствующей структуре в области SGA. Например, если умножить DB_BLOCK_BUFFERS на размер буфера, получится значение, совпадающее с размером в строке DB_BLOCK_BUFFERS для пула NULL в представлении V$SGASTAT (добавляется определенный объем памяти на поддержку защелок). Суммарное количество байтов, вычисленное из строк представления V$SGASTAT для большого пула, совпадет со значением параметра инициализации LARGE_POOL_SIZE. Фиксированная область SGAФиксированная область SGA - это часть области SGA, размер которой зависит от платформы и версии. Она "компилируется" в двоичный модуль сервера Oracle при установке (отсюда и название - "фиксированная"). Фиксированная область SGA содержит переменные, которые указывают на другие части SGA, а также переменные, содержащие значения различных параметров. Размером фиксированной области SGA (как правило, очень небольшой) управлять нельзя. Можно рассматривать эту область как "загрузочную" часть SGA, используемую сервером Oracle для поиска других компонентов SGA. |