Oracle ДЛЯ ПРОФЕССИОНАЛОВ 3-е издание Expert гас е Database Architecture Third Edition Thomas Kyte Darl Kuhn гас е ДЛЯ ПРОФЕССИОНАЛОВ Архитектура, методики программирования и основные особенности версий 9i, 1 Og, 11 g и 12с 3-е издание Томас Кайт Дарл Кун Москва • Санкт-Петербург 2016 • Киев Б Б К 32.973.26-0 1 8 .2.75 К15 УДК 68 1 .3 .07 И здател ьски й дом " Вильяме" Зав. редакцией С.Н. Тригуб Перевод с английского Ю.Н. Артеменко Под редакцией Ю.Н. Артеменко По общим вопросам обращайтесь в И здател ьский дом " Вильяме" по адресу: info@williamspublishing.com, http:/jwww.williamspublishing.com Кайт, Томас, Кун, Дарл . К15 Oracle мя профессионалов: архитектура и методики проrраммирования, 3-е изд. : Пер. с англ . - М . : 000 "ИД. Вил ьяме" , 20 1 6. - 960 с.: ил.- Парал. тит. англ. I SBN 978-5-8459-2042-3 (рус . ) ББК 32.973.26-018.2.75 Все названия программных продуктов являются зарегистрированными торговыми марками соот­ ветствующих фирм. Никакая часть настоящего издания ни в каких целях не может быть воспроизведена в какой бы то ни было форме и какими бы то ни было средствами, будь то электронные или механические, включая фотокопирование и запись на магнитный носитель, если на это нет письменного разреще­ ния издательства APress, Berkeley, СА. Authorized translation from the English language edition puЬlished Ьу APress, lnc., Copyright © 2014 Ьу Thomas Kyte and Darl Kuhn. All rights reseJVed. No part of this work may Ье reproduced or transmitted in any form or Ьу any means, electronic or mechanical, including photocopying, recording, or Ьу any information storage or retrieval sys­ tem, without the prior written permission of the copyпght owner and the puЬlisher. Russian language edition is puЬlished Ьу Williams PuЬlishing House according to the Agreement with R&l Enterprises lnternational, Copyright © 2016. Научно-популярное издание Томас Кайт, Дарл Кун Oracle для профессионалов: архитектура и методики программирования, 3-е издание Верстка Художествен н ы й редактор Т. Н. Артемеюсо В.Г. Павлютин Подписано в nечать 04.11.2015. Формат 70х 100/16 Гарнитура Тimes Уел. печ. л. 77,4. Уч.-изд. л. 62,5 Тираж 400 экз. Заказ NQ 6739 Отпечатано способом ролевой струйной печати в АО «Первая Образцовая типография•> Филиал «Чеховский Печатный Двор>> 142300, Московская область, г. Чехов, ул. Полиграфистов, д.l 000 "И. Д. Вильяме", 127055, г. Москва, ул. Лесная, д. 43, стр. 1 ISBN 978-5-8459-2042-3 (рус.) ISBN 978-1-4302-6298-5 (англ.) © Издательский дом "Вильяме", 2016 © Ьу Thomas Kyte and Darl Kuhn, 2014 Оглавление Об авторах l3 Благодарности 15 Введение 16 Настройка среды 24 Глава 1 . Разработка успешных приложений Oracle 45 Глава 2.Обзор архитектуры 1 13 Глава 3. Файлы 137 Глава 4.Структуры памяти 205 Глава 5.Процессы Oracle 259 Глава 6. Блокировка и защелкивание данных 299 Глава 7. Параллелизм и многоверсионность 359 Глава 8. Транзакции 389 Глава 9. Повтор и отмена 427 Глава 1 О. Таблицы базы данных 487 Глава 11.Индексы 587 Глава 12.Типы данных 671 Глава1З.Секционирование 749 Глава 14. Параллельное выполнение 837 Глава 15.Загрузка и выгрузка данных 881 Предметный указатель 954 С одержание Об авторах Благодарности Введение О чем эта книга Кому адресована эта книга Как структурирована эта книга Исходный код и обновления От издательства 13 15 16 16 17 19 24 24 Настройка среды 24 Настройка учетной записи EODA Настройка схемы SCOTT /TIGER Выполнение сценария Создание схемы без сценария Настройка среды Настройка средства AUTOTRACE в SQL*Pius Настройка пакета Statspack Специальные сценарии Соглашения при написании кода 25 26 26 27 28 29 30 31 44 Глава1. Разработка успешных приложений Oracle 45 Мой подход Метод черного ящика Как следует (и как не следует) разрабатывать приложения баз данных Архитектура Oracle Управление параллельной обработкой Многоверсионность Как заставить приложение выполняться быстрее? Отношения между администратором базы данных и разработчиком Резюме 47 48 59 59 73 78 1 07 1 10 111 Глава 2. Обзор архитектуры 1 13 Определение базы данных и экземпляра Системная глобальная область и фоновые процессы Подключение к Oracle Вьщеленный сервер Разделяемый сервер Механизмы подключения через TCP/IP Подключаемые базы данных Снижение коэффициента использования ресурсов Сокращение объема работ по обслуживанию Отличия подключаемой базы данных Резюме 1 14 1 23 1 25 1 26 1 28 1 29 1 32 1 34 1 34 1 35 1 36 Глава 3. Файлы 1 37 �айлы параметров Что собой представляют параметры Унаследованные файлы параметров i n i t . ora 1 38 1 39 1 43 Соде ржан ие 7 Файлы параметров сервера ( S P F I LE) Заключительные соображения по поводу файла параметров Трассировочные файлы Запрошенные трассировочные файлы Трассировочные файлы, генерируемые в ответ на внутренние ошибки Заключительные соображения по поводу трассировочных файлов Сигнальный файл Файлы данных Краткий обзор механизмов файловой системы Иерархия хранения в базе данных Oracle Табличные пространства, управляемые словарем и управляемые локально Временные файлы Управляющие файлы Файлы журналов повторения транзакций Оперативный журнал повторения транзакций Архивный журнал повторения транзакций Файлы паралей Файл отслеживания изменений Ретроспективные журналы Команда FLAS HBACK DATABAS E Область для быстрого восстановления Файлы DMP (файлы экспорта/импорта) Файлы Data Pump Плоские файлы Резюме 1 46 1 54 1 55 1 57 1 62 1 68 1 68 1 72 1 72 1 74 1 79 1 82 1 84 1 84 1 86 1 89 191 1 94 1 96 1 96 1 97 1 98 200 202 203 Глава4.Структуры памяти 205 Глобальная область процесса и глобальная область пользователя Ручное управление памятью PGA Автоматическое управление памятью PGA Выбор между ручным и автоматическим управлением памятью Заключительные соображения по поводу использования областей PGA и UGA Системная глобальная область Фиксированная область SGA Буфер повторения Кеш буферов блоков Разделяемый пул Большой пул ПулJаvа Пул Streams Управление памятью SGA Резюме 206 208 215 228 230 230 236 237 238 246 249 25 1 252 252 258 Глава 5. Процессы Oracle 259 Серверные процессы Подключения посредством выделенного сервера Подключения посредством разделяемого сервера Резидентный пул соединений с базой данных 260 260 262 264 8 Соде ржан и е Подключения и сеансы Сравнение режимов выделенного сервера, разделяемого сервера и DRCP DRCP Заключительные соображения по поводу выделенного/разделяемого сервера Фоновые процессы Специализированные фоновые процессы Служебные фоновые процессы Подчиненные процессы Подчиненные процессы ввода-вывода Pnnn: серверы выполнения параллельного запроса Резюме 264 27 1 276 276 277 278 292 296 296 297 298 Глава 6. Блокировка и защелкивание данных 299 Понятие бло киров ки Проблемы бло киров ки Потерянные обновления Пессимистичес кая блокиров ка Оптимистичес кая блокировка Выбор между оптимистичес кой и пессимистической блокировкой Взаимобло кировки Эс калация блокировок Типы бло кирово к Бло киров ки DML Блокировки DDL Защелки Блокиров ка вручную и блокиров ки, определенные пользователем Резюме 299 303 303 305 307 315 320 326 326 327 339 344 356 357 Глава 7. Параллелизм и многоверсионность 359 Понятие управления параллелизмом Уровни изоляции транза кций Уровень изоляции READ UNCOMM I TTE D Уровень изоляции READ COMM ITTED Уровень изоляции RE PEATABLE READ Уровень изоляции S E RIAL I ZABLE Уровень изоляции READ ONL У Последствия многовереионной согласованности чтения Распространенный прием организации хранилищ данных, который не работает Объяснение неожиданно высокой активности ввода-вывода в "горячих" таблицах Согласованность записи Согласованные чтения и текущие чтения Наблюдение за перезапуском Почему перезапуск важен для нас'? Р�юш 359 36 1 363 364 366 369 372 373 374 Глава 8. Транзакции 389 Операторы управления транза кциями 390 375 378 378 38 1 385 3� Соде ржан ие 9 Атомарность Атомарность на уровне оператора Атомарность на уровне процедуры Атомарность на уровне транзакции Операторы DDL и атомарность Постоянство Расширения WRI T E оператора СОММ I Т Операторы COMM I T в нераспределенном блоке PL/ SQL Ограничения целостности и транзакции Ограничения IMMED IATE Ограничения DEFERRABLE и каскадные обновления Плохие привычки в отношении транзакций Фиксация в цикле Использование автоматической фиксации Распределенные транзакции Автономные транзакци и Как работают автономные транзакции Когда использовать автономные транзакции Резюме 392 392 394 398 398 399 399 40 1 403 403 404 408 409 417 418 420 42 1 423 426 Глава 9. Повтор и отмена 427 Что собой представляет redo Что собой представляет undo Совместная работа redo и undo Пpимep cцeнapияiNSERT - U P DATE - DELETE -COMM I T Обработка COMM I T и ROLLBACK Что делает оператор COMM I T? Что делает оператор ROLLBACK? Исследован ие redo Измерение rеdо Можно ли отключить генерацию журналов redo? Почему не удается разместить новый журнал? Очистка блоков Конкуренция за журнал Временные таблицы и redo/undo Исследован ие undo Что генерирует максимальный и минимальный объем информации undo? Ошибка ORA-0 1 5 5 5 : snapshot t o o o l d Резюме 428 429 433 433 438 439 446 448 448 450 454 456 46 1 464 470 470 473 486 Глава10. Таблицы базы данных 487 Типы табли ц Терминология Сегмент Управление пространством сегментов Маркер максимального уровня заполнения Списки свободных блоков Параметры PCT FREE и PCTUSED 487 490 490 493 494 496 50 1 10 Содержан и е Параметры LOGG ING и NOLOGG I NG Параметры I N I TRANS и МAXTRANS Традицион н ые таблицы И ндекс-табл и цы Заключительные соображения по поводу индекс-таблиц Кластеризованные и ндекс-таблицы Заключительные соображения по поводу кластеризованных индекс-таблиц Кластеризованные хеш -таблицы Заключительные соображения по поводу кластеризованных хеш-таблиц Отсортирован н ые кл астеризованн ые хеш-таблицы Вложенные таблицы Синтаксис вложенных таблиц Хранение вложенных таблиц Заключительные соображения по поводу вложенных таблиц Времен н ые таблицы Сбор статистики до версии Oracle 1 2с Сбор статистики , начиная с версии Oracle 1 2с Заключительные соображения по поводу временных таблиц Объектные таблицы Заключительные соображения по поводу объектных таблиц Резюме 505 505 505 509 526 527 535 536 545 546 549 550 559 562 563 568 572 577 577 585 585 Глава11.Индексы 587 Обзор и ндексов Oracle И ндексы со структурой В-дерева Сжатие ключей индекса И ндексы по реверсираванным ключам И ндексы, упорядоченные по убыванию Когда должен использоваться индекс со структурой В-дерева? Заключительные соображения по поводу индексов со структурой В-дерева Б итовые и ндексы Когда должен использоваться битовый индекс? Битовые индексы соединений Заключительные соображения по поводу битовых индексов И ндексы на основе фун кций Простой пример и ндекса на основе функции И ндексация только некоторых строк Реализация выборочной уникальности Предостережение относительно ошибки ORA-0 1 7 4 3 Заключительные соображения по поводу индексов на основе функций И ндексы предметной области Невидимые и ндексы М н ожество и ндексов на одной и той же комбинации столбцов И ндексация расширенных столбцов Решение с виртуальным столбцом Решение с индексом на основе функци и Ч асто задаваемые вопросы и мифы об и ндексах Работают ли и ндексы в представлениях? 588 590 593 596 603 605 617 618 619 624 627 627 628 638 640 640 642 642 644 646 646 648 650 65 1 65 1 Содержан ие 11 Могут ли значения NULL и индексы работать вместе? Должны ли быть проиндексированы внешние ключи? Почему индекс не используется? Миф: пространство никогда не используется в индексе повторно Миф: наиболее отличительные столбцы должны быть в индексе первыми Резюме 652 655 656 663 667 670 Глава 12. Типы данных 671 Обзор типов данных Orac1e Символьные и двоичные строковые тип ы Обзор NLS Символьные строки Двоичные строки : тип ы RAW Расширенные типы данных Числовые типы Синтаксис и использование типа NUMBER Синтаксис и использование типов B I NARY FLOAT/B I NARY_ DOUBLE Несобетвенные числовые типы Соображения по поводу производительности Типы LОNG Ограничения типов LONG и LONG RAW Копирование с участием унаследованн ых типов LONG Типы DATE, T IMESTAМ P и INTERVAL Форматы Тип DAT E Вариации типа T IMESTAМ P Тип INTERVAL Типы LOB Внутренние типы LOB Тип BFI LE Типы ROW I D и UROW I D Резюме 671 675 675 679 686 689 692 694 698 699 699 701 701 702 708 709 710 716 724 727 728 744 745 747 Глава 13. Секционирование 749 Обзор секционирования Повышенная доступность Облегчение задач администрирования Улучшенная производительность операторов Сокращение конкуренции в системе OLTP Схемы секционирован ия табли ц Секционирование по диапазонам ключей Хеш-секционирование Секционирование по списку значений ключа Секционирование по интервалам ключей Секционирование по ссьшкам Секционирование по интервалам ключей и по ссылкам Секционирование по виртуальному столбцу Составное секционирование 750 750 753 758 760 760 762 765 769 771 778 783 785 787 12 Содержан и е Перемещение строк Заключительные соображения по поводу схем секционирования таблиц Секционирование индексов Сравнение локальных и глобальн ых индексов Локальные индексы Глобальные и ндексы Системы OLTP и глобальные индексы Частичные индексы Еще раз о секционировани и и производительности Удобство средств обслуживания Множественные операции обслуживания секций Каскадное усечение Каскадный обмен Аудит и сжатие пространства сегментов Резюме 789 792 793 794 795 80 1 813 818 820 827 827 830 832 834 836 Глава 1 4. Параллельнов выполнение 837 Использование паралл ельного выполнения Аналогия параллельной обработки Orac1e Exadata Параллел ьн ы й запрос Паралл е льны й D M L Параллел ьн ы й D D L Параллельный DDL и загрузка данн ых с использованием внешних таблиц Параллельны й DDL и усечение экстентов П роцедурный параллелизм Параллельные конвейерные функции Самодельный параллелизм Самодельный параллелизм старой школы Резюме 839 840 842 843 849 854 855 857 867 868 87 1 875 879 Глава 15. Загрузка и выгрузка данных 881 Внешние таблицы Настройка внешних таблиц Обработка ошибок Использование внешней таблицы для загрузки разных файлов Проблемы многопользовательского доступа П редварительная обработка Заключительные соображения по поводу внешних таблиц В ы грузка Data Pump Инструмент SQLLDR Ч асто задаваемые вопросы п о загрузке данных посредством SQLLDR Предостережения относительно SQLLDR Заключительные соображен ия по поводу SQLLDR В ыгрузка в плоский файл Резюме 88 1 883 893 896 896 898 908 909 910 915 943 943 944 953 Предметный указатель 954 Об автора х Меня зовуr Том Кайт. Я работал на компанию Oracle со времен версии 7.0.9 ( ил и с 1 993 года - для тех, кто не ведет отсчет времени по версиям Oracle). Однако с самим продуктом Огас\е я имел дело примерно с версии 5.\.Sc ( однопользовательская вер­ сия для DOS, распространявшаяся на дискетах 360 Кбайт по цене $99). До перехода в Oracle я более шести лет я проработал специалистом по интеграции систем, строя крупномасштабные гетерогенные базы данн ых и приложения, в основном предна­ значенные для военных и правительствен н ых организаци й . В то время мне прихо­ дилось тратить немало времени на СУБД Oracle, в частности, оказы вая помощь тем , кто использовал базы дан ных Oracle. Я непосредственно контактировал с заказчи­ ками, либо определяя требования и строя их системы, либо чаще помогая их пере­ страивать и настраивать ("настройка" нередко является синон имом "перестрой ки " ) . Кроме того, я тот самый Том , которы й ведет колонку "As k Тот" ( " Спросите у Тома") в журнале Oracle Magazine, отвечая на вопросы по базам дан ных и и нструментам Oracle. Обычно в течение дня на веб-сайте http : 11 a s kt om . o r a c l e . c om я получаю и даю ответы на десятки вопросов. Каждые два месяца я публи кую луч ш ие их них в журнале (все заданные вопросы доступн ы в И нтернете; естественно, они хранятся в базе данных Orac\e). Вдобавок я веду технические семинары по м ногим темам , ко­ торые вы найдете в настоящей книге . В целом очень много своего времени я трачу, помогая людям успешно работать с базами данных Orac\e. И да, в свободное время я строю приложеимя и разрабатываю программное обеспечение в самой компани и Oracle. Эта книга отражает то, что я делаю каждый день. П редставленн ы й в ней мате­ риал раскрывает темы и вопросы, с которыми л юди сталкиваются ежедневно. Эти вопросы освещены с точ ки зрения " Когда я использую это, то поступаю вот так " . Книга является кульминацией м ноголетнего опыта использования этого продукта в несметном числе ситуаций. Дарл Кун администратор баз данных и разработчик, работающий на компанию Oracle. Он также преподает курсы по Orac\e в Университете Реджис (Денвер, штат Колорадо) и является акти вным членом ассоциации пол ьзователе й Скалистых гор (Rocky Mountain Orac\e Users Group). Дарл с удовольствием делится знания м и , что привело к реализации нескольких книжных проектов на протяжен и и последних лет. - О р е цензента х Мелани Кэффри - старш и й менеджер по разработке в Oracle Corporation, про­ двигающи й клиентские и серверные решения Oracle для бизнес-потребностей раз­ нообразных клиентов. Я вляется соавтором несколь ких технических публ и каций , включая книгу Expert Oracle Practice: Oracle Database Administration [гот the Oak ТаЬ/е, вышедшую в издательстве Apress, а также Oracle Web Application Programming for PL/ SQL Developers, Тhе Orac/e DBA lnteractive Workbook и Orac/e Database Administration: Тhе Complete Video Course, опубликованные издательством Prenti ce Hall. Она преподает в Нью-Й орке студентам программу Колумбийского университета " Компьютерные тех­ нологии и приложения " , обучая их расширенному администрировани ю и разработке на PL/ SQL. Кроме того, Мелани - частый докладчик на конференциях Oracle. 14 Об авторах Кристофер Бек получил диплом Ратгерекого уни верситета и работал со многими СУБД более 1 9 лет. П оследние 1 5 лет он является сотрудн иком компан ии Oracle , где занимает должность главного технолога, ориентируясь на основные технологии баз данных. Кристофер - соавтор двух патентов США в области программных ме­ тодологи й , которые стали основой того, что теперь известно как Oracle Application Express. Он ре цензировал и другие кни ги по Oracle, включая первую кни гу Тома Expert One-to-One (Apress, 2003 г. ) , а также сам выступал в роли соавтора двух кн иг ­ Beginn;ng Oracle Programm;ng (Apress, 2003 г.) и Mastering Oracle PL/SQL (Apress, 2004 г.) . Кристофер живет в Северной Вирджинии с о своей женой Мартой и четырьмя детьми, и когда не тратит время на них, обычно играет в видеоигры или смотрит футбол . Фриц Хуrланд- профессионал в области и нформационных технологий , специа­ лизирующийся на производительности и внутреннем устройстве баз данных Oracle. Фриц часто презентует технические тем ы Oracle на конференциях по всему миру. В 2009 году он получил премию Oracle АС Е от Oracle Technology N etwork и спустя год стал руководителем программы Oracle АСЕ. В 20 1 0 году Фриц присоеди н ился к OakTaЬie Network. В дополнение к опыту разработки для Orac\e он хорошо ориен ­ тируется в PostgreSQL и современных операционн ых системах. В настоящее время Фриц работает в компании Accenture из групп ы Acceпture Enkitec. Алекс Фаткулон - специалист по всему спектру технологи й Oracle . Его мас­ терство было жизненно важным при решении ряда огромных проблем, с которыми столкнулись его заказчики . Алекс опирается на годы опыта работы с крупнейшими мировыми компаниями , где е м у приходилось и меть дело практически с о всем , что относится к базам дан ных Oracle - от моделирования данных до построен ия архитектур в рамках решений высокой готовности и устранения проблем с производительностью исключительно больших производственных площадок. Он получ ил степень бакалавра по вычисл ительной технике в Дальневосточном государственном уни верситете ( Вл ади восток, Россия ) , а также я вляется членом Oracle АС Е и OakTaЬJe . Стефан Фаруль изучал язык SQL в 1 983 году с помощью СУБД SQL/DS про­ изводства I В М . В 1 98 6 году после полутора лет учебы в Оттавском ун и верситете ( Канада) он присоеди н ился к очен ь маленькой команде только что созданной ком­ пани и Oracle France и затем проработал год в I В М France . В 1 988 году Стефан ос­ тавил Oracle, занявшись разработкой программнога обеспечения, и вернулся к ба­ зам данных в августе 1 989 года. С тех пор он имел дело с базами данных, главным образом с Oracle, консультируя крупные французские компании на протяжении 25 лет. Стефан опубли ковал несколько кни г по SQL, вел семинары по Oracle в Азии , выкладывал учебные пособия по базам данных в YouTube и проводил для фран цуз­ ских студентов учебные курсы по базам данн ых, одновременно консультируя один крупн ы й банк. П олучая истинное удовольствие от обучения, в настоящее время он преподает вычислительную техни ку в Ун и верситете штата Канзас. Бла год арн ост и Я хотел бы поблагодарить многих людей за оказанную ими помощь в завершении этой книги. Прежде всего, я хочу выразить благодарность вам, читателям этой кни­ ги. Если вы читаете данную книгу, то высока вероятность того, что вы тем или иным образом поучаствовали в работе веб-сайта http : 1 / a s ktom . ora c l e . сот/ , возможно, задав один или два вопроса. Такое действие - получение вопросов и исследование от­ ветов - снабжает меня материалом для книги и знаниями, на которых основан этот материал. Без ваших вопросов я бы никогда не знал о С У БД Oracle столько, сколько знаю сейчас. Так что в конечном итоге именно вы сделали возможным появление на­ стояшей книги. Я хотел бы поблагодарить Тони Дэвиса за его усилия по приведению моей работы в действительно читабельный вид. Если вам нравится последовательность и разбиение книги на разделы, и вы находите представление материала четким, то в значительной степени это достигнуто стараниями Тони. Я работаю с Тони при написании техничес­ ких материалов, начиная с 2000 года, и вижу, насколько выросли его знания Oracle за это время. Он способен выполнять не только литературное редактирование материала, но во многих случаях и научное редактирование. Многие из примеров, представлен­ ные в этой книге, появились благодаря именно ему (без них случайный читатель прос­ то не смог бы разобраться в материале). Тони не редактировал второе издание книги, но содержимое во многом основано на первом издании. Без него настоящая книга не стала бы такой, как она есть. Если бы не группа квалифицированных рецензентов, с которыми я сотрудничал во время написания этой книги и ее предыдущего издания, то мне пришлось бы пере­ живать за ее содержимое. Первое издание рецензировали Джонатан Льюис, Родерик Маналак, Майкл Меллер и Г эйб Романеску. Они потратили массу времени на проверку правильиости материала с технической точки зрения и оценку его полезности в ре­ альной практике. Вторым изданием занималась команда отнюдь не меньшего калибра: Мелани Кэффри, Кристофер Бек и Джейсон Страуб. Я глубоко убежден, что техни­ ческая книга должна оцениваться не только теми, кто ее написал, но и сторонними рецензентами. Благодаря этим людям, я чувствую себя уверенным относительно изло­ женного материала. В компании Oracle я работаю с самыми лучшими и одаренными людьми из всех, с кем мне доводилось встречаться, и каждый из них, так или иначе, внес свой вклад в создание этой книги. В частности, я хотел бы поблагодарить Кена Якобса за его подде­ ржку и энтузиазм на протяжении многих лет. К сожалению, Кен больше не работает в Oracle, но его влияние сохранится надолго. И последнее, но самое важное - я хочу выразить признательность за постоянную поддержку членам своей семьи. Вы знаете, насколько важно чувствовать себя кому-то нужным, когда вы пытаетесь сделать что-то, требующее траты многих часов "в нерабо­ чее время". Не представляю, как бы я смог завершить эту книгу без постоянной подде­ ржки со стороны своей жены Мелани (которая также бьша техническим рецензентом книги), сына Алана и дочери Меган. Ка й т Том Я хотел бы поблагодарить Тома за то, что он пригласил меня поработать с ним над этой книгой; это большая честь для меня. Также я хочу выразить благодарность Джонатану Геннику; его руководство (на протяжении многих лет и книг) заложило для меня основу, которая позволила быть в состоянии трудиться над книгой подобного уровня. И я также благодарен Хейди, Лизе и Бренди; без вашей поддержки я не смог бы успешно поучаствовать в настоящем проекте. Дарл Кун Введение Вдохнове н и е изложить собранн ы й в этой кни ге материал поя вилось у меня вследствие приобретенного опыта разработки программнога обеспечен ия Oracle, со­ трудничества с другими разработчи ками Oracle и оказания им помощи в построении надежн ых приложений на основе баз данн ых Oracle. В целом эта кн ига отражает то, чем мне приходится заниматься ежедневно, и в ней освещены вопросы, с которыми пользователи сталкиваются в своей повседневной работе. Я раскрыл здесь то, что считаю наиболее важным, а именно - базы данных O racle и их архитектуру. Я мог бы написать аналогично озаглавленную кни гу, пос­ вящен ную разработке приложени й с испол ьзованием кон кретного языка и архи­ тектуры - например, приложени й , которые применяют JavaServer Pages для вза­ имодействия с компонентами Enterprise JavaBean ( EJB) , которые, в свою очередь, испол ьзуют JD BC для обмена данн ы ми с Oracle. Однако, по большому счету, для успешного построения таких приложений вы действительно должны хорошо разби­ раться во всех темах, рассмотре н н ых в н астоящей кни ге . В ней собран материал , которы й , по моему глубокому убеждению, должен быть всесторонне усвоен дл я ус­ пеш ной разработки приложе н и й в среде Oracle, будь вы программистом на Visual Basic, применя ющим O D B C , программистом на Java, использующим компонен­ ты EJB и JDBC, или программистом на Perl , испол ьзующим D В I -и нтерфейс Perl . В кни ге не продвигается какая-то специфичная архитектура приложени й ; в ней не сравниваются трехуровневая и клиент-серверная архитектуры. Вместо этого в книге объясняется , что может делать база дан н ых, и что вы должн ы понимать в плане осо­ бенностей ее функционирования . Поскольку база данных находится в основе архи­ тектуры любого приложения, книга должна иметь ш ирокую аудиторию. Как следует из названия , эта кни га сосредоточена на архитектуре базы дан ных и работе самой базы дан ных. Я подробно раскрываю архитектуру базы дан н ых Oracle - файл ы , структуры памяти и процессы , которые образуют базу данных и экземпляр. Затем я перехожу к обсуждению таких важных тем , как блокировка, уп­ равлен и е п араллелизмом , функционирование транзакций, повторение и отмена, и поясня ю, почему эти вопросы настолько важны . Н аконец, я рассматриваю физичес­ кие структуры базы данных, такие как таблицы, и ндексы и типы данных, освещая приемы их оптимального применения. О чем эта книга Одна из проблем, обусловлен н ая наличием многочисленных возможностей при разработке, заключается в том , что иногда трудно выбрать вариант, который лучше всего подходит в конкретных обстоятельствах. Каждый желает заполучить максималь­ но возможную гибкость (столько вариантов, сколько вообще можно иметь) , но при этом хочет, чтобы все оставалось очень ясным - другими словами, простым. СУБД Oracle предлагает разработчи кам практически неограниченные возможности выбора. Н и кто н икогда вам не скажет: " В ы не сможете сделать это в Oracle" . Наоборот, вы услышите: "Сколькими разными сnособами вы предпочитаете делать это в Oracle?" . Я надеюсь, что данная кни га поможет вам производить правильный выбор. Кни га адресована тем , кто высоко ценит наличие выбора, но также предпочитает расп олагать какими-то руководящими принцилами и сведен иями о практических реализациях функциональных средств и возможностей Oracle . Например, в Oracle Введение 17 имеется по-настоящему эффективное средство, которое называется параллельным выполнением. В документации Oracle рассказано, как его испол ьзовать и что оно делает. Однако в ней н ичего не говорится о том , когда вы должн ы и - что, пожа­ луй , еще важнее - когда не должны применять это средство. В документации дале­ ко не всегда сообщаются детали реализации средства, и если вы не осведомлены о них, это может еще не раз дать о себе знать. (Здесь я не имею в виду программные ош ибки , а способ, которым средство предположительно функционирует, и для чего оно в действительности было предназначено.) В этой кни ге я стремился не только описать, как работает та или иная функция , но также и объясн ить, когда и почему вы должны обдумать возможность испол ьзо­ вания отдельного средства или реализации . Я твердо убежден , что в отношении всех сущностей важно понимать не только " как" , но также " когда" и " почему " , а заодно " когда нет" и " почему нет". Кому адресована эта книга К целевой аудитори и этой кн и ги относится любой, кто зан и мается разработ­ кой приложений на основе баз дан ных Oracle . Она предназначена для п рофесси ­ анальных разработч и ков Oracle, которым необходимо знать способы выполнения действи й в базе данных. П рактическая природа кни ги означает, что многие разде­ лы должны быть очень интересными также и администраторам баз данных. В боль­ шинстве примеров для демонстрации ключевых средств применяется SQL* Plus, так что не надейтесь обнаружить в них по-настоящему крутой графически й пользова­ тельски й интерфейс, но вы узнаете, как работает база дан ных Oracle , что могут де­ лать ее ключевые средства и когда они должны (и не должны) использоваться . Книга ориентирована на любого, кто желает получить от Oracle максимум , при­ кладывая минимальные усилия . Она предназначена для любого, кто и щет новые ме­ тоды применения существующих средств. Она рассчитана на тех, кто хочет увидеть, как эти средства можно задействовать в реал ьном мире (не просто ознакомиться с примерами использования фун кци и , но в первую очередь понять, почему она ока­ зывается подходящей в той или и ной ситуаци и ) . Еще одной категорией людей, кого может заи нтересовать эта кни га, я вляются техн ические руководители , ответствен ­ ные за разработчиков, которые зан имаются проектами Oracle. В некоторых отноше­ ниях очень важно, чтобы техн ические руководители понимал и , почему знание базы данных имеет решающее значение в достижении успеха. Эта кни га может стать се­ рьезным подспорьем руководителям, которые хотят, чтобы их персонал был обучен надлежащим технологиям, ил и желают убедиться , что персонал уже знает то, что должен знать. Чтобы извлечь максимал ьную пользу из этой кн и ги , читатель должен соответс­ твовать следующим характеристикам . • Знать язык SQL. Вовсе не обязательно быть луч ш им кодировщи ком SQL во все времена, но хорошие практические навыки помогут в освоени и . • Понимать PL/SQL. Это не я вляется обязательным условием , но облегч ит ус­ воение примеров. Например, данная кни га не научит вас применению цикла FOR или объявлению типа зап иси ; вопросы такого рода подробно освещены в документации по Oracle и многочислен н ых кни гах. Тем не менее, нельзя ска­ зать, что вы не изучите много нового о PL/SQL, когда будете читать эту книгу. 18 Введени е Вы освоите разнообразные возможности P L/S QL, узнаете о новых способах решения задач и ознакомитесь с пакетамиjфункциями, о сушествовании кото­ рых, возможно, даже не подозревали . • Иметь представление о каком-нибудь языке третьего поколения, таком как С или Java. Я уверен , что любой , кто способен читать и писать код на языке тре­ тьего поколения , сможет успешно понять примеры, приведеиные в этой книге. • Быть знакомым с руководством по концепциям базы данных Oracle (Oracle Database Concepts). П оследний пункт требует дополн ительной пары слов: из-за значительного объ­ ема набора документации по Oracle многие находят ее устрашающе большой . Если вы только приступили к изучению или пока е ще не прочитали ни одного докумен­ та из набора, то могу вас заверить, что руководство Oracle Database Concepts - это именно то, с чего следует начинать. Оно занимает около 450 страниц (я хорошо это знаю, т. к. некоторые страницы написаны мною, а редактировать мне довелось це­ ликом все руководство) и затрагивает многие из основных кон цеп ций Oracle, о ко­ торых необходимо знать. Оно может не предоставлять абсолютно все технические детали (им посвящены остальные 10 000 - 20 000 стран иц документации), но обучит вас всем важнейшим концепция м . В руководстве Oracle Database Concepts раскрыты перечисленные н иже темы (здесь упомянуты далеко не все): • структуры в базе данн ых и способ организации и хранения данных; • распределенная обработка; • архитектура памяти Oracle; • архитектура процессов Oracle; • объекты схемы, которые вы будете использовать (таблицы, индексы, кластеры и т.д . ); • встроен н ые и определяемые пользователем т ипы дан ных; • хранимые процедуры SQL; • работа транзакций; • оптимизатор; • целостность данных; • управление параллелизмом. Время от времен и я и сам буду возвращаться к этим темам . Они явля ются фунда­ ментальными. Без их знания вы будете создавать приложения Oracle, предрасполо­ жен н ые к отказам. Я настоятельно рекомендую прочитать это руководство и усвоить упомянутые вопросы. Как структурирована эта книга Чтобы помочь в работе с кни гой , большинство глав организовано в виде четы ­ рех основных разделов (как описано н иже) . Хотя это не жесткое разделение, оно позволяет быстрее переходить к области, в которой требуется дополнительная ин­ формация . Книга содержит 15 глав, причем каждая из н их подобна "мини-книге" - Введе н и е 19 практически самостоятельному ком поненту. И ногда я ссылаюсь на примеры или средства, описан ные в других главах, но л юбую главу кни ги вполне можно читать независимо от остальных. Например, вовсе не обязательно сначала читать главу 1 0, посвященную табл ицам базы дан н ых, чтобы понять материал главы 1 4, в которой рассматри вается параллелизм . Формат и стиль многих глав практически идентичен и представлен н иже. • Введение в функциональное средство или возможность. • Прич и н ы , по которы м может потребоваться применение ( ил и отказ от ис­ пользования) этого средства или возможности . Здесь даются пояснения отно­ сительно того, когда следует подумать о примене н и и этого средства, а когда отказаться от него. • Как использовать это средство. Приводимые здесь сведения не являются прос­ то копией материала из справочника по SQL. Напротив, они представлены в пошаговом виде : то, что необходимо получить, то, что понадобится сделать, и вопросы, которые нужно выяснить, чтобы начать. В этом разделе рассматри­ ваются следующие темы : о способ реал изации средства; о примеры применения ; о способ отладки средства; о предостережения относительно испол ьзования средства; о способ обработки ош ибок (упреждающим образом) ; о резюме с кратким подведен ием итогов. Кни га содержит большое количество примеров и кода, которые доступн ы для за­ грузки на веб-сайте издательства. В последующих разделах приведен ы краткие опи ­ сания содержимого всех глав. Глава 1. Разработка успешных приложений Oracle В этой главе я описываю свой подход к программирован и ю для баз дан н ых. Базы дан ных не создавались оди наковым и . Для того чтобы усп е ш н о и с воевре­ менно разрабаты вать п риложен ия , управляемые базами данн ых, необходимо четко понимать, что именно кон кретная база дан ных способна делать, и каким образом она это делает. Без знания того, что может делать база дан н ых , воз н икает риск постоянно заново изобретать колесо, создавая средства, которые база данн ых уже предоставляет. Без понимания того, каким образом работает база дан ных, скорее всего, будут получаться п риложе н ия, которые функционируют н еэффективно и ведут себя непредсказуемо. В главе предлагается эмпирический взгляд на некоторые приложения , где недо­ статок понимания базы данных привел к неудаче всего проекта. В соответствии с таким ориентирован ным на примеры подходом здесь обсуждаются основные средс­ тва и фун кци и базы дан ных, которые должн ы хорошо пониматься разработчи ком . Суть в том , что вы не должны позволять себе трактовать базу данных как черны й ящик, которы й просто выдает ответы и самостоятельно заботится о масштабируе­ мости и производительности. 20 Введе н и е Глава 2. Обзор архитектуры В этой главе раскрываются основы архитектуры Oracle. Мы начнем с четких оп­ ределений двух терминов, которые многими в мире Oracle понимаются совершенно неправил ьно - экземпляр и база данных. Затем мы рассмотрим два новых типа баз данн ых, появившиеся в версии Oracle 1 2с, в частности - контейнерная база данных и подключаемая база данных. Кроме тоm, мы кратко обсудим системную глобальную об­ ласть (System Global Area - SGA) и процессы, лежащие в основе экземпляра Oracle, а посмотрим, каким образом выполняется простое действие "подключен ия к Oracle". Глава 3. Файлы В этой главе подробно оп исан ы восем ь ти пов файлов, которые образуют базу дан ных и экземпляр Oracle . Н ач и н ая с простого файла параметров и заканчи вая файлами данных и журнальными файлами повторения, мы посмотрим, что они со­ бой представляют, каково их назначение и каким образом они используются . Глава 4. Структуры памяти В этой главе освещены вопросы использования п амяти базой данн ых Oracle, как памяти в отдел ьных процессах ( PGA) , так и разделяемой памяти (SGA) . Мы иссле­ дуем отличия между ручным и автоматическим управлением памятью PGA, автома­ тическим управлением разделяемой памятью в Oracle 1 Og и автоматическим управ­ лением п амятью в Oracle l l g, а также выясн им, в каких случаях подходит каждый из этих методов. После прочтения этой главы вы получите полное представление о том , каким образом Oracle работает с памятью и управляет ею. Глава 5. Процессы Oracle В этой главе предлагается обзор типов процессов Oracle (серверных и фоновых процессов). Кроме того, в ней более подробно описаны отл ичия между подключе­ нием к базе дан н ых с помощью процессов разделяемого и выделенного серверов. М ы также рассмотрим большинство фоновых процессов (таких как LGWR, DBWR, PMON, SMON и LREG), действующих во время запуска экземпляра Oracle, и обсудим их функции. Глава 6 . Блокировка и защелкивание данных В разн ых базах данн ых задачи решаются по-разному (то, что хорошо работает в SQL Server, может не так хорошо работать в Oracle) , и пони мание особенностей реал изации блокировки и управления параллелизмом абсолютно необходимо для успешного построения приложе н и й . В этой главе рассматривается общи й подход, испол ьзуемый в Oracle для решения этих задач , тип ы блокировок, которые могут быть применены ( D M L, D D L и защелки ) , а также проблемы , которые могут возни­ кать при неаккуратной реализаци и блокировки (взаимоблокировка, блокирование и эскалация) . Глава 7. Параллелизм и многоверсионность В этой главе мы будем исследовать мое любимое средство Oracle - м ноговереи­ он ность, а также его влияние на управление параллелизмом и всю структуру nрило­ жен ия . Здесь будет nоказано, что все базы дан н ых отличаются друг от друга, а сама их реализация может влиять на структуру приложе н и й . Мы начнем с обзора раз- Вве де н и е 21 нообразн ых уровней изоляции транзакци й , как они определены стандартом AN S I SQL, и посмотрим , каким образом они отображаются н а реализацию Oracle (а также соответствие этому стандарту других баз данных) . Затем мы проанализируем пос­ ледствия, которые может и меть для нас многоверсионность - средство, позволяю­ щее Oracle обеспечивать неблакирующее чтение базы данных. Глава 8. Транзакции Транзакции являются фундаментальным средством всех баз данных - это часть того , что отл ичает базу дан н ых от файловой системы. Н есмотря на это, их часто понимают неправильно, и многие разработчи ки даже не подозревают о том , что неумышленно отказы ваются от их применения. В этой главе показано, как долж­ ны использоваться транзакции в Oracle, а также раскрыты плохие привычки , кото­ рые могли быть приобретены при разработке приложе н и й для других баз дан ных. В частности , мы взгля нем на последствия атомарности и ее влияние на операто­ ры в Oracle. М ы также обсудим операторы управления транзакциями (сомм r т , SAVE PO I N T и RO LLBAC K ) , ограничения целостности , распределенные транзакции (двухфазную фиксацию) и автономные транзакции. Глава 9 . nов тор и отмена Можно было бы сказать, что разработчикам не обязательно разбираться в деталях реал изации повтора (redo) и отмены (undo) в такой же степени, как администрато­ рам баз данных, но разработчи ки должны знать, какую роль и грают повтор и отмена в базе данных. П осле определения понятия повтора мы посмотрим, что в точности делает оператор сомм r т. Мы обсудим, каким образом выяснить объем сгенериро­ ванной информации redo и как с помощью конструкции NOLOGG I NG значительно сократить объем и нформаци и redo, генерируемой определенными операциями . М ы также исследуем генерацию дан ных redo в связи с таким и проблемами , как очистка блоков и конкурен ция за журналы. В разделе главы , посвященном отмене, м ы рассмотрим роль дан н ых undo и опе­ рации , которые генерируют наибол ьш и й/наименьший объем информаци и undo. Наконец, мы обсудим печально известную ош ибку ORA- 0 1 555 : snapshot too o l d (ORA-0 1 555: устаревший снимок) , возможные причи н ы е е возникновения и спосо­ бы ее предотвращен ия . Глава 10. Таблицы базы данных В настоя щее время Oracle поддерживает м ножество типов таблиц. В этой главе мы по очереди рассмотрим тип ы таблиц - традиционная таблица (т.е. стандартная , "нормальная" таблица) , индекс-таблица, кластеризованная и ндекс-таблица, класте­ ризованная хеш -таблица, вложен ная таблица, временная таблица и объектная таб­ лица - и обсудим когда, как и почему они должны использоваться. Большую часть време ни традиционной таблицы вполне достаточно, но данная глава поможет рас­ познать ситуации , в которых лучше подходят другие тип ы . Глава 1 1 . Индексы И ндексы я вля ются критически важ н ы м аспектом структуры приложе н и я . Корректная реализация требует глубоких знани й данных, и х распределения и плани­ руемого использования. Слишком часто при разработке приложений к и ндексам отно­ сятся как к чему-то второстепенному, из-за чего в итоге страдает производительность. 22 Введе н и е В этой главе подробно рассматриваются различные типы и ндексов, включая ин­ декс со структурой В-дерева ( B*Tree), битовый и ндекс, и ндекс на основе функций и и ндекс предметной области , и обсуждаются обстоятельства, когда они должны , а когда не должны применяться . В разделе, посвященном часто задаваемым вопро­ сам и мифам об и ндексах, я также отвечу на ряд распространенных вопросов вроде " Работают ли и ндексы на представлениях?" и " Почему индекс не используется?" . Глава 12. Типы данных На выбор доступно большое количество типов дан ных. В этой главе исследуются все 22 встроенных типа данных, приводятся объяснен ия их реал изации и рассмат­ р иваются способы и случаи их применения . В начале главы приводится краткий обзор поддержки национальных языков (National Language Support - N LS), знание которой обязател ьно для пол ного понимания простых строковых типов в Oracle. Затем мы перейдем к обсужден и ю вездесущего типа NUMBER. Далее мы раскроем типы LONG и LONG RAW главным образом с исторической точ ки зрения. Основная цель здесь - показать, как работать в приложен иях с унаследованными столбцами LONG и переводить их в тип LOB. После этого мы углубимся в разнообразные ти пы данных для хране н ия значений даты и времен и и удели м внимание ман ипулиро­ вани ю различными типами дан н ых для получения нужного результата. Также будут описаны основы поддержки часовых поясов. Следующими мы обсудим тип ы данн ых L O B . Мы рассмотри м способы их хра­ нения и смысл каждого из м ногочислен н ых настроек, таких как IN ROW , CHUNK, RETENT I ON, САСНЕ и т.д. При работе с типами данных LOB важно понимать, как они реализованы и каким образом хранятся по умолчани ю - особенно, когда дело до­ ходит до настрой ки их извлечен ия и хранения. Глава завершается описанием типов ROW I D и UROW I D. Это специальные патентованные тип ы Oracle, которые представ­ ля ют адрес строки . Мы объясн и м , когда их использовать в качестве типа дан н ых столбца в таблице (что почти н и когда не случается) . Глава 13. Секционирование Секционирование предназначено для облегчения управления очень большими табли цами и и ндексами за счет реализации кон цепции " разделя й и властвуй " ; в основном оно сводится к разбиен и ю таблицы или и ндекса на множество мелких и более управляемых частей . Это область, в которой адми н истратор базы данных и разработчи к должны работать вместе с целью обеспечения максимальной доступ­ ности и производительности приложения. Здесь также подробно раскрыты функци­ ональные средства, появившиеся в версиях Oracle l l g и Oracle 1 2с. В главе рассматривается секцион иро вание как табли ц , так и и ндексов. Будет описано секционирование с использованием локальных и ндексов (распространено в хранилищах данн ых) и глобальных и ндексов (распространено в системах OLTP). Глава 1 4 . Параллельное выполнение В этой главе представлена концеп ция и случаи применения параллел ьного вы­ полнения в Oracle . Мы начнем с рассмотрен ия ситуаций , когда параллельная обра­ ботка полезна и должна использоваться , а также ситуаци й , когда она планироваться не должна. П осле этого мы перейдем к анализу механики параллельного запроса средства, которое большинство л юдей ассоциирует с параллельным выполнен ием. Введе н и е 23 Затем мы опишем язык P D M L ( Parallel D M L) , которы й позволяет п роводить моди­ фикации с испол ьзован ием параллел ьного выпол н е н ия . Мы посмотри м , как язык PDM L физически реализован , и почему эта реал и зация при водит к ряду огран иче­ н и й , касающихся P D M L. Дал е е мы зай м е м ся и сследова н и е м п араллел ьн о го D D L. П о моему м н е н и ю , именно здесь параллел ьное выпол н е н и е проявляется в о всей своей красе. Обы ч н о адм и н истраторы б а з дан н ых располагают н ебол ь ш и м и окнам и обслужи ван и я , в рамках которых должн ы выполнять круп ные операци и . П аралл ел ь н ы й D D L предо­ ставляет адм и н истраторам баз данн ых возможность в полной мере задей ствовать все доступные ресурсы комп ьютера, позволяя им завершать большие и сложные опера­ ции за какую-то долю времен и , которое они отняли бы при последовател ьном в ы ­ полне н и и . Глава завершается рассмотрен ием процедурного параллелизма, т. е . средства, с п о ­ мощью которого мы можем выпол нять код приложен ия параллел ьно. Здесь раскры­ ваются две технологи и . П ервая из н и х - параллельные конвейерные функци и , или способность Oracle параллельна в ы п ол нять хран и м ы е фун кц и и динамическим об­ разом . Вторая технология - это " самодел ьн ы й " п араллел изм (do-it-yourself - D I Y) , когда приложение проектируется так, чтобы оно могло выполняться параллельно. Глава 15. Загрузка и выгрузка данных Внимание в первой половине этой главы сосредоточено на вне ш н их табли цах высокоэффе ктивном средстве, с помощью которого осуществляется м ассовая за­ грузка и вы грузка данных. Есл и вы выполняете большой объем загрузки дан н ых, то должны всерьез подумать о применен и и вне ш н их табл и ц . Здесь также подробно об­ суЖДается средство предварительной обработки в не шн их табл и ц , которое позволяет командам операционной систе м ы автоматически выполняться как часть выборки из внешней таблицы. Вторая полов и н а главы посвя щ е н а S Q L* Loader ( S Q L L D R) и разн ообраз н ы м способам испол ьзования этого и н струмента для загрузки и модификац и и дан н ы х в базе. Рассматриваются такие вопросы , как загрузка дан н ых с разделителям и , обнов­ ление существующих строк и вставка новых строк, выгрузка данн ы х и обращение к SQLLD R из хранимой процедуры . SQLLDR - это тщательно продуман н ы й и очен ь важный инструмент, но с его практическим применением связано немало вопросов. И сходный код и обновления Усваивать материал этой кни ги эффекти внее всего путем тщательной проработки и разбора практических примеров. Работая с примерами , вы можете предпочесть вво­ дить весь код вручную. М ногие читатели выбирают такой подход потому, что он явля ­ ется хорошим способом ознакомиться с используемыми приемами написания кода. Реш ите вы набирать код самостоятел ьно или нет, исходны й код всех при меров, приведеиных в настоящей книге , доступен на веб-сайте издательства. Есл и вы пред­ почитаете вводить код вручную, то файлы и сходного кода можно применять для проверки ожидаемых результатов - это следует делать в первую очередь, когда есть подозрен и е , что код был набран с ошибко й . Если вам не нравится вводить код вруч­ ную, то без загрузки исходного кода с веб-сайта издательства не обойтись. В любом случае файлы кода помогут вам с обновлен ием и отладкой . 24 Введен и е От издательства В ы , читател ь этой книги, и есть главный ее критик и комментатор. М ы ценим ваше мнение и хотим знать, что было сделано нами правильно, что можно было сде­ лать луч ше и что еще вы хотели бы увидеть изданным нами. Нам интересно услы­ шать и любые другие замечания, которые вам хотелось бы высказать в наш адрес. Мы ждем ваш их комментариев и надеемся на них. В ы можете прислать нам бу­ мажное или электронное п исьмо, л ибо просто посетить наш веб-сайт и оставить свои замечания там . Одн и м словом , л юбым удобным для вас способом дайте нам знать, нравится или нет вам эта кни га, а также выскажите свое мнение о том, как сделать наши кни ги более интересными для вас. Посылая письмо ил и сообщение, не забудьте указать название книги и ее авто­ ров, а также ваш обратны й адрес. М ы внимательно ознакомимся с вашим мнением и обязател ьно учтем его при отборе и подготовке к издан и ю последующих книг. Наши коорди наты : E-mail : WWW: i n fo @ w i l l i a rns puЫ i s h i ng . co rn h t t p : / / www . w i l l i a rns puЬ l i s h i ng . co rn И нформация для п исем из: России: Украин ы : 1 27055 , г. Москва, ул . Лесная , д. 43 , стр. 1 03 1 50, Киев, а/я 1 52 Н а с тр о й ка с р ед ы В этом разделе я объясню, как настроить среду, чтобы в ней можно было выпол­ нять приведеиные в книге примеры кода. В частности , рассматри ваются следующие вопросы. • Настройка учетной зап иси EODA, используемой во м ногих примерах. • Корректная настройка демонстрационной схемы sсотт / T I GER. • Настройка и запуск необходимой среды . • Конфигурирован ие средства AUTOTRAC E в SQL* Plus. • Установка пакета Statspack. • Установка и запуск Runstats и других специал ьных утилит, применяемых в книге повсеместно. • Соглашения по кодированию, используемые в этой кни ге. Все сценарии, которые не поставляются Oracle, доступн ы для загрузки на веб­ сайте издательства. В загруженном архиве со сценариями имеются папки chNN, со­ держащие сценарии для каждой главы (NN это номер главы) . Сценарии , перечис­ ленные в разделе " Настройка среды " , находятся в папке chO O . - Н астройка учет ной записи EODA Пользователь EODA участвует в больши нстве примеров, рассматри ваемых в этой книге. Это просто учетная запись, которой была вьщана роль администратора базы данных и привилегии EXECUTE и S E LECT на определенных объектах, принадлежа­ щих SYS: connect 1 as sysdЬa de fine username=eoda de fine usernamepwd= foo create user & &use rname identi fied Ьу & &use rnamepwd ; grant dba to & &username ; grant execute on dbms_stats to & &u s e rname ; grant s elect on V_$ STATNAМE to & & u s e rname ; grant s elect on V_$МYSTAT to & & u s e rname ; grant s elect on V_$ LATCH to & & u s e rname ; grant s elect on V_$ T IMER to & &use rname ; conn & & use rname / & &use rnamepwd Вы можете настроить любого желаемого пользователя для запуска примеров в этой книге. Я выбрал в качестве имени пол ьзователя EODA просто потому, что оно является аббревиатурой англоязычного ори гинала настоящей книги . 26 Настрой ка среды Н астройка схемы scoтт/ T I GER Схема sсотт / T I GE R часто уже будет существовать в базе дан н ых. Обычно она в кл ючена в типовую установку, но не я вляется обязательным компонентом базы дан н ых. Пример схемы s с о т т можно установить для любой учетной записи базы данн ых; с применением учетной записи s сотт не связано ничего магического. При желании можете установить таблицы Е М Р / DE PT прямо в собствен ную учетную за­ п ись базы данн ых. Многие примеры в этой книге полагаются на таблицы в схеме sсотт. Чтобы по­ работать с таким и примерами , вам понадобятся эти таблицы. Если вы имеете дело с совместно используемой базой данн ых, целесообразно установить собственную коп и ю этих табли ц от имени учетной записи, отлич ной от s сотт , чтобы избежать побочных эффектов, возникающих из-за того, что другие пользователи затрагивают те же самые данные. В ыполнение сценария Чтобы создать демонстрационн ые таблицы схемы SCOT T , выполните следующие действия : • введите команду cd $ 0RACLE_HOME / s ql p l u s / demo; • после подключения от имени л юбого пользователя запустите сценари й de ­ moЬ l d . s q l . Н а заметку! В Orac/e 1 O g и последующих версиях демонстрационные подкаталоги должны устанавливаться из установочного носителя . Н иже будут воспроизведены необходимые компоненты demoЫ d . s q l . Сценарий demoЬ l d . s q l создаст и заполнит данными пять таблиц. По заверше­ нии он автоматически заверш ит сеанс SQL* Plus, поэтому не удивляйтесь, когда пос­ ле выпол нения сценария окно SQL* Plus исчезнет с экрана - так было задумано. В стандартных демонстрацион ных таблицах никаких огран ичений ссылочной це­ лостности не определено. Некоторые примеры рассчитывают на то, что в них под­ держивается ссылочная целостность. Поэтому после запуска сценария demoЬ ld . sql рекомендуется выполнить также следующие операторы : a l t e r tаЫе emp add cons t rai nt emp_p k prima ry key ( empno ) ; a l t e r tаЫе dept add con s t raint dept_p k prima ry key ( deptno ) ; alter taЬle emp add constraint emp_fk_dept foreign key (deptno ) references dept ; a l t e r tаЫе emp add con s t raint emp_f k_emp foreign ke y ( mgr ) re fe rence s emp ; На этом установка демонстрационной схемы завершена. Если в какой-то момент вы захотите удалить эту схему с целью освобожден ия места на диске, можете просто запустить сценарий $0RACLE_HOME / s qlplus /demo / demodrop . s q l . Он удалит пять таблиц и завершит сеанс SQL* Plus. Совет. Команды SQL для создания и удаления пол ьзователя sсотт можно также найти в сце­ нарии $ 0RACLE_HOME / rdbms /admi n / u t l s amp l . s ql . Н астрой к а среды 27 Создание схемы без с цена р ия Если доступ к файлу demoЬ l d . s q l отсутствует, для работы с приведе и н ы м и в книге примерами достаточно выпол нить следующие команды: CREATE ТАВLЕ ЕМР ( EMPNO NUМВER ( 4 ) NOT NULL 1 ЕNАМЕ VARCНAR2 ( 1 0 ) 1 JOB VARCНAR2 ( 9 ) 1 MGR NUМBER ( 4 ) 1 H I REDATE DATE 1 SAL NUМBER ( 7 1 2 ) 1 СОММ NUМВER ( 7 1 2 ) 1 DE PTNO NUМВER ( 2 ) ) ; INSERT INTO ЕМР VALUES ( 7 3 6 9 1 1 SMITH 1 1 1 CLERК 1 1 79021 TO_DATE ( 1 1 7 - DEC- 1 9 8 0 1 1 1 DD-MON-YYYY 1 ) 1 8 0 0 1 NULL 1 2 0 ) ; INSERT INTO ЕМР VALUES ( 7 4 9 9 1 1 ALLEN 1 1 1 SALESМAN 1 1 7 6 9 8 1 TO_DATE ( 1 2 0 - FEB- 1 9 8 1 1 1 1 DD-MON-УУУУ 1 ) 1 1 6 0 0 1 3 0 0 , 3 0 ) ; INSERT INTO ЕМР VALUES ( 7 52 1 , 1 WARD 1 , 1 SALESМAN 1 , 7 6 9 8 , TO_DATE ( 1 2 2 - FEB- 1 9 8 1 1 , 1 DD-MON-YYYY 1 ) , 1 2 5 0 , 5 0 0 , 3 0 ) ; INSERT INTO ЕМР VALUES ( 7 5 6 6 , 1 JONES 1 , 1 МANAGER 1 , 7839, TO_DATE ( 1 2 -APR- 1 9 8 1 1 , 1 DD-MON-YYYY 1 ) , 2 9 7 5 , NULL , 2 0 ) ; INSERT INTO ЕМР VALUES ( 7 65 4 1 1 МART I N 1 1 1 SALESМAN 1 , 7 6 9 8 , TO_DATE ( 1 2 8 -S E P- 1 98 1 1 , 1 DD-MON-YYYY 1 ) , 1 2 5 0 , 1 4 0 0 , 3 0 ) ; INSERT INTO ЕМР VALUES ( 7 6 9 8 , 1 ВLАКЕ 1 , 1 МANAGER 1 , 7839, ТО_DАТЕ ( 1 1 -МАУ- 1 9 8 1 1 , 1 DD-MON-YYYY 1 ) , 2 8 5 0 , NULL , 3 0 ) ; INSERT INTO ЕМР VALUES ( 7 7 8 2 , 1 CLARК 1 , 1 МANAGER 1 1 7839, TO_DATE ( 1 9- JUN- 1 9 8 1 1 , 1 DD-MON-YYYY 1 ) , 2 4 5 0 , NULL , 1 0 ) ; INSERT INTO ЕМР VALUES ( 7 7 8 8 , 1 SCOTT 1 , 1 ANALYST 1 , 7566, TO_DATE ( 1 0 9 -DEC- 1 9 8 2 1 , 1 DD-MON-YYYY 1 ) , 3 0 0 0 , NULL , 2 0 ) ; INSERT INTO ЕМР VALUES ( 7 8 3 9 , 1 KI NG 1 , 1 PRES I DENT 1 , NULL 1 TO_DATE ( 1 1 7 -NOV- 1 98 1 1 , 1 DD-MON-YYYY 1 ) , 5 0 0 0 , NULL , 1 0 ) ; INSERT INTO ЕМР VALUES ( 7 8 4 4 , 1 TURNER 1 , 1 SALESМAN 1 , 7 6 9 8 , TO_DATE ( 1 8 - S E P- 1 9 8 1 1 , 1 DD-MON-YYYY 1 ) , 1 5 0 0 1 о, 30) ; INSERT INTO ЕМР VALUES ( 7 8 7 6 , 1 ADAМS 1 1 1 CLERK 1 , 7788, TO_DATE ( 1 1 2 - JAN- 1 9 8 3 1 , 1 DD-MON-YYYY 1 ) , 1 1 0 0 , NULL , 2 0 ) ; INSERT INTO ЕМР VALUES ( 7 9 0 0 , 1 JAМES 1 , 1 CLERК 1 , 76981 TO_DATE ( 1 3 - DEC- 1 9 8 1 1 , 1 DD-MON-YYYY 1 ) , 9 5 0 , NULL , 3 0 ) ; INSERT INTO ЕМР VALUES ( 7 9 0 2 , 1 FORD 1 , 1 ANALYST 1 , 7566, TO_DATE ( 1 3 - DEC- 1 9 8 1 1 1 1 DD-MON-YYYY 1 ) , 3 0 0 0 , NULL , 2 0 ) ; INSERT INTO ЕМР VALUES ( 7 93 4 , 1 MI LLER 1 , 1 CLERК 1 , 7782 , ТО_DATE ( 1 2 3 -JAN- 1 98 2 1 , 1 DD-MON-YYYY 1 ) , 1 3 0 0 , NULL , 1 0 ) ; CREATE ТАВLЕ DEPT ( DE PTNO NUМBER ( 2 ) , DNAМE VARCНAR2 ( 1 4 ) 1 LOC VARCНAR2 ( 1 3 ) ); INSERT INTO DEPT VALUES INSERT INTO DE PT VALUES INSERT INTO DEPT VALUES INSERT INTO DEPT VALUES ( 10 , (20, ( 30 , (40, 1 ACCOUN T I NG 1 , 1 NEW УОRК 1 ) ; 1 DALLAS 1 ) ; 1 RE S EARCH 1 , 1 SALES 1 , 1 CH I CAG0 1 ) ; 1 0PERAT I ONS 1 , 1 BOSTON 1 ) ; 28 Настро й ка среды Если вы создал и схе му посредством показа н н ы х выше команд, не забудьте вы­ пол н ить команды создания огран ичен и й предыдущего раздела. Н а с т р ойка с р ед ы Бол ь ш и н ство при меров в этой кн и ге предназначено лля вы пол н е н ия полностью в среде S Q L* Pius. П оэтому настрой ку и конфигурирование требует тол ько SQL* Pius. Одн а ко у меня есть совет относител ьно применения S Q L* Pius. П очти во всех при­ мерах тем ил и иным образом испол ьзуется пакет D B M S _OUT P U T . Чтобы можно было работать с D B M S_OUT P U T , потребуется выдать следующую команду SQ L* Pius: SQL> s e t s e rveroutput on Ч асты й ввод этой команды довольно быстро становится утом ител ьн ы м . К счас­ тью, S Q L* Pi us позволяет создать файл l o g i n . s q l - с ценар и й , которы й вы полняет­ ся при каждом запус ке S Q L* Pius. Более того, можно определ ить переменную среды S Q L PAT H , что позволит н аходить этот сценар и й н езависимо от того, в каком катало­ ге он хра н ится . Для всех примеров в этой к н и ги применяется такой сценари й l o g i n . s q l : de flne edito r=vl s e t s e rve routput on S l ze unl lmlted set t r lmspool on set l ong 5 0 0 0 s e t l i ne s l ze 1 0 0 s e t page s l z e 9 9 9 9 c o l umn plan_p l u s_exp f o rmat а 8 0 s e t sqlprompt ' &_us e r . @ &_connect_identi f i e r . > ' Н иже при веде н а ан нотирован н ая версия этого сценари я. 1 . de f i ne _e d i t o r =v i . Определяет те кстовый редактор, который SQ L* Pius будет испол ьзовать по умолчан и ю . М ожете указать л юбой предпоч итае м ы й те ксто­ в ы й редактор ( не текстовый процессор) , такой как Notepad ил и ema c s . 2 . s e t s e rve r o u t p u t o n s i z e u n l imi t e d. П о умолчан и ю вкл ючает пакет DBMS O U T P U T (следовател ьно, вводить кажд ы й раз команду s e t s e r v e r o u t p u t on не придется ) . Также устанавл и вает ста ндартн ы й размер буфера в максимально возможное значе н и е . 3 . s e t t r i ms p o o l o n . П р и буферизац и и текста строки будут усе каться с отбра­ с ы ванием пробелов, поэтому о н и н е будут и м еть ф и кс и рован ную лл и н у. Есл и параметр t r i ms p o o l установлен в o f f ( п о умолчан и ю ) , ш ир и на буфери зован­ н ых строк будет равн а знач е н и ю п араметра l i n e s i z e . 4. s e t l o n g 5 0 0 0 . Устанавл и вает стандартное количество байтов, отображаем ы х при выборе столбцов LONG и C L O B . 5. s e t l i n e s i z e 1 0 0 . Устанавл и вает ш ир и н у строк, отображаем ых SQL* Pius, в 1 00 с и м волов. 6 . s e t p a g e s i z e 9 9 9 9 . Устан а вл и вает параметр p a g e s i z e , которы й управляет тем , наскол ь ко часто SQ L* Pius в ыводит заголовки , в бол ьшое значение ( м ы будем получать оди н н абор заголовков на стра н и цу). Настрой к а среды 29 7. column plan_plus _ехр format а В О . Устанаминает стандартную ширину стро­ ки в выводе плана вы полнения , получаемого с помощью AUTOTRAC E . В об­ щем случае значения а В О вполне достаточно для отображен ия полного плана. Последний фрагмент сценария l og i n . sql настраивает приглашение на ввод ко­ манд SQL* Plus: set sqlprompt ' &_u s e r . @ &_conne ct_ident i f i e r . > ' В результате приглашение и нтерфейса приобретает следующий вид, которы й позволяет видеть имя пользователя и идентификатор подключения : EODA@ORA12CR1> Н астройка средства AUTOTRACE в SQL*Pius AUTOTRAC E это средство SQL* Plus, которое выводит план выполнения за­ пущенных запросов и сведения об испол ьзован н ы х и м и ресурсах. В этой книге AUTOTRACE применяется очен ь часто. Существует несколько способов конфи гу­ рирования этого средства. - Начальная установка Средство AUTOTRACE полагается на доступность таблицы по имени PLAN_ТАВLЕ. Начиная с версии O racle l Og, схема S Y S содержит глобал ьную времен ную табли ­ цу под названием PLAN_TABLE $ . Все необходимые привилегии для работы с этой таблицей выданы пользователю PUBL I C и определен открытый синоним (с именем PLAN_TABLE, которы й указы вает на S Y S . PLAN_TABLE$ ) . Это значит, что получать доступ к этой табли це может любой пользователь. На заметку! Если вы имеете дело с очень старой версией O racle, можете создать таблицу PLAN _ТАВLЕ вручную, выполнив сценарий $0RACLE_НОМЕ / rc!Ьms / admin/ut lxplan . sql. Вы должн ы также создать и назначить роль PLUSTRACE : • введите команду c d $ 0RACLE_HOME / s ql p l u s / admin; • войдите в SQL*Plus от имени SYS или пользователя , которому выданы привилегии SYS DBA; • введите команду @ p l u s t rce; • введите команду GRANT PLUSTRACE ТО PUBL I C ; . При желани и можете заменить PUBL I C в команде GRANT другим именем пользо­ вателя . Управление отчетом Отчет о пути выполнения, которы й используется опти м изатором SQL, и ста­ тистику по выполнению операторов можно получать автоматически . Отчет генери­ руется после успешного вы полнения операторов SQL D M L (т.е, S E L E C T , D E L E T E , U P DAT E, MERGE и I N S ERT ) . Он полезен для отслеживания и настройки производи ­ тельности перечисленных операторов. 30 Настрой ка среды Отчетом можно управлять посредством н астрой ки системной переменной AUTOT RACE. • S ET AUTO T RACE O F F . Отчет AUTOTRAC E не генерируется . Это принято по умолчан ию. • SET AUTOTRACE ON EX P LA I N . Отчет AUTOTRAC E будет отображать только путь выполнения , применяемый оптимизатором. • SET AUTOTRACE ON S TAT I ST ICCS. Отчет AUTOTRACE будет отображать толь­ ко статистику по выполнен и ю SQL-операторов. • SET AUTOTRAC E ON. Отчет AUTOTRAC E будет содержать путь выполнения, используемый оптимизатором, и статистику по выполнению SQL-операторов. • SET AUTOTRACE T RACEONLY. П охоже на SET AUTOTRACE ON, но подавляет вы­ вод запроса пользователя , есл и он есть. • S ET AUTOT RACE T RACEONLY EXPLA I N : П охоже на S E T AUTOTRACE ON , но по­ давляет вы вод запроса пользователя (есл и он есть) и также статистику по вы­ полнению. Н астрой ка пакета Statspack Пакет Statspack должен устанавливаться при подключении к базе данн ых от име­ ни пол ьзователя SYS ( CONNECT 1 AS S Y S DBA ) или пол ьзователя, которому выданы привилегни S Y S DBA. Во многих средах установка Statspack будет задачей, требующей участия адми н истратора базы данн ых или системного адми н истратора. Установка Statspack не представляет сложности. Вы просто запускаете сценарий @ s p c r e a t e . s q l . Он находится в каталоге $ 0RACLE_HOME / rdbms / a dmin и должен выпол няться после подключения от имени SYS через SQL* Pius. Перед запуском сценария s p c r e a t e . s q l необходимо знать следующие три единицы информации : • пароль, которы й вы хотите применять для создаваемой схемы PERFSTAT ; • стандартное табличное пространство для схемы PERFSTAT ; • временное табличное пространство, которое вы хотите использовать для схемы PERFSTAT. Выполнение этого сценария дает примерно такой вывод: $ sqlplus 1 as sysdЬa SQL * Plus : Re lease 1 2 . 1 . 0 . 1 . 0 Production on Fri Мау 23 1 5 : 4 5 : 0 5 2 0 1 4 Copyright ( с ) 1 9 8 2 , 2 0 1 3 , Oracle . Al l rights reserved . Connected to : Oracle Database 1 2 с Enterpri s e Edi tion Release 1 2 . 1 . 0 . 1 . 0 - 64bit Production With the Pa r t i t ioning , OLAP , Advanced Ana lytics and Real Appl icat ion T e s t i ng opt i ons SYS @ ORA1 2 CR 1 > @ spcreate Choose the PERFSTAT user ' s pas sword Not speci fying а pas sword w i l l result i n the instal lation FAI LI NG Enter va lue for perfstat_pa s sword : Н астрой к а среды 31 Выберите параль для пользова теля PERFS TAT Не указание пароля приведет к неуда чному завершению уста новки Введите зна чение для perfs ta t_pa ssword : . . . < дл я кра т кости осталь ной вы в од не показан> . . . Во время выполнения сценарий запросит необходимую и нформацию . В слу­ чае опечатки ил и случай ного прекраще н ия установки перед попыткой установить Statspack повторно вы должн ы с помощью сценария spdrop . s q l , находящегося в $0RACLE НОМЕ / rdbms 1admin, удалить пользователя и установленные представле­ ния . Процесс установки Statspack создаст файл spcpkg . l i s . Его необходимо про­ смотреть на предмет выяснения любых ошибок, которые могл и произойти . Однако пользователь, представления и код PL/SQL должны установиться без каких-либо проблем при услови и, что вы указали допустимые имена табличных пространств (и пользователь PERFSTAT пока еще не существует) . _ Совет. Документация по Statspack находится в текстовом файле $ 0RACLE _ НОМ Е / r dbms 1 admi n / spdoc . txt. Специальные сценарии В этом разделе будут описаны требования (есл и есть) со стороны разнообразных сценариев, применяемых в кни ге. Кроме того, мы исследуем их код. Runstats Ruпstats - это инструмент, который я разработал для сравнения двух разных ме­ тодов выполнения того же действия и выбора лучшего из н их. Вы передаете инстру­ менту Runstats два метода, а он делает все остальное. Runstats производит следую­ щие три ключевых измерения . • Время в формате часов, минут и секунд или пройденное время. Эту и нформа­ цию полезно знать, но она не я вляется самой важной. • Статистика системы. Отображает рядом данн ые о том, сколько раз каждый из подходов делал что-либо (например, обращался к синтаксическому анализато­ ру) , и разницу между ними. • Сведения о защелкивании. Это основная часть отчета. Как будет показано в кн и ге , защелка представляет собой легковесную блоки­ ровку. Блокировки - это механизмы сериализации , подавляющие параллел изм . Приложения , которые подавляют паралл елизм , являются менее масштабируемыми, могут поддерживать меньшее число пользователей и требуют больш и й объем ресур­ сов. Наша цель всегда заключается в построен и и приложений, обладающих потен­ циалом масштабирования - приложе н ий, которые могут обслуживать как одн ого, так и 1 000 или 1 0 000 пол ьзователе й . Чем меньше происходит защелкивани я , тем лучше. Я могу выбрать подход, которы й приводит к увеличению времени выполне­ ния , но снижает кол ичество защелок до 1 0% по отношению к другому подходу. М не известно, что подход, использующий меньше защелок, будет масштабироваться зна­ чительно лучше, чем подход с более высоким числом защелок. 32 Настрой ка среды Утилиту Runstats луч ше всего применять в изоляции , т.е. в однопользовательской базе данных. М ы будем измерять статистические показатели и активность по за­ щелкивани ю (блоки рован ию) данных, которые присуши анализируемым nодходам. Мы не хотим , чтобы во время этих измерений другие сеансы вносили свой вклад в загрузку системы или защелки вание. Для проведения тестов подобного рода удоб­ но иметь небольшую тестовую базу данных. Например, я часто использую свой на­ стольный П К или ноутбук. На заметку! Я уверен, что все разработчики должны располагать полностью контролируемой испытательной базой данных, в которой они смогут п роверять свои идеи, не обращаясь постоянно за помощью к администратору базы данных. Разработчики определенно долж­ ны иметь такую базу данных на своих настольных ПК, даже если лицензия в переанальной версии для разработчика предполагает просто " п ри менение ее для разработки и тести ­ рования, но не для развертывания" . В этом случае нечего терять! Кроме того, я проводил несколько неформальных опросов на конференциях и семинарах. Практически каждый администратор баз дан н ых начинал свою деятельность как разработч ик! Опыт и обуче­ ние, которое разработчики могут получить при наличии собственной базы данных - имея возможность видеть, как она в действительности работает - в долгосрочной перспективе сулит значительные преимущества. Чтобы использовать Runstats, понадобится настроить доступ к нескольким пред­ ставлениям V$ , создать табли цу для хранения статистики и создать пакет Runstats. П отребуется достуn к четырем табли цам V$ (динамическим табли цам производи­ тельности) : V $ S TATNAМE, V$MYSTAT , V $ T IMER и V$ LATCH. Вот представление, с ко­ торым я работаю: create or replace view stats as se lect 1 STAT . . . 1 1 1 a . narne nате , b . val ue from v$ statname а , v$mystat Ь whe re a . stati s t i c # = b . s tat i s ti c# union a l l se l e ct 1 LATCH . 1 1 1 name , gets from v $ l at ch union a l l s e lect 1 STAT . . . El apsed T ime 1 , hsecs from v$ t ime r ; На заметку! Действительными и менами объектов, к которым должен быть предоставлен до­ ступ , являются V_$ STATNAМE , V_$MYSTAT и т.д. - имена объектов начинаются с V_$ , а не V $ . Имя V$ - это синон и м , который указывает на представление с именем , начинаю­ щимся с v_ $. Таким образом, V $ S TATNAМE - синон и м , указывающий на представление v_ $ STATNAМE. У вас должен быть открыт доступ к этому представлению. Вы можете и меть привилеги ю S ELECT на V$ S TAT NAМ E , V$MYS TAT и V$ LATCH, выданную непосредственно вам, так что у вас будет возможность создать nредстав­ ление самостоятельно. Кроме того, кто-то друго й , располагающий при вилеrией SELECT на этих объектах, может создать представление и затем вьщать вам привиле­ гию S ELECT на нем. Осталось создать небольшую табл ицу для сбора статистики: create gl obal temporary taЬle run s tats ( runid varchar2 ( 1 5 ) , name va rchar2 ( 8 0 ) , val ue int ) on commit preserve rows ; - Н астрой ка среды 33 Наконец, необходимо создать сам пакет для Runstats. Он содержит три простых АРI-вызова: • RS _START (запуск Runstats) - процедура, которая должна вызываться в начале теста Runstats; • RS _MI DDLE • RS_ STOP - процедура, которая завершает выполнение и выводит отчет. - процедура, которая должна вызываться в середине теста; Спецификация этого пакета выглядит следующим образом: EODA@ORA1 2CR1> create or rep1ace package runstat s_pkg 2 as 3 procedure r s_star t ; 4 procedure rs_rni dd1 e ; 5 procedure rs_st op ( p_di fference threshold i n nurnЬer de fault О ) ; б end; 7 1 Package created . Пакет создан . Параметр р_di f fe rence t h r e s h o l d служит для управления объемом выводи­ мых в конце данных. П акет Runstats собирает статистические сведен ия и информа­ цию о защелках для каждого запуска, после чего выводит отчет о количестве исполь­ зуемых каждым тестом (каждым подходом) ресурсов и разн и це между н и м и . Этот входной параметр можно применять для вывода только тех статистических сведений и информации о защелках, которые отличаются больше, чем на это число. По умол­ чанию значение p_di f ference_t h r e s h o l d равно нулю, поэтому отображаются все результаты . Теперь рассмотрим тело пакета, процедуру за процедурой . П акет начинается с объявления ряда глобальных переменных. Они будут использоваться для хранения времени выполнения каждого теста: EODA@ORA12CR1> create or replace package body runstats_p kg 2 as 3 4 g_ start nurnЬer ; 5 g_ run 1 nurnЬe r ; б g_ run2 nurnЬe r ; 7 Затем следует процедура RS _START. Она просто очищает табл и цу со статистичес­ кими данными и заполняет ее статистическими сведен ия "до запуска" и информа­ цией о количестве защелок. После этого она захватывает текущее значение таймера, которое можно применять для вычисления пройден ного времени с точностью до сотых долей секунды : 8 procedure rs _start 9 is 1 0 begin 11 delete frorn run_stat s ; 12 13 insert into run stats select ' be fore ' , stats . * frorn s t at s ; 14 34 Нас т рой к а среды 15 16 g_s tart : = dbms_ut i l i t y . get_cpu t ime ; 1 7 end; 18 Следующая процедура - R S M I DDLE. Она помещает в переменную G RUN l зна­ чение времени, затраченного на выполнение первого теста. Затем она вставляет те­ кущий набор статистических данных и и нформацию о количестве защелок. Если вы­ честь эти значения из значений, которые ранее были сохранены во время выполнения процедуры RS_ sт ART, можно выяснить количество защелок, задействованных первым методом, количество использованных курсоров (статистически й показатель) и т.д. И , наконец, процедура записывает время начала следующего теста: 19 20 21 22 23 24 25 26 27 28 29 procedure rs middle is begin g_runl : = ( dbms_ut i l ity . get_cpu_t ime-g_start ) ; ins e rt i nto run s t a t s s e l ect ' after 1 ' , stat s . * from stats ; g_s tart : = dЬms_u t i l i t y . get_cpu_t ime ; end; П оследней процедурой в этом пакете является RS _STOP. Ее задача состоит в вы­ воде совокупного времени процессара для каждого запуска, а также разницы между статистически м и показателям и по каждому из двух запусков (выводятся только те, что превышают пороговое значение): 3 0 procedure r s_s top ( p_di fference_thres hold i n numЬer default 0 ) 31 is 3 2 begin 33 g_run2 : = ( dbms_uti l i t y . get_cpu_t ime - g_s tart ) ; 34 dЬms_output . put_l ine ( ' Runl ran i n ' 1 1 g_runl 1 1 ' cpu hsecs ' ) ; 35 36 dЬms _output . put_l ine ( ' Run2 ran i n ' 1 1 g_run2 1 1 ' cpu hsecs ' ) ; 37 38 i f ( g_run2 <> О ) 39 then 40 dЬms_output . put_l ine 41 ( ' run 1 ran i n ' 1 1 round ( g_run l / g_run2 * 1 0 0 , 2 ) 1 1 42 ' % o f the t ime ' ) ; 43 e nd i f ; 44 dbms_output . put_l ine ( chr ( 9 ) ) ; 45 46 ins e rt i nto run stats 47 s e l ect ' a fter 2 ' , stats . * from s ta t s ; 48 49 dЬms_output . put_l ine ( rpad ( ' Name ' , 3 0 ) 1 1 lpad ( ' Runl ' , 1 6 ) 1 1 50 51 lpad ( ' Run2 ' , 1 6 ) 1 1 lpad ( ' Di f f ' , 1 6 ) ) ; 52 Настро й к а среды 35 for х i n 53 54 ( se1ect rpad ( a . name , 3 0 ) 1 1 to_char ( b . va1ue -a . va 1 ue , ' 9 9 9 , 9 9 9 , 9 9 9 , 9 9 9 ' ) 1 1 55 to_cha r ( c . va1ue -b . va 1 ue , ' 9 9 9 , 9 9 9 , 9 9 9 , 9 9 9 ' ) 1 1 56 to_cha r ( ( ( c . va1ue-b . va 1 ue ) - ( b . va 1ue- a . va 1 ue ) ) , 57 ' 9 9 9 , 9 9 9 , 9 9 9 , 9 9 9 ' ) data 58 from run_stats а , run_s tats Ь , run s t a t s с 59 60 whe re a . name = b . name and b . name = c . name 61 and a . runid = ' be fore ' 62 63 a n d b . runid = ' after 1 ' a n d c . runid = ' after 2 ' 64 65 and abs ( ( c . va 1 ue-b . va 1 ue ) - ( b . va1 ue-a . va 1ue ) ) 66 67 > p_d i f ference_thresho1d order Ьу abs ( ( c . va1ue - b . va1ue ) - ( b . va1ue- a . va 1 ue ) ) 68 1оор 69 70 dЬms_output . put_1ine ( x . data ) ; 71 end 1оор ; 72 73 dЬms output . put_1ine ( chr ( 9 ) ) ; 74 dЬms_output . put_1 ine ( ' Run 1 1atches tota1 ver s u s runs - - di fference and pct ' ) ; 75 76 dЬms_output . put_1ine 77 ( 1pad ( ' Run1 ' , 1 4 ) 1 1 1pad ( ' Run2 ' , 1 9 ) 1 1 1pad ( ' Di ff ' , 1 8 ) 1 1 1pad ( ' Pct ' , 1 1 ) ) ; 78 79 for х i n 80 ( s e 1ect to_char ( run 1 , ' 9 , 9 9 9 , 9 9 9 , 9 9 9 , 9 9 9 ' ) 1 1 81 to_char ( run2 , ' 9 , 9 9 9 , 9 9 9 , 9 9 9 , 9 9 9 ' ) 1 1 82 to_cha r ( di f f , ' 9 , 9 9 9 , 9 99 , 9 9 9 , 9 9 9 ' ) 1 1 83 to_char ( round ( run 1 /decode ( run2 , О , to_numЬe r ( O ) , run2 ) * 1 0 0 , 2 ) , 84 ' 9 9 , 9 9 9 . 9 9 ' ) 1 1 ' % ' data from ( se1ect sum ( b . va1ue - a . va1ue ) run 1 , sum ( c . va1ue-b . va1ue ) run2 , 85 sum ( ( c . va 1 ue-b . va 1 ue ) - ( b . va 1 ue-a . va 1 ue ) ) di f f 86 from run_stats а , run_s tats Ь , r u n s t a t s с 87 where a . name = b . name 88 and b . name = c . name 89 a n d a . runid = ' be fore ' 90 and b . runid = ' after 1 ' 91 and c . runid = ' after 2 ' 92 and a . name 1 i ke ' LATCH% ' 93 94 1оор 95 96 dЬms_output . put_1ine ( x . data ) ; 97 end 1оор ; 9 8 end ; 99 1 0 0 end ; 101 1 Package body created . Тело пакета создано . 36 Настрой ка среды Итак, все готово ДJIЯ применеимя Runstats. В качестве примера мы покажем, как использовать Runstats, чтобы выяснить, какой метод эффективнее: одна групповая операция I N S ERT или построчная обработка. Начнем с определения двух таблиц, в которые будут вставляться 1 000 000 строк (сценарий создания табли цы B I G_TABLE представлен далее в этом разделе): EODA@ ORA 1 2 CR 1 > create taЬle t 1 2 as 3 select * from big_ taЬle 4 whe re 1 = 0 ; ТаЬlе created . Та блица создана . EODA@ ORA1 2 CR 1 > create taЬl e t 2 2 as 3 select * from big_ taЬle 4 whe re 1=0 ; ТаЬlе created . Таблица создана . Теперь выполним первый метод вставки записей, предусматривающий применен ие одного SQL-oпepaтopa. Начнем с вызова процедуры RUNSTATS_PKG . RS_START : EODA@ ORA12CR1> ехес runstats_pkg . rs_start ; PL/ SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно завершена . EODA@ORA 1 2 CR1> insert into t 1 2 select * from b i g_taЬl e 3 4 where rownum <= 1 0 0 0 0 0 0 ; 1 0 0 0 0 0 0 rows created . 1 00 0 0 0 0 ст,рок создано . EODA@ ORA12CR1> commi t ; Commi t complete . Фиксация завершена . Затем можно выполнить второй метод - построчную вставку дан ных: EODA@ORA 1 2 CR 1 > ехес runstats_pkg . rs_mi ddl e ; PL/ SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно завершена . EODA@ ORA 12CR 1> begin for х in ( select * 2 3 from big_ taЬle 4 where rownum <= 1 0 0 0 0 0 0 5 loop б insert into t2 va lues Х ; 7 end loop ; в commit ; 9 end ; 10 1 PL/ SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно завершена . Настрой к а среды 37 И, наконец, сгенерируем отчет: EODA@ORA1 2 CR1> ехес runstats_p kg . rs_s top ( 1 0 0 0 0 0 0 ) Run 1 ran in 1 1 9 cpu hsecs Run2 ran in 3 3 7 6 cpu hsecs run 1 ran in 3 . 5 2 % o f the time Run 1 Run2 Di f f Name 29 1 , 000, 032 1 , 000 , 003 STAT . . . execute count 29 1 , 000, 035 1, 000, 006 STAT . . . opened cu rsors cumulati 582 1 , 001 , 466 LATCH . shared pool 1 , 000, 884 14 8 , 818 1, 158, 009 STAT . . . s e s s ion logical reads 1 , 009, 191 183 1, 010, 218 STAT . . . recursive cal l s 1 , 010, 035 95, 964 2 , 074 , 283 STAT . . db Ьlock changes 1 , 97 8 , 3 1 9 443, 882 5 , 4 62 , 3 5 6 5, 018, 474 LATCH . cache buffers chains 3 , 62 0 , 4 0 0 6 7 , 93 8 , 4 9 6 STAT . . . undo change ve ctor s i z e 64 , 3 1 8 , 096 109, 051, 904 176, 160, 768 STAT . . . KT FB alloc space ( Ьlock 67 , 1 0 8 , 8 6 4 1 0 5 , 698 , 5 4 0 384 , 7 1 7 , 388 STAT . . . redo s i ze 279, 018 , 848 STAT . . . logical read byte s f rom 1 , 1 1 4 , 2 5 1 , 2 64 9 , 3 0 0 , 8 0 3 , 5 8 4 8 , 1 8 6 , 5 52 , 3 2 0 . Run 1 latches total ve rsus runs - - di f f e rence and pct Run2 Di f f Pct Run 1 555, 593 6, 795, 317 6, 239, 724 8 . 18% PL/SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно завершена . Отчет подтверждает, что пакет RUNS TAT S_PKG установлен , и показывает, поче­ му при разработке приложений вы должн ы использовать одиночный оператор SQL вместо порции процедурного кода везде, где только возможно. Mystat Сценарий mys t a t . s ql и сопровождающий его mys t at 2 . s q l применяются для того, чтобы показать, как изменяются некоторые " статистические п оказатели " Oracle до и после выпол нение определенной операции. Сценарий mys t a t . s q l со­ бирает начальные значения показателей : set echo o f f set ve ri fy o f f column value new va l V de fine S= " & 1 " set autotrace o f f select a . name , b . value from v$ statname а , v$mystat Ь whe re a . stati stic# = b . stat i s t i c # and lower ( a . name ) = lower ( ' &S ' ) 1 set echo on Сценарий mys t a t 2 . s q l отображает разницу ( &V заполняется в результате запус­ ка сценария mys t a t . s q l - он использует для этого средство NEW_VAL из SQL* Pius, которое содержит последнее значение VALU E , выбранное из п редшествующего за­ проса): 38 Настрой ка среды set echo o f f s e t ve ri fy o f f se lect a . name , b . val ue V , to_cha r ( b . value- &V, ' 9 9 9 , 9 9 9 , 9 9 9 , 9 9 9 ' ) di f f f rom v$statname а , v$mys tat Ь whe re a . statistic# = b . s tati s ti c # a nd lowe r ( a . name ) = lowe r ( ' &S ' ) 1 set echo on Н апример, чтобы посмотреть, сколько информаци и redo сгенерировано оператором U P DATE , можно поступить следующим образом: EODA@ORA 1 2 CR1 > @mys tat " redo s i z e " EODA@ORA 1 2 CR1 > s e t e cho o f f NАМЕ VALUE 4 9 1 1 6 7 8 92 redo s i ze EODA@ORA 1 2 CR1 > update big_taЬl e set owner = l owe r ( owne r ) 2 where rownum < = 1 0 0 0 ; 1 0 0 0 rows updated . 1 00 0 строк обновлено . EODA@ORA 12CR 1> @mystat2 EODA@ORA12CR1> set echo o f f NАМЕ redo s i ze V DI FF 4 91265640 97, 748 Здесь видно, что оператор U P DAT E дл я 1 000 строк сгенерировал 9 7 748 байтов данных redo. SHOW S PACE Процедура S HOW_ s РАСЕ выводит подробную информаци ю об утилизации про­ странства для сегментов базы данных. Ее интерфейс выглядит так: EODA@ORA 12CR 1> des c show_space PROCEDURE s how_space Т ур е Argument Name ------р S EGNAМE VARCНAR2 р OWNER VARCНAR2 р ТУРЕ VARCНAR2 р PART I T I ON VARCНAR2 ---- --- ---- --- --- - ---- --- - --- -- De fau1 t ? I n /Out ----- -- -- ---IN DE FAULT IN DE FAULT IN IN DEFAULT - - - Н иже описаны аргументы этой процедуры. • • Р SEGNAМE. И мя сегмента - например, имя таблицы или индекса. _ Р OWNER. По умолчанию принимается текущий пользователь, но эту процеду­ _ РУ можно применять для просмотра какой-то другой схемы . • Р Т У Р Е П о умолчани ю этот аргумент принимает значение TABLE и представ­ ляет тип просматриваемого объекта. Например, оператор s e l e ct di s t i n c t segment type from dЬ а segments выводит список допустимых типов сегментов. _ . _ _ Настрой к а сред ы • 39 Р PART I T I ON. И мя секции при просмотре пространства для секционирован­ ного объекта. П роцедура s нow_ s РАСЕ одновременно может отображать про­ странство только для одной секции . Когда сегмент хранится в табличном пространстве ASS M , вывод из этой процедуры выглядит следующим образом: EODA@ORA12CR1> ехес s how_space ( ' B I G_TAВLE ' ) ; о Unformatted Blocks . . . . . . . . . . . . . . . . . . . . . FS 1 Blocks ( 0 -2 5 ) . . . . . . . . . . . . . . . . . . . . . о FS2 Blocks ( 2 5 - 5 0 ) . . . . . . . . . . . . . . . . . . . . . о о FS 3 Blocks ( 5 0 - 7 5 ) . . . . . . . . . . . . . . . . . . . . . о FS 4 Blocks ( 7 5 - 1 0 0 ) . . . . . . . . . . . . . . . . . . . . . 14, 469 Ful l Blocks 15, 360 Total Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . Total Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125, 829, 120 Total MBytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 Unused Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . 728 5, 963 , 776 Unused Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Last Used Ext F il e id . . . . . . . . . . . . . . . . . . . . Last Used Ext Blockid . . . . . . . . . . . . . . . . . . . 43, 145 Last Used B1ock . . . . . . . . . . . . . . . . . . . . . . . . . 296 PL/SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно завершена . Н иже при ведены пояснения элементов вывода. • Unformatted Bl ocks ( Неформатированных блоков) . Количество блоков, кото­ рые выделены для таблицы и хранятся ниже маркера максимального уровня за­ полнения (high-water mark - HWM ) , но не используются . Сумма неформатиро­ ванных и неиспользуемых блоков равна общему количеству блоков, вьщеленных для таблицы , но не применяемых для хранения данных в объекте ASS M . • FS l B l ocks - FS 4 В l ocks ( Блоков FS I - Блоков FS4). Количество формати­ рованных блоков с данными. Диапазоны , указанные после их названи й , пред­ ставляют степень пустоты каждого блока. Например, диапазон (0-25) пред­ ставляет количество блоков, пустых на 0-25% . • Fu l l Bl o ck s ( Полн ых блоков) . Количество блоков, заполненных настолько, что они больше не являются кандидатами для выполнения последующих вста­ вок данных. • T ot a l B l o c k s (Всего блоков), T ot a l B yt e s ( Всего байтов), T o t a l Mbyt e s (Всего Мбайт) . Общий объем пространства, которое выделено сегменту, изме­ ренное в блоках базы данных, байтах и мегабайтах. • Unu s e d B l o c ks ( Неиспользуемых блоков) , Unu s e d B yt e s ( Неиспользуемых байтов) . Эти значен ия представляют объем дискового пространства, которое никогда не использовалось. Эти блоки выделены для сегмента, но в настоящее время хранятся выше НWМ -маркера сегмента. • La s t U s e d Ext Fi l e i d ( Идентификатор файла последнего использован ного экстента). Идентификатор файла, который содержит последни й экстент с дан­ ными . 40 Настройка среды • La s t U s e d Ext B l o c k i d ( Идентификатор блока последнего использованного экстента). Идентификатор блока начала последнего экстента; идентификатор блока внугри последнего использованного файла. • L a s t U se d B l o c k (Последн ий использованн ы й блок). Смещение идентифика­ тора последнего блока, использованного в последнем экстенте. Когда процедура SHOW_S PACE применяется для просмотра объектов в табличных пространствах с ручным управлением пространством сегментов, вывод напоминает показанн ы й далее: EODA@ORA12CR1> ехес show_space ( ' B I G_TAВLE ' Free B1ocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Tota1 B1ocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147, 456 Tota1 Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 , 2 0 7 , 959, 552 Tota1 МВуtеs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 , 152 Unused B1ocks . . . . . . . . . . . . . . . . . . . . . . . . . . . 1, 616 Unused Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . 13, 238, 272 La s t Used Ext Fi 1 e i d . . . . . . . . . . . . . . . . . . . . 7 La s t Used Ext B1ock!d . . . . . . . . . . . . . . . . . . . 139, 273 La s t Used B1ock . . . . . . . . . . . . . . . . . . . . . . . . . 6, 576 . PL/SQL procedure s ucce s s fu 1 1 y comp1eted . Процедура PL/SQL успешно завершена . Еди нствен ное отличие от предыдущего отчета связано с о строкой F r e e B l ocks (Свободных блоков) в начале. Здесь указано количество блоков в первой группе с п исков свободных блоков сегмента. Сценар и й выводит сведен ия только об этой группе списков свободных блоков. Чтобы сценарий мог отображать сведения о не­ скольких группах списков свободных блоков, его понадобится модифицировать. Н иже приведен код с комментариями. Эта утилита представляет собой дополни­ тельны й уровень, действующий поверх АРI -интерфейса овмs _S PACE в базе данных. create o r rep1 ace p rocedure show_space ( p_segname in va rchar2 , i n varcha r2 de faul t use r , р_owne r р _type i n varchar2 de fau1 t ' ТАВLЕ ' , p_pa rtit ion in va rcha r2 de fau1t N ULL ) -- Данная nроцедура исполь зует идентификатор authid текущего поль зователя , поэтому она може т запрашивать представления DBA_* с использованием -- привилегий из ROLE и допускает однократную установку для всей базы даннь� , - - а не для каждого поль зовател я , который желает ее применять . authid current user as 1 f ree Ьl ks 1 tota1 Ьlocks 1_tota1_bytes 1 unused Ьlocks 1_unused_bytes 1 LastUsedExt Fi 1 e i d 1 LastUsedExtB1ockid 1 LAST USED BLOCK 1_segment_space_mgmt 1 unformatted Ьlocks 1_un forma tted_bytes numЬe r ; numЬe r ; numЬe r ; numЬe r ; numЬe r ; numЬer ; numЬe r ; numЬe r ; varchar2 ( 2 5 5 ) ; numЬe r ; numЬe r ; Настрой к а среды 41 1 fs 1 Ьlocks nurnЬe r ; 1 f s 1 _bytes nurnЬe r ; 1 f s 2 Ьlocks nurnЬe r ; 1_fs 2_bytes nurnЬe r ; 1 fs З Ь l o c ks nurnЬe r ; 1_fs 3_bytes numЬe r ; 1 fs 4 Ьlocks nurnЬe r ; 1_f s 4_byte s nurnЬe r ; 1_fu1 1_Ьlocks nurnЬe r ; 1_fu1 1_bytes nurnЬe r ; - - Встроенная процедура для вывода аккуратно - - форматированных чисел с nростыми метками . p rocedure р ( р_1аЬе1 in varcha r 2 , p_num i n nurnЬe r is begin dЬms_output . put_1 ine ( rpad ( p_1abe 1 , 4 0 , ' . ' ) 1 1 to_cha r ( p_num , ' 9 9 9 , 9 9 9 , 9 9 9 , 9 9 9 ' ) ) ; end ; begin - - Этот запрос вьпюлняется динамически , чтобы nозволить данной nроцедуре быть созданной nоль зователем, имеющим достуn к Предста влениям - - DBA_SEGМEN T S / TAВLES PACES посредств ом роли , как обычно принято . -- П РИМЕЧАНИЕ : во время выnолнения вызывающая nроцедура -- ДОЛЖНА иметь доступ к этим двум представлениям ! -- Этот запрос определяе т , я вляется ли данный объект объектом ASSM . begin execute immediate ' s e l ect t s . s egment_space management from dЬa_s egments s e g , dЬa_taЬle spaces t s where s eg . s egment_name = : р s egname and ( : p_pa r t i t i o n is nu1 1 o r s eg . p a r t i t i on_name = : p_pa r t i t i on ) and s e g . owne r = : p_owne r and s e g . taЬl e space_name = t s . taЬlespace_name ' into l_s e gment_space_mgmt u s i ng p_s egname , p_pa r t i t i o n , p_p a r t i ti o n , p_owne r ; exception when too_many_rows then dЬms_outpu t . put_1 ine ( ' Th i s mus t Ье а p a rt i t i oned taЬle , u s e p_p a r t i t i o n = > ' ) ; Эта таблица должна быть секционированной , исполь зуйте р_pa r t i t i on = > return ; e nd ; Если объе кт является табличным пространством AS SM, то для получения информации о пространстве мы должны применять этот АРI - вызов . В противном случае мы исполь зуем АРI -интерфейс FREE BLOCKS для сегментов , упра вляемь� nоль зователем . i f 1_segment_space_mgmt = ' AUTO ' then dЬms_spa ce . space_usage ( p_owne r , p_s egname , p_typ e , l_un f o rmatted_Ьlocks , l_unformatted_byte s , l_f s 1_Ьlocks , 1_fs 1_byt e s , 1 f s 2_Ьl o c ks , l_f s 2_byt e s , l_f s З_Ь l oc k s , l_fs З_byt e s , l_fs 4_Ьlocks , 1_fs 4_bytes , l_ful 1_Ьlocks , 1_fu1 l_bytes , p_pa rtition ) ; р ( ' Un fo rmatted Bl oc ks ' , 1 un formatted Ь l o c ks ) ; р ( ' FS 1 B1ocks ( 0 - 2 5 ) 1 f s 1 Ь l o c ks ) ; 42 Настрой ка среды р ( ' FS 2 B1ocks ( 2 5 - 5 0 ) ' , 1_fs2_Ьlocks ) ; р ( ' FS З B1ocks ( 5 0 - 7 5 ) ' , 1_fs 3_Ьlocks ) ; р ( ' FS 4 B1ocks ( 7 5 - 1 0 0 ) ' , 1_fs 4_Ьlocks ) ; 1 ful l Ьlocks ) ; р ( ' Fu l l B1ocks e1se dЬms_space . free_Ьlocks ( => p_owne r , segrnent_owne r => p_s egname , segment_name => p_type , segrnent_type free 1 i s t_group_id = > О , free Ь l ks => 1_free_Ьl ks ) ; р ( ' Free B1ocks ' , 1 free_Ь l ks ) ; end i f ; -- Затем с помощрю АРI-вызова unused_space извлекается остальная информация . dЬms_space . unused_space ( segrnent_owne r => р_owne r , segment_name => p_s egname , => p_typ e , segment_type part i t ion_name => p_pa r t i t i o n , t o ta 1 Ьlocks => 1_tota1_Ьlocks , tota1_bytes = > 1_tota1_bytes , unused Ьlocks => 1_unused_Ьl ocks , => l_unused_byte s , unused byte s LAST_USED_EXTENT_FI LE_I D = > l_La stUs edExt Fi 1 e i d , LAST_USED_EXTENT_BLOCK_I D => 1_Las tUsedExtB1ockid, LAST USED BLOCK => 1 LAST USED BLOCK ) ; р ( ' Tota1 B1ocks ' , 1_tota l_Ьlocks ) ; р ( ' Total Bytes ' , 1_ total_bytes ) ; р ( ' Total MByte s ' , t runc ( l_total_bytes / 1 0 2 4 / 1 0 2 4 ) ) ; р ( ' Unused B1ocks ' , 1_unused_Ьlocks ) ; р ( ' Unused Bytes ' , 1_unused_bytes ) ; р ( ' La s t Used Ext Fi l e i d ' , 1_La stUs edExt Fi l e i d ) ; р ( ' La s t Used Ext B1ockid ' , l_LastUs edExtB1 ockid ) ; р ( ' La s t Used Block ' , 1 LAST USED BLOCK ) ; end ; 1 BIG ТАВLЕ Во многих примерах этой книги используется табли ца B I G_TABLE. В зависимос­ ти от системы эта таблица может содержать от одной до 4 м иллионов записей, а ее размер варьируется в пределах от 200 Мбайт до 800 Мбайт. Во всех случаях ее струк­ тура остается той же самой . Для создания таблицы B I G_TABLE я написал сценар и й , которы й выпол няет пе­ речисленные ниже действия. • Создает пустую табли цу на основе представлен ия ALL_OBJECT S . Это словар­ ное представление применя ется для заполнения таблицы B I G_ТАВLЕ. • Устанавл ивает для этой таблицы режим NOLOGG I N G . Это не обязательно и было сделано ради производительности. Использовать режим NOLOGG I NG для тестовой таблицы совершенно безопасно. Однако не применяйте его в произ­ водствен ной системе, т. к. тогда будут отключены средства вроде Oracle Data Guard (Защита данных Oracle) . Настро й ка среды 43 • Заполняет табли цу, занося в нее содержимое представления ALL _OBJECTS и затем выполняя на каждой итераци и вставку таблицы в саму себя , что каждый раз увеличивает ее размер примерно вдвое . • Создает на таблице ограничение первичного ключа. • Собирает статистику. Чтобы построить таблицу B I G_TABLE, можете запустить следующий сценарий в командной строке SQL* Pius и передать ему количество строк таблицы в качестве па­ раметра. Сценарий остановится , когда достигнет указанного количества строк. create taЬle big_taЬle as se1 ect rownum id, OWNER , OBJECT_NAМE , SUBOBJECT_NAМE , OBJECT_I D , DATA_OBJECT I D , OBJECT_TY PE , CREATED, LAST DDL_T I МE , Т I МЕSТАМ Р , STATUS , TEMPORARY , GENERATED, SECONDARY , NAМES PACE , E D I T I ON NАМЕ frorn a1 1_obj ects whe re 1=0 1 a1ter taЬle big_taЬle no1ogging ; dec1are 1 cnt nurnЬe r ; 1 rows nurnЬe r : = & numrows ; begin insert / * + append * / into big_taЬle se1ect rownum id, OWNER, OBJECT_NAМE , SUBOBJECT_NAМE , OBJECT_I D , DATA_OBJECT_I D , OBJECT_TY PE , CREATED, LAST_DDL_T I МE , ТIМЕ SТАМР , STATUS , TEMPORARY , GENERATED, SECONDARY , NAМES PACE , E D I T I ON NАМЕ frorn a 11_obj ects whe re rownum <= &numrows ; 1 cnt : = s q1 % rowcount ; cornrnit ; whi1e ( 1 cnt < 1_rows ) 1оор insert / * + APPEND * / into big_taЬle se1ect rownurn+1_cnt , OWNER, OBJECT_NAМE , SUBOBJECT_NAМE , OBJECT_I D , DATA_OBJECT_I D , OBJECT_TYPE , CREATED , LAST_DDL_T IME , T I MESTAМ P , STATUS , TEMPORARY , GENERATED , S ECONDARY , NAМE S PACE , E D I T I ON NАМЕ frorn big_taЬl e а whe re rownum <= 1 rows - 1 cnt ; 1 cnt : = 1 cnt + sq1 % rowcount ; cornrni t ; end 1оор ; end ; - - 1 a1ter taЬle big_taЬle add con s t raint big_taЬle_p k prirnary key ( id ) ; ехес dЬrns_stats . gather_taЬle_stats ( user , ' BIG_TAВLE ' , estirnate_percent=> 1 ) ; 44 Настрой к а среды Я произвел оценку базовой статистики о таблице. Для индекса, ассоциированно­ с го первичным ключом, статистика вычисляется автоматически при его создании. С огла ш ения при написании кода Одно из испол ьзуемых в этой книге соглашен и й при нап исан ии кода касается и менования перемен н ых в коде P L/SQL. Н апример, взгляните на следующее тело пакета: create or replace package body my_pkg as g_va riaЫe va rchar2 ( 2 5 ) ; p rocedure р ( p_va riaЫe in varcha r 2 is l_va riaЫe va rchar2 ( 2 5 ) ; begin nul l ; end ; end ; 1 Зде с ь п р и с утствуют т р и п е р е м е н н ы е : гл о б ал ь н ая п е р е м е н н ая п а кета G _VCAR IAB L E , формальный параметр процедуры Р VAR IABLE и локальная пере­ менная L_VARIABLE. Переменные именуются согласно их области действия . Имена глобальных переменн ых нач и наются с G имена параметров - с Р_, а имена ло­ кальн ых переменных - с 1_. Основная причина такого именования - провести различие между и менами переменных PL/SQ L и именами столбцов в таблице базы данных. Н апример, показанная н иже процедура будет всегда выводить все строки таблицы ЕМР, в которых поле ЕNАМЕ не является пустым : _ _, c r e a t e procedure р ( ЕNАМЕ in varchar2 ) as begin for х i n ( s e l ect * from emp where ename Dbms_output . put_l ine ( x . empno ) ; end loop ; end ; = ЕNАМЕ ) l oop Встретив выражение ename ЕNАМЕ, механизм SQL сравнивает столбец ЕNАМЕ с сам и м собой (разумеется) . М ожно было бы примен ить выражение ename Р . ЕNАМЕ, т.е. уточн ить ссылку на переменную P L/SQ L с помощью имени процедуры, но об этом легко забыть и получить в итоге ошибку. Я просто всегда и меную свои переменные по области действия . В результате я легко могу отличать параметры от локальных и глобальных переменных, а также ус­ траняю любую неоднознач ность в отношении имен столбцов и имен переменных. = = ГЛ А В А 1 Р азр а б от ка ус п е ш ных пр ил ожен и й Oracle о чень много времени я провожу, работая с проrраммным обеспечен ием системы управления базами данных (СУБД) Oracle и , что еще важнее, общаясь с тем и , кто использует это программное обеспечение. В течение последних 2 5 лет или около того мне довелось работать над многим проектами - как успешными, так и совер­ шенно неудачными - и мой опыт можно было бы обобщить следующим образом . • На успех или провал приложения, построенного на основе базы данных - и зависящего от базы данных - оказывает влияние то, как оно использует базу данн ых. Как следствие этого, все приложения построен ы на основе баз дан ­ ных; я н е в состоянии назвать ни одного полезного приложения , которое где­ то не хранило бы дан ные. • Приложения приходят и уходят, однако данные существуют всегда. Речь идет не о построении приложе н и й ; на самом деле речь идет о данн ых, лежащих в основе этих приложений. • Команда разработки нуждается в нескольких разработчи ках, разбирающихся в базах данных, которые будут отвечать за соблюдение логики базы данных и обеспечение работоспособности построенной с истемы с первого дня ее вве­ дения в эксплуатаци ю. Необходимость в проведе н и и подстройки сразу после развертыван ия свидетельствует о том , что система не создавалась в подобной манере. Эти соображения могут казаться совершенно очевидн ы м и , но я убедился , что слишком многие относятся к базе дан ных как к черному ящику - чему-то такому, о чем знать не обязательно. Возможно, они располагают генератором SQL-кoдa, кото­ рый, по их мнению, избавит от бремени изучения языка SQL. Или же они полагают, что будут пользоваться базой данных только как двумерн ы м файлом и выпол нять "чтение по ключам " . Как бы там ни было, я могу утверждать, что в большинстве случаев такая точка зрения ошибочна: без понимания базы данных просто не обой­ тись. В этой главе будет показано, почему требуется знание базы данных, в частнос­ ти , зачем необходимо разбираться в перечисленных ниже вопросах. • Архитектура базы данных: как она работает и что собой представляет. • Что такое средства управления паралл ельной обработкой, и каков в н их смысл . 46 Глава 1 • Как выполнять повседневную настройку своего приложения . • Каким образом в базе данных реализованы некоторые вещи - они не обяза­ тельно реализованы так, как вы могл и подумать. • Каки е функциональные возможности база данных уже предлагает, и почему в общем случае лучше применять предоставленное средство, чем строить собс­ твенное. • П очему может требоваться знан ие языка SQL, выходя щее за рамки общего курса. • Администраторы баз дан ных и разработчи ки находятся в одной команде, а не представляют два враждующих лагеря , которые постоя нно пытаются перехит­ рить друг друга. П оначалу может показаться , что перечень подлежащих изучен ию вопросов бес­ конече н , но прим ите во внимание следующую аналогию: что бы вы сделали в пер­ вую очередь, есл и бы пришлось разрабатывать в высшей степени масштабируемое производствен ное приложение для совершенно новой операционной системы (ОС)? Скорее всего, ваш ответ был бы следующим : "Сначала выяснили бы, как работает эта новая ОС, каким образом в ней будут выполняться приложения , и тому подоб­ ные вопросы " . Если ваш ответ отл ичается , то с бол ьшой вероятностью вы потерпи­ те поражение. Н апример, сравн и м ОС Windows и U N IX/Linux. Если вы я вляетесь опытн ым программистом в Windows, которого попросили разработать новое приложение для платформы U N IX/Linux, то вам придется заново изучить ряд вопросов. Управление памятью реализовано совершенно по-другому. П остроен ие процессов сервера су­ щественно отличается: в среде Windows должен быть разработан еди нственный nро­ цесс - единственный исполняемый модуль с множеством потоков. В среде UN IX/ Linux разработка не сводится к построен и ю одного автономного исполняемого мо­ дуля ; вместо этого приходится иметь дело с множеством совместно работающих процессов. Это верно, что и Windows, и U N IX/Linux я вляются операционными сис­ темам и . Обе они предлагают разработчи кам множество одинаковых служб - управ­ ление файлами , управление памятью, управление процессами , обеспечение безопас­ ности и т. п . Однако они серьезно отличаются по архитектуре, и большая часть того, что вы изуч или в среде Windows, не применимо к U N IX/Linux (и, справедли вости ради , наоборот) . Ч тобы добиться успеха на новой платформе, вы должны забыть все, что знали о старой платформе. То же самое касается и среды базы данных. Все моменты , связанные с прил оже н ия м и , которые выполня ются непосредс­ твенно в среде ОС, относятся также и к приложения м , которые будут выполняться в среде базы дан н ых: необходимо осознавать, что база дан ных является критически важной для успеха приложе н ия . Если вы не понимаете , что делает конкретная база данных и как она это делает, то ваше приложение будет обречено на неудачу. Есл и вы считаете , что раз уж ваше приложение нормально работает в среде S Q L Server, то оно обязательно будет успешно функционировать в среде Oracle, то это прило­ жен и е , скорее всего, потерпит неудачу. Разумеется , корректно также и обратное утверждение: вовсе не обязательно, что масштабируемое, аккуратно разработанное приложение Oracle сможет работать в среде SQL Server без существенных архитек­ турных изменений. П одобно тому, как Windows и U N I X/Linux явля ются операцион- Ра зрабо тка усп е ш н ы х п р ило же н и й O racle 47 ными системами , но фундаментально отличаются друт от друта, Oracle и SQL Server (здесь можно было бы упомянуть практически любую базу дан ных) представляют собой базы данных, существенно отличающиеся в архитектурном плане . Мой п одх од Прежде чем мы приступим, я должен пояснить вам свой подход к разработке . Я предпочитаю подходить к решению проблем , строя решение вокрут базы данн ых. Если какое-то действие может быть выполнено в базе данных, то так и делается. Это обусловлено нескольки м и причинам и . Самая главная из н их заключается в том , что если фун кциональность встроена в базу дан ных, то ее можно развернуть где утодно. М не не известна ни одна популярная и коммерчески успешная серверная операци­ онная система, для которой программное обеспечение Oracle было бы недоступным. Начиная с Windows и заканчи вая десятками систем U N I X/Linux - везде доступно одно и то же программное обеспечение Oracle и те же самые варианты . Мне часто приходится строить и тестировать решения Oracle 1 2с, Oracle l lg или Oracle l Og на портативном компьютере под управлением ОС U N IX/Linux л ибо ОС Windows, ко­ торая выполняется на виртуальной машине. Полученные решения можно затем раз­ вертывать на разнообразных серверах, на которых функционирует одно и то же про­ rраммное обеспечение баз данных, но в средах разных операционных систем. Если же фун кциональное средство приходится реализовать вне базы дан ных, то окажется , что его крайне трудно развертывать везде, где хочется . Одной из основных характе­ ристи к языка Java, которая делает его настолько привлекательн ы м , я вляется ком ­ пиляция программ в одной и той ж е среде виртуальной маши н ы Java (Java Virtual M achine - JVM ) , обеспечивающая высокую степень их переносимости ; именно эта характеристика привлекает меня в базах данных. База данных - это моя виртуаль­ ная машина и это моя операционная система. Итак, я стараюсь все выполнять в базе данных. Если же мои требован ия выходят за рамки того, что может преДII о жить среда базы данных, я строю решение на языке Java вне этой среды . В результате почти все сложности , связанные с операционной системой , остаются скрытым и . Я по-прежнему должен понимать, каким образом ра­ ботают мои " виртуальные машины" (Oracle и временами JVМ ) - ведь всегда нужно знать инструменты , с которым и приходится работать, - но они , в свою очередь, по­ заботятся о том , как лучше выполнять те или иные действия в среде заданной ОС. Таким образом , простое знан ие особенностей работы одной " виртуальной ОС" позволяет строить приложения, которые будут успешно фун кционировать и мас­ штабироваться под управлением многих операционных систем. Я вовсе не утверж­ даю, что можно находиться в полном неведе н и и относительно используемой ОС, но как разработчик программнога обеспечения , строя щий приложен ия баз данных, вы довольно неплохо изолированы от нее и не будете иметь дела с большинством нюансов. Безусловно, адми н истратору базы дан ных, отвечающему за работу про­ rраммного обеспечен ия Oracle, придется намного больше взаимодействовать с ОС (если это не так, то поищите другого администратора) . Если же вы разрабатываете клиент-серверное программное обеспечение, и большая часть кода выпол няется за пределами базы дан ных и вне виртуальной маш и н ы (вероятно, наиболее популяр­ ной виртуальной машиной я вляется JVM ) , то придется снова обращать внимание на ОС. Глава 1 48 При разработке программ нога обеспечения базы данных я придержи ваюсь до­ статочно простой философии , которая оставалась неизменной на протяжении мно­ гих лет. • Все, что тол ько возможно, должно делаться в одном операторе SQL. Верите или нет, но это возможно почти всегда. С течением времени это утверждение становится еще более справедливым. SQL - исключительно мощный язык. • Если что-то нельзя выпол нить в одном операторе SQL, то это необходимо реализовать на языке P L/SQ L с помощью как можно более краткого кода. Следуйте при нципу "больше кода больше ошибок, меньше кода меньше ошибок" . = = • Если задачу нел ьзя реш ить средствами P L/SQL, попробуйте воспользоваться хранимой процедурой Java. Однако после выхода Oracle9i и последующих вер­ с и й потребность в этом возни кает очень редко. PL/SQL является полноцен­ ным и популярным языком третьего поколения (third-generation programming language - ЗGL). • Если задачу не удается решить на языке Java, попробуйте написать внешнюю процедуру С. И менно такой подход применяют наиболее часто, когда нужно обеспечить высокую скорость работы п риложения либо использовать API ­ и нтерфейс от независимых разработчиков, реализованный на языке С. • Если вы не можете решить задачу с помощью внешней процедуры С, всерьез задумайтесь над тем , если в ней необходимость. В этой книге вы будете повсеместно встречать примеры воплощен ия оп исанной выше ф илософии . М ы будем использовать PL/SQ L и его объектн ые тип ы для ре­ шения задач, которые в SQL сделать невозможно или неэффективно. Язык PL/SQL существует уже очен ь долгое время - на его отработку ушло более 27 лет (к 20 1 5 году) ; в действительности , возвращаясь к верси и Oracle ! Og, был переписан сам ком­ п илятор PL/SQL, чтобы стать в первую очередь оптимизирующим ком пилятором. Н и какой другой язык не связан настолько тесно с SQL и не является до такой сте­ пени оптимизированным для взаимодействия с SQL. Работа с SQL в среде PL/SQL происходит совершенно естественным образом, в то время как в любом другом язы­ ке, от Visual Basic до Java, применение SQL может оказаться довольно-таки обреме­ нительны м . PL/SQ L ни когда не выглядел достаточно "естественным " , поскольку он не я вляется расширением какого-то языка. Когда возможности PL/SQL исчерпают­ ся , что в текущих выпусках базы дан ных случается очень редко, мы будем исполь­ зовать Java. И ногда мы будем прибегать к языку С, но, как правило, только когда С я вляется еди н стве н н ым выбором или когда требуется максимальная скорость, обеспечиваемая С. Часто последняя причина уходит на второй план благодаря н из­ коуровневой комп иляции Java - возможности преобразования байт-кода Java в спе­ цифический для операционной системы объектный код платформы. Во многих слу­ чаях это позволяет коду Java работать почти так же быстро, как код С. Метод ч ерного ящ и к а Л ич н ы й практический опыт (имеются в виду допущенные мною ошибки) поз­ волил мне составить собствен ное мнение о причинах столь частых неудач при раз- Ра з работ ка усn е шных n рил о же н и й O racle 49 работке программнаго обеспечения , взаимодействующего с базами данных. Должен признаться, что я включил в эту кни гу ряд проектов, которые хотя и не был и офи ­ циально признаны неудачными, однако потребовали знач ительно большего време­ ни на разработку и развертывание, чем планировалось изначально. П ричина в том , что в них приходилось вносить существенные изменения, изменять архитектуру или прилагать значительные усилия по настройке. Я называю такие затянувшиеся про­ екты неудачами, поскольку в большинстве случаев они должны был и быть заверше­ ны в плановые сроки (или даже быстрее) . Единственная наиболее часто встречающаяся причина неудачи связана с недо­ статочными практически ми знаниями самой базы данных, т.е. отсутствие общего представления об основном инструменте , которы й применяется . Метод черного ящика предполагает намеренное абстрагирован ие разработчи ков от базы дан ных; фактически он поощряет отсутствие вообще каких-либо знани й о базе данн ых! Во многих случаях этот метод препятствует ее использованию. Похоже , что такой под­ ход был порожден страхом , неуверенностью и сомнениями . Было принято считать, что базы данн ых, SQL, транзакции и целостность данных "трудны " для понимания . Итогом стало решение н икого не заставлять делать что-то "трудное " . В результа­ те исповедующие такую философию разработчики относятся к базе дан н ых как к черному ящику и поручают генерацию всего необходимого кода какому-то програм­ мному средству. Они стараются отгородиться множеством защитн ых уровней, чтобы даже не касаться этой "трудной" базы данных. Я никогда не мог понять такой подход к разработке базы данных, частично по­ тому, что лично мне изучение Java и С далось значительно труднее, чем изучение концепций, лежащих в основе баз данн ых. Теперь я знаю языки Java и С довольно хорошо, но для овладения практическими навыками их применения мне понадо­ билось намного больше времени, чем это было при освоении баз данных. В случае базы данных нужно иметь представление о ее работе, но вовсе не обязательно знать абсолютно все ее внутрен н ие и внешние особенности . При программирован и и на С или JavajJ2EE необходимо знать все внутренние и внешние фун кций , количество которых в этих языках поистине огромно. Если вы строите приложение базы данных, то наиболее важной частью прогром ­ много обеспечения является сама база данных. П оэтому члены успешно работающей команды разработки будут учитывать это обстоятельство и стремиться к максималь­ ному изучению базы данных, уделяя ей основное внимание. М ного раз мне доводи­ лось присоединяться к командам разработки проектов, в которых был принят почти диаметрально противоположны й подход. Типичный сценарий мог бы выглядеть следующим образом . • Разработчи ки полностью овладели инструментом для построения графических пользовательских интерфейсов или языком, которы й они используют для со­ здания такого интерфейса (таким как Java). Во многих случаях за их плечами были долгие недели, если не месяцы, обучения . • В команде потратили ноль часов на обучение Oracle и ноль часов на обретение опыта работы с Oracle. Большинство членов команды вообще не имеют опыта взаимодействия с базами данных. Они также получили указание быть " незави­ симыми от базы данных" - указание (вьщанное руководством или выведенное из теоретического свода правил ) , следовать которому у н их мало шансов по Глава 1 50 многим причинам. Самой очевидной причиной я вляется отсутствие у членов команды достаточн ых знани й о том , что собой представляют базы данных или что они делают, которые позволили бы прийти к наименьшему обшему знаме­ нателю среди баз данн ых. • Разработчи ки сталкиваются с м ногочисленными проблемами , которые каса­ ются производительности , целостности данных, зависания приложения и т. п . ( н о зато им удается создавать очен ь привлекательные окна) . В резул ьтате неизбежного возникнове н ия п роблем с производительностью ко мне обращались за помощью в их решен и и (в прошлом, как обучающи йся разра­ ботчик, я часто сам был причи ной таких п роблем ) . В одном конкретном случае я не сумел вспомн ить точн ы й си нтаксис новой команды , которой нужно было вос­ пользоваться . Попросив принести справочное руководство по SQL , я получил в руки документ для верси и Oracle 6.0. Сама разработка велась на основе версии 7.3 - по прошествии пяти лет после выхода версии 6.0! Этот документ был единственным, с чем имели дело разработчики , но было похоже на то, что данный факт их совершен­ но не смущал . Они даже не думали о том, что средства, которые они должны были знать для успешного проведен ия трассировки и настройки , в версии 6 в действи­ тельности не существовали . И х не вол новало, что за те пять лет, которые прошли с момента написания имеющейся в их распоряжении документации , появились новые функциональные возможности, такие как три ггеры , хранимые процедуры и многие сотни других. Понять, почему им потребовалась помощь, не составило труда - чего нельзя было сказать о решен и и возникших у них проблем . На заметку! Даже в наши д н и я часто обнаруживаю, что разработчи ки приложений баз дан н ы х совершенно не уделяют время чте н и ю документации . На своем веб-сайте a s kt om . o r a c l e . com я часто встречаю вопросы вроде "как выглядит синтаксис для . . . " в сочетании с заявлениями "у нас нет документации , поэтому, пожалуйста, просто расска­ жите нам " . Я отказываюсь давать прямые ответы на м ногие из таких вопросов, а вместо этого отправляю спрашивающих к сетевой документации , доступной любому пользовате­ лю где угодно в м и ре. За последние 1 5 лет оправдания типа "у нас нет документации" или "у нас нет доступа к ресурсам" практически утратили свою актуальность. Распространение И нтернета и появление таких сайтов, как otn . o r ac l e . com (Oracle Techпology Network ­ сеть технологии Oracle ) , делает отсутствие под рукой полного набора до ку ментации со­ вершенно непростительны м ! Сегодня каждый и меет доступ ко всей документации ; нужно п росто ч итать ее, или - что еще п роще - искать в ней ответы на вопросы . Сама идея о том , что разработчи ки , которые строят приложение базы данных, должны быть изол ированы от базы данных, представляется мне странной , но такая позиция существует. Многие продолжают верить, что разработчи ки не могут тратить время на освоение базы дан н ых и в целом вовсе не обязаны что-либо знать о базе данных. Почему? Не единожды мне доводилось слышать утверждение наподобие " . . . ведь Oracle является наиболее масштабируемой базой дан ных в мире, поэтому моему персоналу не нужно ее изучать; она просто работает" . Действительно, Oracle - са­ мая масштабируемая база данн ых в мире. Однако в среде Oracle наряду с эффектив­ ным и масштабируемым кодом достаточно легко написать неудачный и не поддаю­ щийся масштабировани ю код. Замените слово "Oracle" названием любого другого программнога обеспечен ия, и утверждение останется справедливым. Не подлежит Ра з работка усnеш н ых n ри л ожен и й O racle 51 сомнению: приложение, которое работает плохо, написать знаqительно проще, qем приложение, которое работает хорошо. Даже в самой масштабируемой в м ире базе данных иногда о<Iень легко полуqить в итоге однопользовательскую систему, если вы не знаете, qто делаете. База дан н ых - это и нструмент, а неправильное применение любого инструмента может приводить к проблемам . Стали бы вы разбивать грецкие орехи щипцами для колки орехов так, как если бы это бьm молоток? Конеqно, щип­ цы можно бьmо бы использовать и так, но подобное применение этого и нструме нта является неподходящим, и дало бы в результате месиво (а возможно и несколько ушибленных пальцев) . И гнорирование особенностей базы данных может привести к аналогиqным последствиям . Как-то меня пригласили принять уqастие в одном проекте, которы й зашел в ту­ пик. Разработqи ки столкнулись с крупными проблемами , касающи мися п роизводи ­ тельности ; создавалось впеqатление, 'ITO их система выполняла многие транзакции последовательно. Вместо того qтобы множество пользователей могл и работать па­ ралл ел ьно, кажды й из них помещался в дл и нную оqередь и был вынужден дожи­ даться , пока завершит работу пользователь, стоящий перед н и м . Архитекторы сис­ темы ознакомили меня со своим творением - класси<Iеской трехзвен ной моделью. В этой системе веб-браузер должен бьm обмен иваться данными с сервером приложе­ ний среднего звена, на котором функционировали страни цы J S P (JavaServeг Pages) . В свою оqередь, J S Р-страни цы должны бьmи использовать еще один уровень, бины Enterprise JavaBeans ( EJ B) , которы й выпол нял все SQ L-запросы . Код SQL в бинах EJ B генерировался и нструментом третьей стороны в независимой от базы данных манере. В системе было оqень трудно диагностировать qто-либо, т. к. н и оди н из фраг­ ментов кода не бьm снабжен каким-нибудь инструментарием или средствами трас­ сировки . Снабжение кода инструментарием - это тонкое искусство превращен ия каждой второй строки разработанного кода в отладочн ы й код, который в случае возникновения проблем с производительностью , емкостью или даже логикой поз­ воляет точно отследить место, где они произошли . В сложившейся ситуации можно бьmо утверждать лишь то, что источник проблемы находился между браузером и ба­ зой данных - другими словами , под подозрением оказалась вся система. База дан ­ ных Oracle тщательно инструментирована, но приложение должно быть в состоян и и включать и отключать инструментарий в соответствующих точках, а это как раз то, что не бьmо предусмотрено проектом. Таким образом , мы столкнулись с попыткой диагностирования проблем произ­ водительности, располагая лишь теми сведениями , которые можно бьmо почерпнуть из самой базы данных. К счастью, в этом слуqае решение бьmо довольно простым . Просмотр таблиц V$ (эти таблицы я вляются одн им из способов предоставления доступа к инструментарию и статистической и нформации Oracle) показал , что ос­ новное соперн ичество велось за единственную табли цу - таблицу очереди на об­ работку. Приложение должно бьmо помещать записи в эту табли цу, а другой набор процессов - извлекать записи из нее и обрабатывать. Исследовав эту табли цу более внимательно, мы обнаружили битовы й индекс на одном из столбцов (более подроб­ ную информацию о битовых индексах можно найти в главе 1 1 ) . Причина такого вы­ бора состояла в том, что этот столбец - флаг обработки - мог содержать только два значения: У и N. Записи , вставленные в таблицу, должны бьmи иметь в этом столбце значение N (не обработана) . 52 Глава 1 П осле считывания и обработки зап иси другими процессами эти процессы долж­ н ы были изменять значение в столбце с N на У, указы вая на то, что запись обрабо­ тана. Разработчи кам нужно было быстро находить записи со значен ием N, поэтому столбец был прои ндексирован . О н и где-то прочитал и , что битовые индексы пред­ назначены для столбцов с н изким кардинальным числом (столбцов, содержащих небольшое количество отличающихся значени й ) , поэтому сочли такой вид и ндекса вполне естественным. ( Попробуйте поискать в Google строку "when to use Ьitmap in­ dexes" (когда использовать битовые индексы); словосочетание "low-cardinality" (низ­ кое кардинальное число) будет встречаться повсеместно. К счастью, сейчас имеется также много статей , опровергающих эту излишне упрощенную концепцию.) И менно битовый и ндекс был причи ной всех проблем . В битовом индексе единс­ твен ная запись ключа указывает на множество строк - сотн и и более . Когда ключ битового индекса обновляется (и тем самым блокируется) , то сотни записей , на ко­ торые он указывает, также блокируются . Таким образом, вставка новой записи со значением N приводит к блокированию зап исей N в битовом индексе , по существу блокируя также и сотни других записей со значением N . М ежду тем процесс , ко­ торый читает эту табли цу и обрабатывает зап иси , не имеет возможности изменить значение какой-либо записи с N на У, т.к. для этого ему пришлось бы заблокировать тот же самый ключ битового и ндекса. Фактически другие сеансы, которые пытают­ ся всего л и ш ь вставить новую запись в эту таблицу, также должны блокироваться , поскольку они предпринимают попытку заблокировать ту же самую запись битового ключа. Короче говоря , разработчи ки создали табли цу, вставлять и обновлять записи в которой мог только один пользователь за раз! Мы можем ле гко в этом убедиться , используя простой сценар и й . На заметку! Для демонстрации проблем блокировки и параллельного доступа н а протяже­ н и и всей книги я буду использовать автономные транзакции . Я твердо убежден , что ав­ тономные транзакции являются средством, которое в Oracle не должны были открывать разработч икам по той простой причине, что больши нство разработчиков не знают, ког­ да и как п р именять их правильно. Некорректное использование автономных транзакци й может - и будет - приводить к проблемам нарушения логической целостности данных. Помимо их применения в качестве демонстрационного и нструмента, автоном ные тран­ закции и меют только еще одно п редназначение - служить механизмом п ротоколи рова­ ния ошибок. Чтобы запротоколи ровать ошибку в блоке исключения, понадобится записать сведения о ней в табли цу и зафиксировать ее, не фиксируя н ичего другого. Это было бы допустим ы м использованием автономной транзакции . Если вы применяете автоном ную транзакци ю вне контекста протоколирования или демонстрации концепци и , значит, вы почти наверняка делаете что-то совершенно неправильное. Здесь я испол ьзую автономную транзакцию в базе дан ных, чтобы иметь две па­ раллельные транзакци и в одном сеансе . Автономная транзакция запускает "подтран­ закцию" отдельно и независимо от любой уже установившейся транзакции в сеансе. Эта автономная транзакция ведет себя так, как если бы она находилась в совершен­ но отдельном сеансе - фактически родительская транзакция приостанавли вается . Автономная транзакция может быть заблокирована родительской транзакцией (как мы увидим) и , более того, автономная транзакция не может видеть незафи ксиро­ ванных модификаций , произведенных родительской транзакцией. Например: Ра зработка усnеш н ых n рило же н и й Oracle 53 EODA@ORA12CR1> create taЬle t 2 ( proce s s ed_f lag va rchar2 ( 1 ) 3 ); ТаЬlе created . Таблица создана . EODA@ORA12CR1> create bitmap index 2 t_idx on t ( processed_flag ) ; I ndex created . ИНдекс создан . EODA@ORA 12CR1> insert into t va lues ( ' N ' ) ; 1 row created . 1 строка создана . EODA@ORA12CR1> declare 2 pragma autonomous transact ion ; 3 begin 4 insert into t value s ( ' N ' ) ; 5 commit ; 6 end ; 7 1 declare * ERROR at l i ne 1 : ORA - 0 0 0 6 0 : deadlock detected whi l e wa it ing for resource ORA - 0 6 5 1 2 : at l ine 4 ОПМБКА в строке 1 : ORA - 0 0 0 60 : в процессе ожидания ресурса обнаружена взаимная блокировка ORA - 0 65 1 2 : в строке 4 Совет. За подробными сведениями о настройке приглашения командной строки SQL для отображения информации о среде , такой как имя пользователя и имя базы данных, обра­ щайтесь в раздел " Настройка среды" в начале книги . Поскольку использовалась автономная транзакция и создана подтранзакци я , произошла взаимная блокировка, т.е. вторая вставка была заблокирована первой вставкой. Если бы имелось два отдельных сеанса, то н и какой взаимной блокиров­ ки не возникло бы. Вместо этого вторая вставка просто б ыла бы заблокирована и ожидала, пока не произойдет фиксация или откат первой вставки . И менно этот симптом проявился в проекте, с которы м я и мел дело - проблема с блокировкой и сериализацией. Таким образом, в приведеином случае мы столкнулись с отсутствием понимания функциональной возможности базы данных (битовых и ндексов), в результате чего с самого начала база данных была обречена на плохую масштабируемость. П роблему усугубляло также и то, что не было ни каких причин для написан ия кода работы с очередью. В базе данных доступны встроенные средства работы с очередями, кото­ рые появил ись в версии Oracle 8.0, вышедшей в 1 997 году. Встроенное средство ра­ боты с очередями позволяет иметь много производителей (сеансов, которые встав­ ляют необработанные зап иси ) , одновременно помещающих сообщения в очередь, и много потребителей (сеансов, которые получают записи со значением N для об­ работки) , параллельно получающих эти сообщения. Это значит, что для реал изации Глава 1 54 очереди в базе данных писать какой-то специальный код не требуется . Разработчики должны был и воспользоваться встроен ным средством. И они могли это сделать, но им помешала полная неосведомленность о его существовании. К счастью, как только причина проблемы была выявлена, ее устранение не со­ ставило особого труда. Столбец флага обработки нуждался в и ндексе , но не в би­ товом. Здесь необходим обычн ы й и ндекс со структурой В-дерева. Это вызвало не­ продолжительные споры , поскольку никто не верил , что использование обычного и ндекса в столбце, содержащем два отличающихся значения, является удачной иде­ ей. Однако после выполнения моделирования (я большой поклонник моделирова­ ния, тестирования и экспериментирования) мы смогли удостовериться в правиль­ иости этого подхода. На заметку! Мы создаем и ндексы - любого типа - обычно для поиска небольшага количес­ тва строк в крупном наборе дан ных. В этом случае количество строк, которые мы хотели искать через и ндекс, было равно одному. Мы нуждались в поиске одной необработанной записи . Одна строка - это очень маленькое количество, следовательно, и ндекс является подходящим решением. Подошел бы и ндекс любого типа. И ндекс со структурой В-дерева весьма удобен при поиске одиночной записи в большом наборе записей. При создании и ндекса необходимо выбрать один из следующих подходов. • П росто создать и ндекс на столбце флага обработки . • Создать и ндекс на столбце флага обработки только для тех зап исей, в кото­ рых флагом обработки является N т.е. индексировать только и нтересующие значения. Как правило, мы не хотим применять индекс, когда флаг обработки равен У, из-за того, что подавляющее большинство зап исей в таблице имеют флаг обработки У. Обратите внимание, что здесь не было сформулировано "мы никогда не хотим . . . ". Если по какой-то причине необходимо часто подсчиты­ вать количество обработанных записей, то наличие и ндекса для таких записей может быть очен ь полезно. - В главе , посвященной и ндексаци и , м ы более детально рассмотрим оба под­ хода. В кон це кон цов, мы создали очен ь маленький и ндекс только на записях, в которых флаг обработки был равен N. Доступ к эти м зап исям был исключи­ тельно быстрым, а подавляющее большинство записей со значен ием У вообще не участвовали в этом и ндексе . М ы испол ьзовали и ндекс, основанный на фун кции decode ( proce s s ed_ f l a g , 1 N 1 , 1 N 1 ) , которая возвращает либо N, либо NULL; учи­ тывая , что ключ NULL в обычн ы й индекс В-дерева не поме щается , в результате мы проиндексировали только записи со значением N. На заметку! В главе 1 1 вы найдете дополн ительные сведения о NULL и и ндексации . Закончилась ли на этом история? Вовсе нет. Решение, находя щееся в руках моего клиента, все еще оставалось неоптимальным. По-прежнему приходилось выполнять сериализацию " извлечен ия из очереди " необработанных записей. Мы могли быст­ ро найти первую необработанную запись, используя s e l e ct * f r om queue _taЬle whe r e decode ( pr o ce s s ed_f l a g , 1 N 1 , 1 N 1 ) = 1 N 1 FOR U P DATE , НО ВЫ ПОЛНЯТЪ ЭТУ операцию мог тол ько один сеанс за раз. В проекте применялась версия Oracle \ Og, Ра зрабо т ка усп ешн ых п рил ожен и й O rac l e 55 и потому нельзя было воспользоваться относительно новым средством SKI P LOCКE D, которое появилось только в Oracle l lg Release l . Ко нструкция sкr Р LOCKE D поз­ волила бы м ногим сеансам п араллельна находить первую неблакированную и н е ­ обработан н ую запись, п осле чего заблокировать е е и обработать. Вме сто этого м ы должны был и реал изовать код для н ахожде н и я первой н еблакирован ной зап иси и блокировать ее вручную. Такой код в Oracle l Og и предшествующих ве рсиях в целом вы глядел бы так, как показано н иже . Мы начин аем с создан ия таблицы с требуемы м индексом , которы й был описан ранее , и наполне ния ее некоторы м и данн ыми : EODA@ORA1 2CR1> c reate taЬle t 2 ( id numЬer prima ry key , 3 proce s s ed_flag va rcha r2 ( 1 ) , 4 payload va rchar2 ( 2 0 ) 5 ); ТаЫе created . Таблица создана . EODA@ORA 1 2 CR 1 > ereate i ndex 2 t idx on 3 t ( decode ( proces sed_flag , ' N ' , ' N ' ) ) ; I ndex created . Индекс создан . EODA@ORA12CR1> insert into t 2 se lect r , 3 ca se when mod ( r , 2 ) = О then ' N ' e l s e ' У ' end , 4 ' payload ' 1 1 r 5 from ( select level r from dual б 7 connect Ьу level <= 5 ) 8 1 5 rows created . 5 с трок создано . EODA@ORA12CR1> select * f rom t ; I D Р PAYLOAD 1 У payload 1 2 N payload 2 3 У payload 3 4 N payl oad 4 5 У payload 5 З атем понадобится найти все необработанн ые зап и с и . Для каждой зап иси м ы от­ правляем базе дан ных вопрос вида: "Заблокирована ли уже эта за п и с ь? Есл и нет, то заблокировать ее и предоставить " . Код выглядит пр и мерно так: EODA@ORA1 2CR1> create or replace 2 function get_firs t_unloc ked_row 3 return t % rowtype 4 as resource_busy exception ; 5 pragma excepti on_i n i t ( resou rce_bus y , - 5 4 ) ; б 7 l_rec t % rowtype ; 56 Глава 1 В begin for х i n se1ect rowid rid 9 10 f rom t whe re decode ( p roce s s ed_f1ag , ' N ' , 1 N 1 ) 11 1оор 12 13 begin s e 1ect * into 1 rec 14 f rom t 15 where rowid = x . rid and proce s sed_f1ag= 1 N 1 1б for update nowai t ; 17 return 1 rec ; 1В exception 19 20 when resource_bus y then nu1 1 ; when no_data_found then nu1 1 ; 21 end ; 22 end 1 оор ; return nu1 1 ; 23 2 4 end; 25 1 Function created . Функция создана . 'NI ) На заметку! В п р иведенном выше коде был выполнен код D D L - C REAT E OR R E P LACE FUNCT I ON . Непосредственно перед запуском оператора DDL п роисходит автоматическая фиксация, поэтому здесь присутствует неявный вызов соммr т . Вставляемые строки фик­ сируются в базе данных - и этот факт необходим для корректной работы последующих примеров. Вообще говоря , факт автоматической фиксации используется повсеместно в оставшейся части книги. Если вы запускаете эти примеры без выполнения CREATE OR RE PLACE , не забудьте сначала сделать сомм r т ! Есл и теперь п ри мен и ть две р азн ы е транзакц и и , можн о заметить , что он и п ол уч а­ ют разные зап и с и . Кро м е того, о н и п ол учают и х одн о временн о (с н о ва с ис п ользова­ н и ем авто ном ных транз а кци й для дем о н стр ац ии п роблем параллельн ого доступ а ) : EODA@ORA1 2 CR1 > dec1are 2 1 rec t % rowtype ; 3 begin 4 1 rec : = get first un1ocked row ; 5 dЬms_output . put_1ine ( 1 I got row ' 1 1 1 rec . id 1 1 б end; 7 1 I got row 2 , payload 2 PL/SQL p rocedure succe s s fu 1 1 y completed . Процедура PL/SQL успешно выполнена . - - - 1 EODA@ORA 1 2 C R 1 > dec 1 are 2 p ragma autonomous_t ransaction ; 3 1 rec t % rowtype ; 4 begin 5 1 rec : = get first unlocked row ; б dЬms_output . put_1 ine ( ' I got row ' 1 1 1 rec . id 1 1 ' 7 commi t ; в end; 9 1 1 1 1 1_rec . payload ) ; ' 1 1 l_rec . payload ) ; - - - Разработка успешных пр иложе н и й Oracle 57 I got row 4 , payload 4 PL/ SQL p rocedure succe s s fu l l y completed . Процедура PL/SQL успешно выполнена . Теперь в Oracle l lg Release 1 и последующих версиях показанную выше логику можно реализовать с применением конструкции S K I P LOCKED. В приведеином далее примере мы снова выполним две параллельные транзакции и обнаружим, что каж ­ дая находит и блокирует записи одновременно. EODA@ORA12CR1> dec l a re 2 l_rec t % rowtype ; 3 curs o r с 4 is s elect * 5 f rom t б 7 where de code ( p ro ce s s ed_f l a g , 1 N 1 , 1 N 1 ) FOR U PDATE в 9 SКI P LOCI<ED ; 1 0 begin open с ; 11 12 fetch с into l rec ; i f ( c% found ) 13 14 15 1б 17 1В 19 INI then dЬms_output . put_l ine ( 1 I got row 1 1 1 l_rec . id 1 1 1 1 l_re c . payload ) ; end i f ; close с ; end ; 1, 1 I got row 2 , payload 2 PL/ SQL p rocedure succe s s fu l l y completed . Процедура PL/SQL успешно выполнена . EODA@ORA1 2CR1> dec l ar e 2 pragma autonomous_t ra n s a ct i o n ; 3 l_rec t % rowtype ; 4 cursor с is 5 б s elect * 7 from t в whe r e decode ( p roce s s ed_flag , 1 N 1 , 1 N 1 ) INI FOR UPDATE 9 1О SКIP LOCI<ED ; 1 1 begin 12 open с ; 13 fetch с i nto l re c ; 14 i f ( c% found ) 15 then 1б dЬms output . put_l ine ( 1 I got row 1 1 1 l_rec . id 1 1 1 1 l_re c . payload ) ; 17 end i f ; close с ; 1В 19 commit ; 2 0 end ; 21 1 1 58 Глава 1 I got row 4 , payload 4 PL/ SQL p rocedure succe s s ful l y completed . Процедура PL/SQL успешно выполнена . Оба продемонстрированн ы х выше "реш е н ия " должн ы помочь справиться со второй проблемой сериализации , с которой столкнулся мой клиент при обработке сообще н и й . Но намного л и проще получилось бы решение, если бы клиент прос­ то применял средство Advaced Queuing и вызывал процедуру DBMS _AQ . DEQUE UE? Чтобы решить проблему сериал изации поставщика сообщений, нам пришлось ре­ ализовать индекс, основанный на функции . Чтобы решить проблему сериализации для потребителя, пришлось использовать этот основанный на функции индекс для извлечен ия зап исей и написания кода. Таким образом , мы устранили основную про­ блему, порожденную неполным пон иманием применяемых средств, и лишь после тщательного изучения выяснили, что система была недостаточно инструментирова­ на. Однако перечисленные ниже проблемы остались нерешенными. • Приложение было построено без единого соображен ия относительно масшта­ бирования на уровне базы дан ных. • В приложении была реализована функциональность (таблица очереди), кото­ рую база данных уже предоставляла, причем с высокой степенью параллелиз­ ма и масштабируемости . Речь идет о программном обеспечении AQ (Advaced Queuing - расширенная организация очереде й ) , встроенном в базу дан ных. Разработчики пытались построить эту функциональность заново. • Опыт показал , что от 80 до 90 (и более!) процентов всех действий по настройке должны быть выполнены на уровне приложения (обычно в интерфейсном коде, который читает и записывает в базу данных), а не на уровне базы дан ных. • Разработчи ки не и мели н и малейшего представления о том, что делают бины в базе дан н ых, или где искать поте нциальные проблемы. Н а этом проблемы данного проекта не исчерпывались. Нам также необходимо было выяснить следующие моменты. • Как настроить SQL-кoд, не изменяя е го. Вообще говоря , это очень трудно. Овладеть до не которой степени этой магией в Orac\e 1 Og и последующих вер­ сиях можно с помощью SQL Profi\es (эта опция требует лицензии на пакет на­ стройки Oracle (Oracle Tuning Pack) ) , в Oracle l l g и выше - посредством рас­ ш иренной статистики , а в Oracle l 2c и далее - с использованием адаптивной оптимизации запросов. Однако неэффекти вный SQL-кoд остается неэффек­ тивным SQ L-кодом . • Как измерить производительность. • Как выявить имеющиеся узкие места. • Как и что и ндексировать. И так далее. К концу недели разработчики , ранее сторонившиеся базы данных, были пораже­ ны тем и возможностями, которые она могла предоставить, и простотой получения и нформации . Самое главное , они увидел и , наскол ько ее применение может повы­ сить производительность приложения . В итоге разработч ики добились успеха, от­ став от графи ка всего на несколько недель. Ра з работка усnе ш ных n р иложе н и й Oracle 59 Мой рассказ о мощи возможностей базы дан н ых приведен здесь не для того, что­ бы критиковать средства или технологии , подобные H ibemate, EJ B и контейнерному подходу к реализации постоянства. Критика касается намерен ного и гнорирования базы данных, особенностей ее функциони рования и с пособов ее использования . Применеиные в рассмотренном случае технологии вполне себя оправдали - разу­ меется, после того, как разработчи ки получили некоторое представление о самой базе данных. Подводя итог, можно сказать, что база данных, как правило, служит краеутоль­ ным камнем приложения . Если она работает недостаточно хорошо, то все остальное не имеет особого значения. Что делать, если используемый черн ы й ящик плохо ра­ ботает? Единствен ное что можно предпринять в этой ситуации - смотреть на него и гадать, почему он работает не так, как нужно. Вы не можете н и поч и нить его, н и настроить. В ы просто не понимаете, каким образом о н работает - и в ы сознатель­ но поставили себя в такое положен ие . Альтернативой является отстаиваемый м ною подход: понимать базу данн ых, знать, как она работает, что она может предложить, и в полной мере задействовать ее потенциал . К ак следует ( и как не следуе т ) разрабатывать приложе ния баз дан ных Но достаточно строить гипотезы , сейчас, по крайней мере . В оставшейся части этой главы будет применяться более практический подход с обсуждением того, почему знание базы данных и ее элементов определенно позволит значительно приблизиться к успеш ной реализаци и (не переписывая приложение по нескольку раз). Некоторые проблемы устранять проще, если понимать, каким образом их искать. Устранение других проблем может потребовать радикального переписывания кода. Одна из целей настоящей книги - в первую очередь помоч ь вам избежать этих проблем. На заметку! В приведенных далее разделах некоторые основные функциональные средства Oracle обсуждаются без подробного освещения их сути и всех особен ностей применения. При необходимости я буду отправлять за деталями либо к одной из последующих глав книги , либо к соответствующей документации Oracle . Архитектура Oracle М не приходилось сотрудничать со многи м и клиентами , использующими круп­ ные производственные приложе н ия , которые были " перенесены" в Oracle из друтой платформы баз данных (например, SQL SeiVer) . Слово " перенесено" взято в кавыч ­ к и потому, что больш инство встречаемых м н о ю адаптаций сводились к точке зрен ия "найти минимальные изменения , которые обеспечил и бы успешную комп иляцию и выполнение кода SQL SeiVer на платформе Oracle" . Откровенно говоря , приложе­ ния, построенные в результате такого подхода к делу, попадались мне чаще всего, поскольку именно они требовали наибольшей помощи. Я вовсе не критикую SQL SeiVer в этом отношен и и - ведь справедливо и обратное! П еренос приложе н и я Oracle и его помещение с минимальн ы м и изменен ия м и в среду SQL SeiVer при ве­ дет к получению столь же плохо работающего кода, как и наоборот; проблема имеет обоюдный характер. 60 Гл ава 1 Однако в одном конкретном случае архитектура SQL Server и способ применения SQL Server действительно были навеян ы реал изацией Oracle . В качестве конечной цели ставилось масштабирование, но обратившиеся ко м не разработчи ки на самом деле не хотели переходить на другую базу дан н ых. Они хотели провести перенос с м и н и мальными усилиями со своей сторон ы , и потому оставил и архитектуру в ос­ новном прежней - на уровне клиента и базы дан н ых. Это решение имело два важ­ н ых последствия . • Архитектура подключений в Oracle осталась той же самой, что и использован­ ная в SQL Server. • Разработчи ки применял и литеральны й (неограниченный) SQL-кoд. Эти два обстоятельства повлекли за собой построение системы, которая не могла поддержи вать необходимую пользовательскую нагрузку (серверу базы дан ных прос­ то не хватало доступной памяти ) и обладала крайне низкой производительностью. Испо льзуйте единственное подключение в Orac/e В среде SQL Server открытие подключения к базе данных для каждого параллель­ но выпол няющегося оператора является весьма распространенной практикой . При выполнении пяти запросов в среде SQL Server вполне можно встретить пять под­ ключен и й . С другой сторон ы , в Oracle вне зависимости от того, сколько запросов нужно выполн ить, пять или даже пятьсот, максимал ьное количество открываемых подключений равно еди нице. В результате то, что принято в SQL Server, совершенно не рекомендуется применять в среде Oracle; нал ичие множества подключений к базе дан н ых просто нежелательно. Однако как раз это и было сделано. П ростое веб- приложение для каждой веб­ страницы может открывать 5, 1 0, 1 5 и более подключений, а это значит, что сервер мог поддерживать только 1 /5, 1/ 1 0, 1 / 1 5 и менее параллельна работающих пользовате­ лей от того числа, которое должен . Кроме того, была предпри нята попытка исполь­ зован ия базы данных на обычной платформе Windows - в среде простого сервера Windows без доступа к Datacenter- вepcи и Windows Server. В результате архитектура Windows с единственным процессом ограничила общи й объем операти вной памя­ ти, доступ ной серверу баз данных Oracle, до приблизительно 1 , 75 Гбайт. Поскольку каждое подключение Oracle занимает, как м и н имум, определен н ы й фиксирован­ ный объем памяти , возможности масштабирования кол ичества пользователей , ра­ ботающих с приложен ием, были существенно ограничены . Объем оперативной па­ мяти сервера составлял 8 Гбайт, но из них можно было использовать только около 2 Гбайт. На заметку! В среде 32-разрядной ОС Windows достуnны способы использования большего объема оперативной памяти , такие как ключ /AW E , но для этого требуются версии ОС, которые в описанной ситуации не применялись. Существовало три подхода к решению этой проблем ы , причем все три были до­ статочно трудоем кими - и это после завершения " переноса"! Ра зрабо т ка усп е шных п риложе н и й Oracle 61 Были доступны следующие варианты . • Изменить архитектуру приложения, чтобы оно могло получить преимущест­ ва выполнения в среде Oracle , и во время генерирования страни цы применять одно подключение, а не от 5 до 1 5. Это единствен ное решение, которое дейс­ твительно устранило бы проблему. • Провести модернизацию ОС (отнюдь не простая задача) и задей ствовать мо­ дель с большим объемом доступной памяти, предлагаемую версией Wmdows Server Datacenter (что само по себе совсем не просто, т. к. сопряжено со слож­ ной настройкой базы дан н ых, с определением косве н н ых буферов данных и других нестандартных параметров) . • П еренести базу данных из Windows в среду какой-то другой ОС, которая под­ держивает множество процессов. Это фактически позвол ило бы базе дан н ых задействовать всю установленную оперативную память. На 32-разрядной плат­ форме Windows вы ограниче н ы примерно 2 Гбайт памяти дЛЯ комбинирован­ н ых областей PGNSGA (2 Гбайт для обеих вместе), поскольку они выделяются еди нственным процессом . При использовании платформы с множеством про­ цессов, которая также является 32-разрядной , вы будете ограничены примерно 2 Гбайт для SGA и 2 Гбайт на процесс для PGA, что существенно больше, чем обеспечивает 32-разрядная платформа Windows. Как видите, ни одна из этих возможностей не относилась к решениям, о которых можно было бы сказать: "Хорошо, мы сделаем это до обеда" . Каждая из них пред­ ставляла собой сложное решение проблемы, которую проще всего было решить на этапе переноса базы данных, пока вносились изменения в код и в наиболее важные элементы системы. Более того, простое тестирование масштабирования , проведеи ное до развертывания системы, позволило бы выявить проблемы подобного рода еще до того, как конечные пользователи начали бы испытывать какие-то неудобства. Используйте переменные привязки Если бы я писал кни гу о том , как строить немасштабируемые приложе н ия Oracle, то первая и последняя глава называлась бы " Не используйте переменные привязки " . Отказ от применения перемен н ых привязки является основной причиной возник­ новения проблем с производительностью и главным ограничителем возможностей масштабирования , не говоря уже об огромной степени риска в плане безопасности . Способ работы Oracle с разделяемым пулом (очень важная структура данных в раз­ деляемой памяти) в большинстве случаев определяется разработчи кам и , использу­ ющими переменные привязки . Если вы хотите заставить транзакционную реализа­ цию Oracle работать медленно, вплоть до пол ной ее остановки , просто откажитесь от применения переменных привязки. Переменная привязки - это метка-заполнитель в запросе . Например, дЛЯ извлечения записи сотрудни ка 1 2 3 можно выполнить следующий запрос: select * from emp whe re empno = 1 2 3 ; В качестве альтернативы можно запустить такой запрос: select * from emp whe re empno = : empno ; 62 Глава 1 В типичной системе запрос информации о сотруднике 1 2 3 вполне может быть выполнен оди н или два раза и больше н икогда на протяже н и и длительного пери­ ода време н и . Позже может требоваться информация о сотрудни ке 4 5 6 , затем - о сотруднике 7 8 9 и т.д. Или, как в предшествующих операторах SELECT, если вы не указываете в своих операторах вставки переменные привязки , то значения первич­ ного кл юча будут жестко закодированы в них, и мне известен тот факт, что такие операторы вставки н икогда не смогут использоваться повторно! Если в запросе при­ меняются литералы (константы) , то каждый запрос оказывается совершенно новым, н и когда ранее не выполнявшимся в базе дан ных. Он должен быть си нтаксически разобран , определен (произведено распознавание и ме н ) , проверен на соблюдение правил безопасности, оптим изирован и т. п . Короче говоря, каждый запускаемый уникальный оператор будет требовать ком­ пиляции при каждом своем выполнен и и . Во втором запросе использовалась переменная привязки : empn o , значение ко­ торой передается во время выполнения запроса. Этот запрос компилируется толь­ ко один раз, а затем план запроса сохраняется в разделяемом пуле (библиотечном кеше), из которого он может быть извлечен и применен повторно. Разница между этим двумя методами с точки зрен ия производительности и масштабируемости не просто вели ка - она огромна. И з предыдущего объяснения должно быть совершенно понятно, что синтакси­ чески й разбор оператора с жестко закодирован н ы м и переме нными (называемый полным разбором) будет проходить дольше и потреблять намного больше ресурсов, чем повторное использование уже разобранного плана запроса (которое называется частичным разбором) . Однако степень сн ижения количества пользователей, кото­ рых может поддерживать система, при первом методе может оказаться не настолько ясной. Очевидно, что отчасти это объясняется увеличением потребления системных ресурсов, но более значительный фактор связан с влиян ием механизмов защелок, применяемых к библиотечному кешу. П ри выпол н е н и и пол ного разбора запроса база данных будет дольше хран ить определенные н изкоуровневые устройства последовательной обработки , называе­ мые защелками (или внутренними блокировками) ; за допол нительной информацией о н их обращайтесь в главу 6. Эти защелки защищают структуры данных в разде­ ляемой памяти Oracle от одновременных изменений двумя сеансами (в противном случае структуры данн ых были бы повреждены) и от считывания структуры данных кем-либо во время ее изменения. Чем дольше и чаще приходится "защелки вать" эти структуры данных, тем более длинной будет становиться очередь для получения таких защелок. Это приведет к монополизации ограниченных ресурсов. Временами компьютер может выглядеть недогружен н ы м , тем не менее, все действия в базе дан н ых будут выполняться очен ь медленно. Внешне все выглядит так, будто кто­ то владеет одн и м из механизмов последовательной обработки , создавая очередь ­ достичь максимальной производительности не удастся . Достаточно нал и ч ия в базе данн ых одного неправильно ведущего себя приложения , чтобы производительность всех приложе н и й знач ительно сн изилась. Еди нствен ное небольшое приложение без переменных привязки со временем приведет к удалению из разделяемого пула всех SQL-запросов, принадлежащих остальн ы м хорошо настроенным приложениям . Одной ложки дегтя хватит, чтобы испортить бочку меда. Ра зрабо т ка усп ешных п р ил оже н ий O racl e 63 Н а заметку! Чтобы увидеть отличие между полным и частичным разбором в действии, реко­ мендуется пересмотреть демонстрационный видеоролик, доступный по ссылке http : 1 1 t i nyu r l . corn / RW P -OLT P - PARS I NG . О н был смонтирован командой, с которой я рабо­ тал - командой Real World Performance ( П роизводительность в реальном мире) из Oracle . В нем наглядно показана разница между полным и частичным разбором - она близка к отличию на порядок! В транзакционной системе, архитектура которой ориентирована на использование переменных привязки , можно добиться десятикратного увеличения скоро­ сти выполнения в случае их применения. Вы можете использовать эту короткую визуаль­ ную презентацию, чтобы убедить других разработчиков о высоком влиянии переменных привязки (либо их отсутствия) на производительность! Если же вы применяете переменные привязки , то любой, кто отправляет точно такой же запрос, ссылающийся на тот же самый объект, будет использовать ском п и ­ лированный план из пула. Комп иляция процедуры производится только один раз, после чего ею можно пользоваться снова и снова. Это очен ь эффективно, и именно на такую работу рассчитана база данных. П ри этом н е только умен ьшается объем задействованных ресурсов (частичный разбор требует намного меньшего количества ресурсов), но также сокращается время действия защелок, да и потребность в н их будет возникать реже . В результате производительность и масштабируемость прило­ жений значительно возрастают. Чтобы получить общее представление о том , насколько огромн а разн ица в про­ изводительности в случае применеимя переменных привязки , можно запустить не­ большой тест. В этом тесте мы просто вставим нескол ько строк в следующую про­ стую таблицу: EODA@ORA 1 2 CR1> create taЬle t ТаЫе created . Та блица создана . ( х int ) ; Теперь создади м две очен ь простые хранимые процедуры . Обе они будут встав­ лять в табли цу числа от 1 до 1 О 000, но первая процедура использует единствен н ы й SQL-oпepaтop с переменной привязки: EODA@ORA 1 2 CR1> create or replace procedure proc1 2 as 3 begin for i in 1 . . 1 0 0 0 0 4 loop 5 б execute irnrnediate 1 insert into t values ( : х ) 1 u s i ng i ; 7 end loop ; 8 9 end; 10 1 Procedure created . Процедура создана . Вторая процедура конструирует уни кальный SQL-oпepaтop для каждой вставля­ емой строки : EODA@ORA 1 2 CR1> create or replace procedure proc2 2 as 3 begin 64 Глава 1 4 for i in 1 . . 1 0 0 0 0 1оор 5 б execute immediate 7 ' insert into t va1 ue s ( 8 end 1оор ; 9 e nd ; 10 1 Procedure created . Процедура создана . ' 1 lil 1 ') '; Еди нственное отличие между этим и двумя процедурами состоит в том, что в од­ ной применяется переменная привязки , а в другой - нет. Обе процедуры исполь­ зуют динам ический SQL-кoд с идентичной логикой . Разница закл ючается только в применен и и перемен ной привязки в первой процедуре . М ы можем оценить два подхода с использованием простого разработанного мною инструмента run s t a t s для детального сравнен ия : EODA@ORA12CR1> ехес runstats_p kg . rs_start PL/SQL p rocedure succe s s fu l l y completed . Процедура PL/SQL успешно выполнена . EODA@ORA12CR1> ехес proc1 PL/SQL p rocedure succe s s fu l l y completed . EODA@ORA12CR1> ехес runs tats_p kg . rs_middle PL/ SQL p rocedure succe s s fu l l y completed . EODA@ORA12CR1> ехес proc2 PL/ SQL procedure succe s s fu l l y completed . EODA@ORA12CR1> ехес runstats_p kg . r s_stop ( 9 5 0 0 ) Run 1 ran i n 3 4 cpu hsecs Run2 ran in 4 32 cpu hsecs run 1 ran i n 7 . 8 7 % of the t ime На заметку! За подробными сведениями о runs t a t s и других утилитах обращайтесь в раз­ дел "Настройка среды" в начале этой книги . Вы можете получить несколько отличающиеся значения для nроцессарного времени или л юбой другой метрики. На это влияет версия Oracle, операционная система и аппаратная платформа. Общая идея будет той же , но точ­ ные значения наверняка окажутся другим и . П редыдущий результат четко показывает, что в плане процессориого времени вставка 10 000 строк заняла значительно больше времени и ресурсов в случае без пе­ ременных привязки по сравнению с ситуацие й , когда они применялись. Фактически вставка строк без участия переменных привязки потребовала более чем на порядок больше процессориого времен и . Для каждой вставки без переменных привязки практически все время, затрачен ное на выполнение оператора, уходило просто на разбор этого оператора! Но есть кое-что похуже. Если мы просмотрим другую ин­ формацию, то обнаружим существен ное отличие в утилизации ресурсов при каждом подходе: Ра зрабо т ка усn е ш н ых n рил оже н и й Oracle Name STAT . . . CCursor + s ql area evi c STAT . . . enqueue reques t s STAT . . . enqueue releases STAT . . . execute count STAT . . . opened cursors cumulati STAT . . . taЬle s cans ( short taЬl STAT . . . sorts (memory) STAT . . . parse count ( ha r d ) LATCH . s e s s ion allocation LATCH . s e s s ion idle bit STAT . . . dЬ Ьlock gets STAT . . . dЬ Ьlock gets from cach STAT . . . dЬ Ьlock gets from cach LATCH . shared pool s imulator STAT . . . cal l s t o get snapshot s STAT . . . parse count ( tota l ) LATCH . ca l l a l l ocation LATCH . enqueue has h chains STAT . . . con s i s tent gets STAT . . . cons i s tent gets from са STAT . . . cons i s tent gets p i n ( fa STAT . . . con s i s tent gets pin STAT . . . ca l l s to kcmgcs STAT . . . s e s s ion logical reads STAT . . . recurs ive cal l s STAT . . . KT FB al loc space ( Ьlock LATCH . cache buffe rs chains LATCH . row cache obj e cts LATCH . s hared роо1 STAT . . . s e s s ion pga memory STAT . . . logical read bytes from Run 1 2 35 34 10, 020 10, 019 3 3 2 5 17 10, 447 10, 447 79 8 22 18 4 70 2 66 2 66 219 219 1 17 10, 713 10, 058 1 96 , 608 51, 835 206 2 0 , 0 90 65 , 5 3 6 8 7 , 7 60 , 8 9 6 Run2 9 , 965 10, 012 10, 012 20, 005 20, 005 10, 000 10, 000 10, 000 10, 007 10, 025 30, 376 30, 376 2 0 , 037 19, 980 20, 003 20, 005 20, 016 20, 211 40, 093 40, 093 4 0 , 0 67 4 0 , 0 67 40, 085 70, 469 70, 005 131 , 072 171 , 570 240 , 686 289, 899 - 2 62 , 1 4 4 577 , 2 82 , 0 4 8 65 Di ff 9, 963 9, 977 9 , 978 9, 985 9, 986 9, 997 9 , 997 9, 998 10, 002 10, 008 19, 929 19, 929 19, 958 19, 972 19, 981 1 9 , 987 2 0 , 0 12 20, 141 39, 827 39, 827 39, 848 39, 848 3 9 , 9 68 59, 756 59, 947 - 65 , 53 6 119, 735 240, 480 2 69 , 8 0 9 -327 , 680 4 8 9 , 52 1 , 152 Run1 l atches total versus runs - - d i f ference and pct Run1 Run2 Diff Pct 7 1 1 , 2 93 9 . 38% 784, 913 7 3 , 62 0 PL/SQL procedure s ucce s s ful l y comp1eted . Процелура PL/SQL успешно выполнена . Утилита run s t a t s генерирует отчет, которы й демонстрирует разницу в исполь­ зовании защелок, а также отличия в статистике. Здесь run s t a t s было указано на­ печатать все отличия , превышающие значение 9 500. Можно заметить, что полный разбор выполнялся 2 раза при первом подходе с применением переменных привяз­ ки и 10 000 раз при подходе без переменных привязки (по одному разу для каждой вставки). Однако разница в количестве операций разбора - лишь вершина айсберга. Здесь также видно, что в случае подхода без переменных привязки использовалось на порядок больше "защелок" , чем с переменными при вязки. Эта разни ца может породить вопрос о том, что собой представляет защелка? Давайте ответим на этот вопрос. Защелка (latch) - это тип блокировки , при­ меняемый для сериализации доступа к разделяемым структурам данных, которые находятся в глобальной системной области (System Global Area - SGA) , где Oracle хранит разобранный скомпилированн ы й SQL- кoд. При модификаци и чего-либо в 66 Глава 1 этой разделяемой структуре вы должны позаботиться о том , чтобы в каждый мо­ мент времени только одному процессу был разрешен доступ к ней. (Оче нь плохо, если два процесса или потока попытаются обновить одну и ту же структуру в памя­ ти одновременно - ее повреждение неизбежно.) П оэтому в Oracle используется ме­ ханизм защелкивания, который представляет собой облегченный метод блокировки для обеспечения последовательного доступа. П усть слово "облегченный" не вводит в заблуждение. Защелки являются устройствами сериализаци и , которые в каждый момент времени разрешают доступ к структуре данных в памяти только одному про­ цессу. Защелки , применяемые реал изацией полного разбора, я вля ются одн ими из наиболее часто используемых. Сюда входят защелки для разделяемого пула и биб­ лиотеч ного кеша. Это "долговременные" защелки , за которые часто соперничают пользователи . Все это означает, что при увеличении количества пользователей , пы­ тающихся одновременно выполнить полный разбор SQL-кoдa, с течением времени производительность будет ухудшаться в геометрической прогресси и . Чем больше пользователей вы полняет разбор, тем их большее количество ждет возможности за­ щелкнуть разделяемый пул , и тем длиннее очереди и дольше ожидание. Выполнение SQL-операторов без переменных привязки во многом подобно ком­ п иляции подпрограммы перед каждым вызовом метода. П редставьте себе, что кли­ ентам поставлен исходный код Java, который требует перед вызовом метода любого класса запускать ком пилятор Java, комп илировать класс , выполнять метод, а затем отбрасывать байт- код. Для повторного вызова этого же метода приходится пред­ прин имать те же самые действия : компилировать его, вы полнить и затем отбросить байт-код. Такой подход совершенно неприемлем в приложении, неприемлем он и в базе данн ых. Другое следствие отказа от использования перемен ных привязки для разработчи­ ков, применяющих конкатенацию строк, касается безопасности, а именно - уязви­ мости к внедрению SQL (SQL injection) . Если вы еще не знакомы с этим термином, я советую на какое-то время отвлечься от кни ги и поискать в И нтернете упоминания " SQ L injection " . П о состоян и ю на момент нап исания этой кни ги вы получите свы­ ше пяти м иллионов ссылок. П роблема внедрения SQL хорошо документирована. Н а заметку! В недрение SQL - это брешь в системе безопасности , которая возникает, ког­ да разработч и к п р и н и мает дан ные, в веденные конеч ным пользователем, объединяет их с зап росо м , затем ком п или рует и вы полняет получившийся запрос. На самом деле раз­ работчи к nрини мает от конечного пол ьзователя фрагменты SQL- кoдa , ком пилирует их и вы полняет. Такой прием потен циально позволяет конечному пользователю модифици ро­ вать SQL-onepaтop так, чтобы он делал то, что разработч и к оператора не намеревался . Это очень похоже на ситуацию, когда оставляют те рми нал с открытым сеансом SQL* Pius, который был подключен с nривилегия м и пол ьзователя SYS DBA. Тем сам ым вы приглаша­ ете кого угодно сесть и ввести л юбую команду, ском пилировать ее и затем выполнить. Последствия могут оказаться катастрофически м и . Фактически если вы не используете переменные привязки и применяете прием с конкатенацией строк, как в показаиной ранее процедуре PROC 2 , то код становится уязвимым для атак внедрением SQL и потому должен быть тщательно пересмотрен. Причем это должен сделать кто-то другой, а не разработчик, написавш ий этот код, потому что код должен быть пересмотрен критически и объекти вно. Если проверя- Ра зра ботка усn е ш ных n рил ожени й O racle 67 ющий является партнером автора кода или хуже того - другом или подчиненным, то проверка будет не столь критической, какой должна быть. К коду, разработанно­ му без использования переменных привязки , следует относиться с подозрением он должен быть скорее исключением, нежели нормой . Чтобы продемонстрировать, н асколько коварн ы м может быть внедрен и е SQL, рассмотрим следующую короткую процедуру: EODA@ ORA 1 2 CR1 > create or rep1ace procedure i n j ( p_date in date ) 2 as 1 username a1 1_us er s . username % type ; 3 с s ys_refcursor ; 4 varchar 2 ( 4 0 0 0 ) ; 1_query 5 б begin 7 1_query : = 8 se 1ect username from а 1 1 users 9 1 where created = 1 1 1 l p_date 1 1 ' 1 1 1 ; 10 11 dЬms_output . put_1 i ne ( 1_query ) ; 12 open с for 1_query; 13 14 for i i n 1 . . 5 15 1оор 16 fetch с into 1_username ; 17 exit when c% not found ; 18 1 ) ; dЬms_outpu t . put_1ine ( 1 username 1 1 ' 19 end 1оор ; 20 21 c1ose с ; 2 2 end ; 23 1 Procedure created . Процедура создана . На заметку! Этот код вы водит только максимум nять записе й . Он был разработан для вы­ nолнения в " nустой" схеме. Схема с множеством существующих табли ц может приводить к разнообразным эффектам , которые изменят результат, показанный ниже . Один из эф­ фектов может вы ражаться в том , что вы не увидите табл ицу, которую я п ытаюсь показать в примере - это может быть связано с выводом всего лишь пяти записе й . Другой эффект может проявиться как ош ибка в числе или значен и и - по причине дли нного имени таб­ лицы . Ни один из этих фактов не делает пример недействительным ; желающий похитить данные все это может обойти . Сейчас больш и н ство известных м н е разработчи ков посмотрят на этот код и скажут, что он безопасен с точки зрен ия внедрения SQL. Они обоснуют это тем , что входные данные дл я процедуры должны быть переменной Oracle типа DATE 7-байтовым двоичным форматом, представляющим век, год, месяц, день, час, м и ну­ ту и секунду. Не существует способа, которым переменная DATE могла бы изменить смысл приведеи ного оператора SQL. Как выяснилось, это очень большая ошибка. Код уязвим в отношении внедрения - модифи кац и и во время выполнения - со стороны любого, кто знает, каким образом это сделать (вполне очевидно, что та- 68 Глава 1 кие люди есть). Если выполнить процедуру так, как разработчи к "ожидает" , вот что можно увидеть: EODA@ ORA1 2 CR1> ехес inj ( s ysdate ) s e l ect * frorn а 1 1 users where created = 1 1 2 - МАR- 1 4 1 PL/ SQL procedure succe s s fu l l y cornpleted . Процедура PL/SQL успешно выполнена . П олучен н ы й результат показывает, что оператор SQL сконструирован безопас­ но - вполне ожидаемо. Тогда как можно использовать эту процедуру ненадлежа­ щим образом? Давайте представим , что вы подключили к проекту нового разра­ ботчи ка - разработч и ка-злоум ы шлен н и ка. Все разработчи ки имеют доступ для выполнения этой процедуры с целью просмотра пользователей , зарегистрирован ­ ных в базе данных сегодня, но не имеют доступа к любой другой таблице схемы, к которой принадлежит данная процедура. Они не знают, какие таблицы имеются в схеме - специалисты из команды обеспечения безопасности решили, что подход вида "безопасность через незнание" вполне эффективен , и потому решили запре­ тить всем публ и кацию имен таблиц. Таким образом, разработчи ки не знают о су­ ществовании следующей конкретной таблицы: EODA@ ORA1 2CR1> create taЬle user_pw 2 ( unarne varchar2 ( 3 0 ) prirnary key , pw varchar2 ( 3 0 ) 3 4 ); ТаЬlе created . Та блица создана . EODA@ ORA1 2CR1 > insert into user_pw 2 ( unarne , pw ) 3 values ( 1 ТКУТЕ 1 , 1 ТОР S ECRET 1 ) ; 1 row created . 1 строка создана . EODA@ORA12CR1> cornrnit ; Cornrni t cornplete . Фикса ция выполнена . Табли ца USER_PW выглядит довольно важной, но вспомните, что пользователи не знают о ее существован и и . Однако они (пользователи с минимальными привилеги­ ями) имеют доступ к процедуре I N J: EODA@ ORA1 2CR1 > create user devacct ident i fied Ьу foobar ; User created . Пользова тель создан . EODA@ ORA1 2CR1> grant create s e s s ion to devacct ; Grant s ucceeded . Выдано успешно . EODA@ ORA1 2 CR1> grant execute оп i n j to devacct ; Grant succeeded . Злоумышленник из числа разработчи ков или пользователей может просто запус­ тить следующий код: Ра зработка успе шных п р ил оже н и й Oracle 69 EODA@ORA1 2 CR1> connect devacct / fooba r ; Connected . Подключено . DEVACCT@ORA12CR1> alter s e s s ion s et nls date format = 1 " 1 1 union s e lect t narne frorn tab- - " 1 ; 2 Sess ion altered . Сеанс изменен . DEVACCT@ORA12CR1> ехес eoda . inj ( sysdate ) select usernarne frorn a l l users where c reated = 1 1 union select tnarne frorn t ab - - 1 USER PW . . . . . PL/SQL procedure succes s fu l l y cornpleted . Процедура PL/SQL успешно выполнена . В приведеи ном выше коде оператор s e l e c t выпол няет оператор (не возвраща­ ющий строк) : select use rnarne f rorn a l l users where created = 1 1 И объеди няет его с оператором: select tnarne frorn tab Взгляните на последнюю конструкцию, т. е . -- 1 • В SQL* Plus двумя дефисами , идущими подряд, обозначается комментари й ; в итоге последняя одиночная кавычка попадает в комментарий , который необходим для того, чтобы оператор был си нтак­ сически правильным. Здесь нас и нтересует NLS_DATE_ FORМAT - большинство даже не подозревает о воз­ можности включения символьных строковых литералов с типом NLS _ DATE_ FORМAT . (К сожа11ению, м ногие даже не знают, что формат даты можно изменять и без это­ го "трюка " . И м также не известна возможность изме нять сеанс (для установки NLS _DAT E_ FORМAT ) , не располагая привилегией ALTER S E S S I ON! ) Злоумы шленник здесь может воспользоваться вашим кодом для опроса таблицы, которую вы не наме­ ревались запрашивать, с применением вашего набора привилегий. П редставление сло­ варя ТАВ ограничивает его доступом к набору таблиц, которые может видеть текущая схема. Когда пользователи запускают эту процедуру, владельцем данной процедуры является текущая схема, используемая для авторизации (т.е. вы, а не пользователи ) . Теперь они могут видеть, какие таблицы находЯтся в схеме. Злоумышленн и ки видЯт таблицу USER_ PW и проявляют к ней вполне естествен н ы й и нтерес. Затем они п ыта­ ются обратиться к этой таблице: DEVACCT@ORA1 2CR1 > se lect * frorn eoda . us e r_pw ; select * frorn eoda . us e r_pw * ERROR at l i ne 1 : ORA- 0 0 9 4 2 : taЬle or view does not exist ОIIМБКА в строке 1 : ORA-00942 : та блица или представление не существует 70 Глава 1 Злоумы шле н н и к не может получить доступ к табли це непосредственно; ему не хватает привилегни S E LECT н а этой табл и це . Но не переживайте - есть и другой путь. П ользователь желает узнать о столбцах таблицы. Вот оди н способ посмотреть структуру таблицы: DEVACCT @ ORA12CR1> alter s e s s ion set 2 n l s date format = ' " ' ' union select tnarne 1 1 ' 1 ' ' 1 1 cnarne frorn col - - " ' ; S e s s ion a l t e red . Сеанс изменен . ' DEVACCT @ ORA1 2CR1> ехес eoda . in j ( s ysdate ) s e lect use rnarne frorn all users where created = ' ' union s e lect tnarne l 1 ' / ' 1 l cnarne frorn col - - ' USER PW/ PW . . . . . USER PW/UNAМE . . . . . PL/SQL p rocedure s ucce s s fu l l y cornpleted . Процелура PL/SQL успешно выполнена . Итак, теперь известны также имена столбцов. Зная имена таблиц и столбцов таб­ лиц в схеме, можно еще раз изменить NLS_DATE_FORМAT для опроса этой таблицы , а не табли ц словаря данных. Вот что злоумышленник может предпринять далее: DEVACCT @ ORA12CR1> al t er s e s s ion s et 2 n l s date forrnat = ' " ' ' union s elect unarne 1 1 ' ' 1 ' ' 1 1 pw frorn user_pw -- " ' ; S e s s ion a l t e red . Сеанс изменен . DEVACCT@ ORA12CR1> ехес eoda . i n j ( s ysdate ) s e lect use rnarne frorn a l l users where created = ' ' uni on s e lect unarne l 1 ' / ' 1 l pw frorn u s er_pw-- ' ТКУТ Е / ТО Р SECRET . . . . . PL/SQL p rocedure s ucce s s fu l l y cornpleted . Процелура PL/SQL успешно выполнена . И вот, пожалуйста - злоумышлен н и к из числа разработчи ков или пользователей теперь обладает вашей ценной информацией об и менах пользователе й и паролях. Продолжи м наши рассуждения: а что, если данный разработчи к располагает приви­ легией C REATE PROCE DURE? В полне обосновано предположить, что это так (в конце кон цов, он ведь разработчик). Мог ли он продви нуться еще дальше в рассматрива­ емом примере? Безусловно. Эта невинно выглядящая хранимая процедура, как ми­ нимум, предоставляет гарантированн ы й доступ по чтению ко всему, к чему имеет доступ схема EODA; и есл и учетная запись, эксплуатирующая такую ошибку, облада­ ет привилегией CREATE PROCEDURE, то хранимая процедура позволит злоумышлен­ н и ку выпол н ить любую команду, которую могла бы выполн ить схема EO DA! Чтобы удостовериться в этом , мы выдадим схеме привилегию CREATE PROCEDURE: DEVACCT@ORA12CR1> connect eoda / foo Connected . Подключено . Ра зрабо т ка усп еш н ых п р иложе н и й Oracle 71 EODA@ORA1 2CR1> g rant create p rocedure to devacct ; Grant succeeded . Выдано успешно . EODA@ORA 12CR1> connect devacct / fooba r ; Connected . Подключено . На заметку! В настоящем примере предполагается , что пользователю EODA была назначена роль администратора базы данных ( DBA) с конструкцией w r т н ADM I N O PT I ON . Затем мы от имени разработчика создадим функцию, которая вьщает привиле­ гии DBA. С этой функцией связаны два важных факта: она я вляется подпрограм­ мой с правами вызывающего, т.е . будет выполняться с привилегиям и , выда н н ы ­ ми запустившему ее пользователю, и она же я вляется подпрограммой с прагмой autonornous _t ransact i on, что означает создание подтранзакц и и , которая фикси­ руется или откатывается перед возвратом из подпрограмм ы , тем самы м делая воз­ можным ее вызов из SQL-кoдa. Вот эта функция: DEVACCT@ORA1 2CR1> create o r rep lace function foo 2 return va rcha r2 3 authid CURRENT USER 4 as p ragma autonomous t ransaction ; 5 6 begin 7 execute immediate 1 g rant dba to devacct 1 ; return nul l ; в 9 end ; 10 1 Function created . Функция создана . Теперь осталось л и ш ь обманом заставить E O DA (адми н истратора базы дан н ых, который может предоставить роль DBA другим пользователям) выполнить показан­ ную функцию. Учитывая то, что уже было сделано для использования дефекта внед­ рения SQL, это легко. Мы установим NLS_DATE_FORМAT , чтобы включить ссылку на нашу функцию, и выдадим пользователю EODA привилегию на ее выполнение: DEVACCT@ ORA1 2CR1 > al t er s e s s ion set 2 nls date fo rrnat = 1 " 1 1 union s elect devacct . foo from dual - - " 1 ; Sess ion alte red . Сеанс изменен . DEVACCT @ORA12CR1 > grant execute on foo to eoda ; Grant succeeded . Выдано успешно . Цель достигнута! У нас есть адми н истратор базы данных: DEVACCT@ORA12CR1> sel ect * from s e s s i on_role s ; no rows selected строки не выбраны DEVACCT @ORA12 CR1 > ехес eoda . inj ( s ysdate ) 72 Глава 1 se1ect usernarne from а 1 1 users whe re created = ' ' union se1ect devacct . foo f rom dua 1- - ' PL/SQL p rocedure s ucce s s fu 1 1 y comp1eted . Процедура PL/SQL успешно выполнена . DEVACCT@ ORA12CR1> connect devacct/ fooba r Connected . Подключено . DEVACCT@ ORA 12CR 1> s e 1ect * from s e s s ion ro1e s ; ROLE DBA SELECT CATALOG ROLE XS RESOURCE OLAP DBA 2 4 rows s e 1 e cted . 24 строки выбрано . Совет. Чтобы п росмотреть, как и е роли выд а ны другим ролям , з а п росите предста вление ROLE ROLE PRIVS. Как же защититься от этого? Нужно использовать переменные привязки, например: EODA@ORA12CR1> create or rep1ace p rocedure NOT_inj ( p_date in date } 2 as 3 1 use rnarne a1 1_users . us e rname % t ype ; с 4 sys re fcursor ; varchar2 ( 4 0 0 0 } ; 5 1_query б begin 7 1_que ry . 8 se1ect username 9 f rom а 1 1 users 10 whe re created = : х ' ; 11 12 dЬms_output . put_1ine ( 1 query } ; open с for 1_query US ING P_DATE ; 13 14 15 for i i n 1 . . 5 16 1оор 17 fetch с into 1_u s e rnarne ; 18 exi t when c%not found ; ' }; 19 dЬms_output . put_1 ine ( 1 usernarne 1 1 ' end 1оор ; 20 21 c1ose с ; 2 2 end ; 23 1 Procedure created . Процедура создана . Ра зработка успе шных п р иложени й Oracle 73 EODA@ORA1 2CR1> ехес NOT_inj ( s ysdate ) se lect use rname from a l l users whe re created = : х PL/ SQL procedure succe s s ful l y completed . Процедура PL/SQL успешно выполнена . Нал и цо простой и очевидн ы й факт: в случае применен и я переменн ых п р и вязки вы не станете жертвой внедрения SQ L. Если вы не используете переме н н ы е при вяз­ ки , то должн ы тщательно проинспектировать каждую строку кода с позици и "злого гения" (знающего абсолютно все тон кости Oracle) и оце нить воз м ожность соверше­ ния атаки на код. Есл и б ы я был уверен в том , что 99,9999% моего кода безопас н ы к атакам внедрением SQL, и пришлось бы пережи вать только об оставшихся 0 ,000 1 % (где по каким -то причи нам примене н ие переме н н ы х п р и вязки н е возможно ) , то я спал бы гораздо спокой нее, чем в ситуаци и , когда при шлось бы волноваться по по­ воду того , что все 1 00% кода беззащитны к внедрен и ю SQL. Во всяком случае , в конкретном прое кте, с описан ия которого был н ачат данн ы й раздел, пере п и с ы вание существующего кода дл я и с п ользования переме н н ых п р и ­ вязки было еди н ствен н о возмож н ы м выходом . Получ е н н ы й в резул ьтате код фун­ кцион ирует на порядок быстрее и во много раз увел и ч и вает количество параллель­ но работающих пользователей , которые с истема в состоян и и поддержи вать . К тому же код стал более безопасным - не пришлось пересматри вать всю кодовую базу на предмет возможных проблем с внедрен и е м SQ L. Однако эта безопасность досталась дорогой ценой в смысле затрат време н и и усил и й , потому что моему кли енту п р и ­ шлось п исать код систе м ы , после чего переписывать код заново. Дело н е в том , что применение перемен н ых п р и вязки трудно ил и чре вато ошибками , а в том , что они не использовал и такие перемен ные и значал ь н о , а потому в ы н ужде н ы б ыл и пере­ смотреть почти весь код и модифицировать е го. Моему кл и е н ту н е п р и шлось б ы платить эту цену, если бы разработчи ки понимали жизне нную важность переменн ых привязки с самого первого дня . Управление параллельной обработкой Управлен ие параллел ьной обработкой я вляется одной из тех областей , в кото­ рых базы дан н ы х различаются . Име н н о в этой области базы дан ных отличаются от файловой системы и друг от друга. Исключительно важно, чтобы прил оже н и е базы дан ных корректно работало в условиях п араллельного доступа , однако о необходи­ мости проверки выполнения этого требования часто забывают. Техн ологии , которые прекрасно работают, когда все происходит последовательно , н е обязател ьно будут работать хорош о , когда все п ол ьзователи делают что-то одноврем е н но. Отсутствие четкого представления о том, как механ измы управления параллельной обработкой реализованы в конкретной базе данных, при ведет к следующи м проблемам : • нарушение целостности дан н ых; • с н иже н и е скорости работы п р ил ожен и й даже при н е бол ьто м кол ич естве пользователей ; • уменьшение возможностей масштабирования для поддержки большего ч и сла пользователей . 74 Глава 1 Обратите внимание, что здесь не говорится " м ожет. . . " или " вы рискуете . . . " . Напротив - все это неизбежно произойдет п р и отсутствии соответствующей ре­ ализаци и управления параллел ьной обработкой , причем даже без вашего ведома. Отсутствие правил ьно реализованного управления параллел ьной обработкой при­ ведет к нарушению целостности базы данных, поскольку какие-то фун кции , рабо­ тающие в условиях изоля ци и , будут работать не так, как ожидалось, в ситуации с несколькими пользователям и . Приложен ие будет работать медленнее, чем должно, потому что ему придется ожидать доступа к данным. Возможность масштабирова­ ния будет утеряна из-за проблем , связанных с блокировкой и соперничеством . По мере того, как очереди для доступа к ресурсам будут удлиняться , время ожидания будет становиться все больше и больше. В качестве аналогии можно при вести пробку на пун кте взимания дорожного сбора. Если автомобили подъезжают по очереди , друг за другом, движение не стопо­ рится . Если же множество автомобилей подъезжает одновременно, начинает обра­ зовываться пробка. Более того, время ожидания увеличивается совсем не пропорци­ онально количеству автомобилей на контрольном пункте . С определенного момента значительное дополнительное время начинает тратиться на "разбирательства" между водителями, дожидающимися своей очереди , и на их обслуживание (в базе дан ных этому соответствует переключение контекста). П роблем ы паралл ельной обработки наиболее трудны для отслеживания. Эта за­ дача аналогична выполнению отладки в многопоточной программе. Программа мо­ жет нормально работать в управляемой искусствен ной среде отладчика, но оказаться совершенно неработоспособной в реальной среде . Н апример, в условиях состязаний может случиться так, что два потока одновременно изменяют одну и ту же структуру дан ных. П одобные ошибки крайне трудно отслеживать и исправлять. Если прово­ дить тестирование приложен ия только в изоляции, а затем развернуть его для десят­ ков параллельна работающих пол ьзователей , скорее всего, это приведет к проя вле­ н и ю множества скрытых проблем параллельной обработки . В следующих двух разделах будут продемонстрированы два небольших примера того, как недостаточное пон имание вопросов параллельной обработки может разру­ ш ить данные или привести к снижению производительности и масштабируемости. Реализация блокировки База данных использует блокировки (lock) для обеспечен ия того , что изменение указанного фрагмента дан ных в каждый кон кретн ы й момент времени может со­ верш ать максимум одна транзакция . По существу блокировки - это механ изм ы , которые разрешают параллельную обработку; без применения какой-либо модели блокировки для предотвращения, например, одновременных обновлен и й одной и той же строки , многопользовательски й доступ к базе данных был бы невозможным. Однако при злоупотреблении или неправильном использовании блокировки могут в действительности только мешать параллельной обработке . Если программист или сама база данн ых блокирует данные без необходимости , то меньшее число людей сможет параллельна выполнять операции. Поэтому понимание сущности блокиров­ ки и особенностей ее работы в базе дан н ых исключ ительно важно при построении масштабируемого и корректно функционирующего приложения. Очень важно также понимать, что каждая база дан ных реал изуют блокировку по-своему. В одних блокировка осушествляется на уровне страниц, в других - на Ра з работ ка у сп е ш н ых п рил оже н и й Oracle 75 уровне строк. Одни базы дан н ых распространяют блокировки с уровня строк н а уровень страниц, друтие этого не делают. В одних базах данных блокировки чте н ия применя ются , в других - нет. В некоторых базах данн ых последовательные тран ­ закции реализованы через блокирование, а в других - посредством согласован н ых по чтению представлен и й дан н ых (без блокировок) . Все эти мелкие различия могут приводить к огромным проблемам с производительностью или явным программным ошибкам, если не понимать особенностей их работы. Н иже описан ы принципы политики блокировки Oracle. • Oracle блокирует данные на уровне строк при модифи кации дан н ых. Блоки­ ровка не распространяется на уровни блока или таблицы. • Oracle никогда не блокирует данные, чтобы всего лишь прочитать их. П ростые операции чтения не помещают какие-либо блокировки на строки данных. • Процесс, записывающий данные, не блокирует процесс, которы й читает дан ­ ные. Позвольте повторить: операции чтения не блокируются операциями записи. Это фундаментальным образом отличается от м ногих других баз данных, в ко­ торых операции чтен ия блокируются операциями записи . Хотя такая характе­ ристика кажется исключительно положительной (в основном , так оно и есть), поп ытка наложения ограниче н и й целостности посредством логики приложе­ ния при недостаточном понимани и этой концепции, скорее всего, приведет к получению неправильной реализации. • П роцесс, записывающий дан ные, блокируется только в том случае, если дру­ гой процесс, выполняющий запись, уже заблокировал строку, к которой обра­ щается этот процесс. П роцесс, читающи й данные, н и когда не блокирует про­ цесс, который выполняет запись. Указанные обстоятельства должны учитываться при разверты вании приложе н ия . П р и этом необходимо осознавать, что описанная политика уни кальна для Oracle каждая база данных обладает собственными особен ностями реализации блокировки. Даже приводя все свои приложеимя к " наименьшему общему знаме н ателю SQL.?' , следует учитывать, что модели блокировки и паралл е льной обработки , используе­ мые каждым поставщиком баз данных, определяют различия в поведен и и прило­ жения. Разработч ик, которы й не понимает, каким образом база данных реал изует параллельную обработку, неизбежно столкнется с проблемами целостности дан н ых. (Это особен но часто происходит при переходе от друтой базы данн ых к Oracle и на­ оборот, а также из-за пренебрежения учета в Приложен иях отличий между механиз­ мами параллельной обработки. ) Предотвращение потерянных обновлений Один из побочных эффектов применения неблакирующего подхода Oracle состо­ ит в том, что в действительности необходимо обеспечить, чтобы во время выполне­ ния каких-либо действий сам и м разработчи ком доступ к строке предостамялся не более чем одному пользователю. Разработчик демонстрировал мне создан ную и м недавно программу резервиро­ вания ресурсов (конферен ц-залов, проекторов и т. п . ) , которая находилась в процес­ се развертывания . В этом приложении было реализовано бизнес-правило для пре­ дотвращения выделения ресурса более чем одному лицу в любой заданн ы й период 76 Глава 1 времен и . То есть приложение содержало код, которы й специально проверял , не за­ резервирован ли данн ы й временной и нтервал за другим пользователем (по крайней мере, разработчи к полагал , что это так) . Код запрашивал таблицу SCHEDULES и при отсутстви и в ней строк с резервированием, перекрывающим и нтересующий времен­ ной и нтервал , вставлял новую строку. Таким образом, в основном разработчи к имел дело с двумя таблицам и : EODA@ ORA12CR1> create taЬle resou rces 2 ( re source_narne va rchar2 ( 2 5 ) p rirnary key , othe r data va rchar2 ( 2 5 ) 3 4 ); ТаЫе created . Таблица создана . EODA@ ORA12CR1> create tаЫе s chedules 2 ( re source_narne va rchar2 ( 2 5 ) references resource s , 3 start t irne dat e , 4 end tirne date 5 ); ТаЫе created . Таблица создана . Сразу после вставки записи о бронировании помещения в таблицу SCHE DULE S , но перед фиксацией приложение выпол няло запрос: EODA@ ORA 1 2 CR1 > s e lect count ( * ) frorn s chedules 2 3 whe re resou rce narne = : resource narne and ( s ta rt_t irne < : new_end_tirne ) 4 AND ( end_t irne > : new_s tart_tirne ) 5 б 1 Все казалось простым и " пуленепробиваемым" (во всяком случае, разработчику) ; есл и результатом подсчета был О, то помещение поступало в ваше распоряжение. Если результат подсчета больше О, то помещение не может быть зарезервировано на заявлен н ы й период времен и . Выяснив, в чем состояла логика разработчика, я выполнил оче н ь простой тест, чтобы показать ему ошибку, которая должна была проявиться в процессе эксплуатации приложен ия - ошибку, которую было бы не­ вероятно трудно отследить и диагностировать. М ногие бьm и бы убеждены, что это должна быть программная ошибка базы данных. Все что я сделал - это попросил кого-то воспользоваться соседним терминалом. Оба пол ьзователя (разработчи к и второе лицо) открьmи оди н и тот же экран при­ ложения , и "на счет три " каждый из них щелкнул на кнопке выполнения и попы­ тался зарезервировать одно и то же помещение на почти перекрывающийся период времени. Обоим пользователям удалось выполнить резервирование. Логика, которая прекрасно работала в условиях изоляции, дала сбой в многопользовательской среде. В этом случае проблема частично была вызвана неблакирующими операциями чте­ н ия Oracle. Оди н из сеансов никак не блокировал другой . Оба сеанса просто запусти­ ли запрос и выполнил и действия по резервированию помещения . Оба сеанса смогли вьщать запрос для просмотра и нформации о резервировании, даже если один из них уже начал модифицировать табли цу SCHEDULES (изменение не будет видно другому сеансу вплоть до выполнения операции фиксации , ко времени которой уже слишком Ра з работка усп ешных п рил оже н и й Oracle 77 поздно). Поскольку казалось, что пользователи н и когда н е будут п ы таться изменять одну и ту же строку в табли це S C H E DU L E S , то их блокировка н е производилась и , следовательно, бизнес-правило н е могло вступить в с илу, как б ыло задумано. Это вызвало уди вл е н и е у разработч ика, нап и савшего к этому моменту н е м ало приложе н и й баз дан н ы х , т. к. е го о п ыт б ыл связан с базой дан н ы х , п оддержи ваю­ ще й блокировки чте н и й . То есть сеанс, ч итающий дан н ы е , блокировался бы сеан ­ сом , записывающим дан н ы е , а сеанс, зап и сы ваю щ и й дан н ы е , б ыл б ы заблокиро­ ван параллел ьны м чте н ием этих дан н ых. В е го м и ре одна из двух описанн ы х в ы ш е транзакци й заблокировала бы другую - или , возможно, в приложен и и воз н и кла бы взаимоблокировка. Однако в итоге транзакция все равно п отерпела бы неудачу. Таким образом , разработч и ку требовался метод п р и н удител ьного п р и м е н е н ия бизнес-правила в многопол ьзовательско й среде - способ обеспеч е н ия того , чтобы в каждый момент времени только одно лицо могло делать резервирован ие кон кретно­ го ресурса. В этом случае решение заключалось в небольшой сериализации . Кроме выполнения при веде и н ого ранее зап роса count ( * ) разработчи к сначала запускал следующий зап рос: select * from resources whe re res ource nате = : re s ource name FOR UPDATE ; Здесь производится блокирование ресурса ( помеще н и я ) , предн азнач е н ного мя резервирован и я , непосредстве н но перед е го резервирова н и е м - и н аче говоря , до запроса этого ресурса из табл и ц ы S C H E D U L E S . За счет блокирования ресурса, ко­ торый пользователь п ытается зарезервировать, разработч и к гарантирует, что н и кто другой в то же самое время не сможет изменить графи к эксплуатации этого ресур­ са. Любым пользователям, желающим выпол н ить оператор S ELECT FOR U P DATE мя данного ресурса, придется ожидать, пока не будет осушествлена ф иксация транзак­ ци и , после чего они получат возможность увидеть графи к испол ьзования ресурса. Шансы п ерекрытия граф и ков исчезал и . Разработчи к и обя з а н ы пон и мать, что в многопользовательской среде о н и должн ы иногда применять прием ы , аналоги ч н ы е испол ьзуемым при многопоточном программирован и и . В рассматр иваемо м случ ае конструкция FOR U P DAT E действует подобно семафору. Она обесп е ч и вает п оследо­ вательный доступ к кон кретной строке табли ц ы RE SOURC E S , не позволяя каки м -то двум пользователям зарезервировать ресурс одновременно. П рименение подхода FOR U P DAT E по-прежнему обеспечи вает в ысокую сте п ен ь параллелизма, т. к. потен циально могут резерви роваться тысячи ресурсов. Это тот редкий случай , когда устанавл ивается руч н ая блокировка дан н ых, которые в дейс­ твител ьности мы обновлять не собирае мся . Вы долж н ы уметь распознавать ситуа­ ции, когда необходимо блокировать вручн ую , и что вероятно еще важнее - когда этого делать не следует ( п озже будет п р и веден соответствующий п р име р ) . Более того, конструкция FOR UPDATE не блокирует чте н и е дан н ых о ресурсе другим и поль­ зователям и , как это бы вает в других базах дан ных. В результате такой подход буде т очень хорошо масштабироваться . П роблем ы , подобн ые о п и санной в этом раздел е , имеют круп н ы е последствия при переносе приложен и я из одной базы дан н ых в другую (я вернусь к этой теме далее в главе ) , время от време н и создавая разработчи кам разнообраз н ые препятс­ твия . Н апример, если вы обладаете оп ытом работы с други ми базами дан н ых, в ко­ торых процессы записи данн ых блокируют п роцессы чтен ия и наоборот, то можете привыкнуть полагаться на этот факт для предотвраще ния проблем с целостностью 78 Глава 1 данных. Отсутствие параллелизма является одни м из способов защиты от проблем подобного рода, и и менно так работают многие базы данных, отличные от Огасlе. В базе дан ных Oracle правила паралл ельной обработки обладают наивысшим при­ оритетом, и следует помнить, что это обусловливает совершенно и ное поведение приложений (в противном случае неприятные последствия неизбежн ы). Мне приходилось сталкиваться с ситуациями, когда разработчики , даже ознако­ м ившись с подобным примером, поднимали на смех идею о том, что им необходи­ мо понимать, каким образом все это работает. Они говорили : " М ы просто помечаем флажок 'транзакционное' для нашего приложения H ibernate и оно само заботится обо всем , что связано с транзакция м и ; нам незачем знать всю эту кухню". Я спра­ ш ивал их: "Так что, H ibernate будет генерировать отл ичающийся код для SQL Server, DB2 и Oracle - совершенно разный код, разное количество операторов SQL, разную логику? " . Они отвечал и - нет, но приложение будет транзакционным. Возн икала путани ца. Транзакционное в данном контексте означает просто поддержку фи кса­ ции и отката, а не то, что код транзакционно согласован (читай : что код корректен). Н езависимо от и нструме нта или платформы, используемой для доступа к базе дан­ ных, знание средств управления параллельным доступом жизненно важно, если вы не хотите повредить свои данные. На протяжен и и 99% времени блокировка совершенно прозрачна, и о ней можно не беспокоиться . Но именно оставшийся оди н процент случаев нужно уметь рас­ познавать. Для решения этой проблемы не существует какого-то простого контроль­ ного перечия типа "чтобы сделать это, необходимо выполнить то" . Все зависит от пони мания поведения приложен ия в многопользовательской среде и в базе данных. Мы рассмотри м эту тему значительно подробнее в главах, посвященных блоки­ ровани ю и управлен и ю параллельной обработкой . В них вы узнаете , что примене­ ние ограничени й целостности данных такого типа, как описанный в этом разделе, когда вы должны реализовать правило, распространяющееся на несколько строк в одной таблице или на две и более таблиц (вроде ограничения ссылочной целостнос­ ти), всегда требует особого внимания . Кроме того, в м ногопользовател ьской среде, скорее всего, придется использовать ручное блокирование или какую-то другую тех­ нологию для поддержания целостности. Многоверсионность Эта тема оче н ь тесно связана с управлением параллел измом , поскольку мно­ говерсион ность служит основой механ изма управления параллел ьной обработкой Oracle. База дан ных O racle действует на основе многоверсионной , согласованной по чтению модели параллелизма. В главе 7 мы раскроем технические аспекты этой модели более подробно, но по существу она представляет собой механизм, посредс­ твом которого Oracle обеспечивает следующие концепци и . • Согласован н ые по чте н и ю запросы . Запросы , которые создают непротиворе­ ч ивые результаты для конкретного момента времени. • Н еблакирующие запросы. Запросы н икогда не блокируются процессом , запи­ сывающим данные, как это и меет место в других базах данных. В базе данных Oracle эти две концепции очень важны. В основном термин много ­ версионность описывает способность Oracle одновременно поддерживать несколько версий данных, извлеченных из базы (начиная с версии 3.0, вышедшей в 1 983 году!) . Ра зрабо т ка усп ешн ых п р иложе н ий O racle 79 Понятие согласованность чтения отражает тот факт, что запрос в Oracle будет возвра­ щать результаты из согласованного момента времен и . Кажды й блок, используемый запросом, будет в точности соответствовать этому моменту времени, даже если дан ­ ные были модифицированы и л и блокированы, пока вьшолнялся запрос (это было действительным, начиная с версии 4.0, которая появилась еще в 1 984 году!) . Если вы понимаете, как совместно работают м ноговерсионность и согласованность чте­ ния, то всегда поймете ответы, полученные из базы дан н ых. Прежде чем приступить к более подробному рассмотрению реализации многоверсионности в Oracle, давайте ознакоми мся с ее работой на простом примере: EODA@ORA 12CR1> create taЬle t 2 as 3 se 1ect username , created 4 from all users 5 1 ТаЬlе created . Таблица создана . EODA@ORA12CR1> set autoprint off EODA@ORA12CR1> variaЬle х re fcur sor ; EODA@ORA12CR1> begin 2 open : х for se lect * from t ; 3 end; 4 1 PL/ SQL procedure s ucce s s fu l l y completed . Процедура PL/SQL успешно выполнена . EODA@ORA12CR1> decl are 2 pragma autonomous_transaction ; -- вы могли бы т а кже сдел а т ь э т о 3 -- в другом сеансе sqlplus , 4 -- и резул ь т а т был бы идентичным 5 6 begin 7 de lete from t ; 8 commi t ; 9 end; 10 1 PL/SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно выполнена . EODA@ORA1 2 CR 1 > print х USERNAМE CREATED DEVACCT OPS$MELAN I E SCOTT OPS$ TKYTE АРЕХ 0 4 0 2 0 0 АРЕХ PUBLI C USER 0 2 -S E P - 1 3 1 7 -JUL- 1 3 0 3 - JUL- 1 3 0 2 - S E P- 1 3 2 8 - JUN - 1 3 2 8 - JUN- 1 3 AUDSYS SYS 2 8 - JUN - 1 3 2 8 - JUN- 1 3 3 6 rows selected . 36 строк выбрано . 80 Глава 1 В этом примере мы создаем тестовую табли цу т и загружаем в нее данные из таб­ лицы ALL U S E R S . Затем мы открываем на этой таблице курсор. Никакие данные из курсора не извлекаются: он только открывается и остается в таком состоянии . _ На заметку! И мейте в виду, что СУБД Oracle не "отвечает предварительно" на запрос. В слу­ чае открытия курсора данные никуда не коп ируются - представьте себе, сколько времени потребовалось бы для открытия курсора в табли це , содержащей 1 м иллиард строк, если это вообще удалось бы сделать. Курсор открывается немедленно и отвечает на запрос по мере перемещения. Другим и словам и , чтение данных из таблицы выполняется только при их извлечении из курсора. Затем в этом же сеансе ( ил и , возможно, в другом - подход все равно сработал бы) мы перешли к удалению всех данных из таблицы. Мы даже выполнили фик­ сацию ( COMM I T ) этого удален и я . Строки исчезли - но так ли это на самом деле? Фактически их можно извлечь через курсор ( ил и посредством запроса FLAS HBAC K с применением конструкции AS O F ) . Дело в том , что резул ьтирующий набор, воз­ вращенный командой O P EN, был предопределен на момент его открытия. Во время открытия мы затронули не единственн ы й блок данных в этой таблице, но ответ уже был " высечен в камне" . У нас нет возможности узнать, каким будет этот ответ, до тех пор, пока не извлечем данн ы е ; однако с точки зрения нашего курсора резуль­ тат я вляется неизменным. Это не значит, что при открытии курсора Oracle копирует предыдущие дан н ые в какое-то другое место; на самом деле данные сохранила для нас команда DELET E , поместив их (начальные копи и образов строк, существующие до выполнения D E L E T E ) в область дан н ых, которая называется сегментом отмены или сегментом отката. Ретроспектива В прошлом решение о моменте времен и , когда выполняемые запросы должн ы быть согласован ными, всегда принимала СУБД Oracle. То есть СУБД Oracle делала это так, чтобы любой открытый результирующий набор был текущим относительно одного из следующих двух моментов времен и . • Момент времени, когда курсор бьut открыт . Это стандартное поведение для режима изоля ции READ COMM I T T E D (отл ичия между уровнями транзакций READ СОММ I ТТЕD, READ ONLY и S ERIAL I ZABLE рассматриваются В главе 7). • Момент времени начала транзакции, к которой относится данный запрос. Это стандартное поведение для уровней транзакци й READ ONL У и S ERIAL I ZAВLE. Тем не менее , начи ная с верси и Oracle9i, м ы получ или в свое распоряжение средство ретроспективного запроса, с помощью которого можно предложить базе данных Oracle выполнить запрос " на момент" (разумеется , с определенными разум­ ными ограничениями в отношен и и промежутка времени , на который можно воз­ вратиться в прошлое) . Таким образом, вы можете " видеть" согласованность чтения и многоверсионность еще более наглядно. На заметку! Архив ретроспекти вных данных, применяемый для обслуживания ретроспектив­ ных запросов ( отстоящих на месяцы и годы в п рошлое ) , который доступен в Oracle 1 1 g Release 1 и последующих версиях, для производства версии данных, существовавших в Ра зработка ус п е шных п рил ожени й O racle 81 базе на определенный момент времени в прошло м , не испол ьзует согласованность чте­ ния и м ноговерсион ность. Вместо этого он применяет копи и п режних образов зап исей , которые были помещены в архив . М ы возвратимся к теме архивных ретроспективных дан ­ ных в одной из последующих глав. Также обратите внимание, что архив ретроспективных данных является функциональным средством базы данных, начи ная с версии 1 1 . 2 . 0 . 4 и далее . Ранее это была возможность для базы данных, доступная за отдельную плату; те­ перь это средство для всех, используемое без дополн ительных л ицензионных затрат. Рассмотрим следующий пример. Начнем с получения значения SCN (System Change Number (номер систем ного изменения) или System Commit N u mber (номер системной фиксации ) ; эти два термина взаи мозаменяе м ы ) . Номер SCN представ­ ляет собой значен ие внутренних часов Oracle: каждый раз, когда происходит фик­ сация, показание этих часов увеличи вается ( и н крементируется) . М ожно было бы также применять дату или отметку време н и , но значение SCN я вляется легко до­ ступным и очень точным: SCOTT @ORA12CR1> variaЬle scn numЬer SCOTT @ORA 12CR 1 > е х е с : s cn : = dЬms_flashbac k . get_s ystem_change numЬe r ; PL/ SQL procedure s ucce s s fu 1 l y completed . Процедура PL/SQL успешно выполнена . SCOTT@ORA1 2CR1> print scn SCN 13646156 На заметку! В вашей системе доступ к пакету ов м s F LAS H BACK может быть огран ичен. Я выдал право на выполнение этого пакета в своей базе данных пользователю s со т т ; вы можете сделать то же самое. И мея номер SCN , мы можем потребовать от Oracle предоставить данные на мо­ мент времени , соответствующий значению SCN ; вместо SCN можно было бы указать дату и отметку времени. М ы хотим иметь возможность запросить базу данн ых Oracle позже и выяснить, что находилось в таблице в этот конкретны й момент времени. Но давайте посмотрим, какую информацию содержит таблица ЕМР прямо сейчас: SCOTT@ORA12CR1> s e lect count ( * ) from emp ; COUNT ( * ) 14 Теперь удалим всю и нформацию и удостоверимся , что она " исчезла" : SCOTT @ORA1 2CR1> delete from emp ; 1 4 rows deleted . 1 4 строк удалено . SCOTT @ORA1 2CR1> s e l ect count ( * ) from emp ; COUNT ( * ) о 82 Глава 1 SCOTT@ORA1 2 CR 1 > commi t ; Commi t complete . Фиксация выполнена . Одн ако, используя ретроспективный запрос с конструкцией AS OF SCN или AS OF T IMESTAМP , можно также потребовать от Orac\e отобразить содержимое таблицы на желаемый момент времени : SCOTT@ORA1 2CR1> select count ( * ) , 2 : s cn then_s cn , 3 dЬms_flashback . get_s ys tem_change numЬer now s cn 4 from emp as of scn : s cn ; COUNT ( * ) THEN SCN NOW SCN 14 1 3 64 6 1 5 6 1 3 64 6157 Наконец, в Orac\e \ Og и последующих версиях доступна команда f l a shba c k, ко­ торая позволяет посредством лежащей в основе технологии м ноговерсионности воз­ вращать объекты в состояние, в котором они пребывали в какой-то момент времен и в прошлом . В рассматри ваемом случае мы можем привести таблицу Е М Р к виду, ко­ торый она и мела перед удалением всей информации (в качестве части процесса нам понадобится разреш ить перемещение строк ( row movement ) , что позволит изменять назначенные идентификаторы строк (rowid) - необходимое условие для вы полне­ н ия ретроспективного отката таблицы): SCOTT@ORA1 2CR1> alter tаЫе emp еnаЫе row movement ; ТаЫе a l tered . Таблица изменена . S COTT @ORA 1 2 CR 1 > flashback tаЫе emp to scn : s cn ; Flashbac k complete . Фиксация завершена . S COTT @ORA 1 2 CR 1 > s e l ect cnt_now , cnt_the n , 2 : s cn then_s c n , 3 dЬms flashback . get_s ystem_change_numЬer now scn 4 from ( select count ( * ) cnt_now from emp ) , 5 ( s e lect count ( * ) cnt_then from emp as of s cn : scn ) б 1 CNT NOW CNT THEN THEN SCN NOW SCN 14 14 13646156 1 3 6 4 67 8 6 Вот что собой представляют согласованность чте н ия и многоверсионность. Если вы не понимаете , как работает многоверсионность Orac\e и что она подразумевает, то не сможете воспользоваться всеми преимуществами Oracle или п исать коррект­ ные приложения в Oracle (гарантирующие целостность данных). Н а заметку! Ретроспективный откат табл ицы требует наличия версии Enterprise Edition базы данных Oracle. Р азработка усп е шных п рило же н ий O rac l e 83 Согласованность чтения и неблакирующие чтения А теперь рассмотрим последствия м ноговерсионности : согласованные по чтению запросы и неблакирующие чтения. Пр и веденный н иже код может вызвать уди вле­ ние у тех, кто не знаком с м ноговерсионностью. Для п ростоты п редположим, что считы ваемая таблица содержит по одной строке для каждого блока базы дан ных (наиме ньшей еди н и цы хранения в базе дан н ых), а в этом примере выполняется полный просмотр таблицы. М ы будем запрашивать простую табли цу ACCOUNT S , которая хранит балансы банковских счетов и имеет очень простую структуру: create tаЫе accounts ( account_numЬer numЬer primary key , account balance numЬer ); В реальном приложении таблица ACCOUNTS должна была бы содержать сотни ты­ сяч строк, но для простоты мы рассмотрим таблицу с четырьмя строками , как пока­ зано в табл . 1 . 1 (в главе 7 мы проанализируем этот пример более подробно). Таблица 1 . 1 . Содержимое таблицы ACCOUNTS Номер счета (account_nwnЬer) Баланс сч ета (account_balance) 1 23 $500.00 2 234 $250 .00 3 345 $400 .00 4 456 $ 1 00.00 Строка В конце рабочего дня мы хотим получить отчет о наличии денежн ых средств в банке. Это предельно простой запрос: select sum ( account_bal ance ) from accoun t s ; Ответ в этом примере, конечно же, очевиде н : $ 1 250. Однако что произойдет, есл и мы успеш но прочитали строку 1 , а в о время чте н ия строк 2 и 3 банкомат генериру­ ет транзакции в отношении этой таблицы и переводит сумму $400 со счета 1 23 н а счет 456? Запрос обнаружит $500 в строке 4 и возвратит сумму, равную $ 1 650, не так ли? Естественно, подобного следует избегать, потому что ответ был бы ошибоч­ ным - ни в оди н из моментов времени в столбце баланса счетов такая денежная сумма не присутствует. В Orac1e описан ные ситуации не возникают благодаря согла­ сованности чтения. М етоды, испол ьзуемые в Oracle, отл ичаются от применяемых в большинстве остальных баз данных, и вы должны понимать эти отличия . В о многих других базах данн ых дл я получен ия "согласован ного" и " корректно­ го" ответа на этот запрос придется либо заблокировать целую таблицу, пока сумма вычисляется , либо заблокировать строки при их чте н и и . Это препятствует измене­ нию ответа во время его получения. Если вы заблокируете табли цу заранее, то ответ будет соответствовать состоянию базы данных на момент, когда запрос начал выпол ­ няться . Если вы будете блокировать данные по мере их считывания (метод, обычно называемый блокировкой разделяемого чтения, который предотвращает обновления , 84 Глава 1 но не препятствует доступу к данным со стороны других процессов, выполняющих чтение) , то получ ите ответ, соответствующий состоя н и ю базы данных на момент заверш е н ия запроса. Оба метода в значительной степени снижают степень парал­ лелизма. Блокировка таблицы препятствует любым обновлениям целой таблицы на протяжен и и выполнения запроса (для таблицы, состоя щей из четырех строк, этот промежуток времени оказы вается очень коротким , но для таблиц, которые содер­ жат сотни тысяч строк, он мог бы занять несколько минут) . Метод "блокировки по ходу" предотвращает обновлен ия данных, которые бьuш прочитаны и уже обработа­ н ы , и может приводить к возникновению взаимоблокировок между этим запросом и другими операциями обновления . Как уже упоми налось ранее, без полного понимания концепции м ноговерсион­ ности невозможно в полной мере воспользоваться преимуществами, предлагаемыми Oracle . Разберем одну из причин этого. М ноговерсионность в Oracle применяется для получения ответа, соответствующего моменту начала запроса, и запрос будет выполнен без блокирования чего-либо. ( П ока транзакция перевода денежн ых сумм с одного счета на другой обновляет строки 1 и 4, эти строки будут заблокированы для друrих процессов записи, но не для процессов чтения данных, таких как запрос S EL E C T S U M ) Фактически в Oracle отсутствует блокировка "разделяемого чте­ ния " (распространенный тип блокировки в друrих базах данн ых) , т. к. необходимость в ней отсутствует. Все , что снижает степень параллелизма, из Oracle было удалено. Мне на практике встречались случаи, когда отчет, созданный разработчиком, ко­ торый не понимал возможности многоверсионности Oracle , полностью блокировал всю систему. Причиной было то, что разработчи к стрем ился получить согласован­ ные по чтению (т.е. правильные) результаты запросов. В любой другой базе дан ных, с которой разработч и к имел дело, это требовало блокирования табл иц либо ис­ пользования оператора S E LE C T W I T H HOLDLOCK (механизм SQL Server, пред­ назначен н ы й для блокировки строк в разделяемом режиме по мере их считывания) . В итоге разработчи к должен был либо блокировать таблицы перед тем , как присту­ п ить к запуску построения отчета, либо применять запрос S ELECT FOR U P DATE (ближайш и й аналог W I T H HOLDLOCK) . Это при водило к практически полной оста­ новке обработки транзакций - причем совершенно неоправданно. Каким же образом СУБД Oracle получает правильн ый непротиворечи вый ответ ($ 1 250) во время чтения без блокировки каких-либо дан ных - друrими словами, без снижения степени параллелизма? Секрет кроется в используемых Oracle транзак­ ционных механизмах. При каждом изменении данн ых Oracle создает зап иси в двух разных местах (большинство друrих баз дан н ых помещают обе записи в одно место; для н их сегмент отката (undo) и журнальн ы й сегмент (redo) - просто "транзакцион­ ные дан н ые " ) . Одна запись поступает в журналы повторного выполнения , где Oracle хранит информаци ю для повторного выполнения (redo) , или " наката" (roll fotward) транзакц и и . Для операции вставки это будет вставляемая строка. Для операции уда­ ления кон цептуально это будет сообщение об удалении строки из файла Х, блока У, строкового слота Z и т.д. Еще одной записью является запись отмены (undo), по­ мещаемая в сегмент отмены. Есл и транзакция отказывает и должна быть отмене­ на, то Oracle читает образ "до того" из сегмента отмены и восстанавливает дан ные. В дополнение к применению этих данных сегмента отмены для отмены транзакций, Oracle использует их для отмены изменений в блоках данных и их восстановления в том состоя н и и , которое соответствовало моменту начала выполнения запроса . • . • . • • • • . • Ра зрабо т ка ус n ешных n р иложе н и й Oracle 85 Это позволяет производить чтение, м и нуя блокировку, и получать согласованные, правильные ответы , не блокируя какие-либо данные самостоятельно. Итак, применительно к рассматриваемому примеру, Oracle приходит к правил ь­ ному ответу, как описано в табл . 1 . 2. Та бл и ца 1 . 2 . Многоверсионность в действии Момент времени Запрос Т1 Считывает строку 1 ; на данный мо­ мент баланс = $500; сумма = $500 Обновляет строку 1 ; помещает монопольную блокировку на строку 1 , предотвращая дру­ гие обновления (но не чтени я ) . Теперь строка 1 содержит $ 1 00 Т2 тз Т4 Считывает строку 2 ; на данный мо­ мент баланс = $250; сумма = $750 Считывает строку 3; на данный мо­ мент баланс = $400; сум ма = $ 1 1 50 Обновляет строку 4; помещает монопольную блокировку на строку 4, предотвращая дру­ гие обновления (но не чтения). Теперь строка 4 содержит $500 Т5 Тб Считывает строку 4; обнаруживает, что строка 4 была изменена. В дейс­ твительности будет выполнен откат блока , чтобы его вид соответствовал моменту времени Т 1 . Из этого блока зап рос прочитает значение $ 1 00 Фиксирует транзакцию Т7 та Транза кция перевода денежных сумм с одного счета на другой П редставляет в качестве ответа значение $ 1 250 В момент времени Тб по существу Oracle выполняет " чтение через" блокировку, которую наша транзакция поместила на строку 4. Именно так реализованы небла­ кирующие чтения: Oracle только проверяет, изменил ись ли дан ных, не беспокоясь о том , заблокированы ли данные в текущий момент (что подразумевает возможность изменения данных). СУБД Oracle просто извлекает старые данные из сегмента отка­ та и переходит к следующему блоку дан н ых. Рассмотрим еще одну простую демонстрацию многоверсионности . В базе дан н ых доступно несколько версий одного и того же фрагмента информаци и для различных моментов времени. СУБД Огас!е способна испол ьзовать эти снимки данн ых, соот­ ветствующие разным моментам времен и , для выполнения согласованных по чтению запросов и неблакирующих чтений. Такое согласованное по чтению представление данных всегда создается на уров­ не SQL-oпepaтopa. Результаты любого оди ночного SQL-oпepaтopa явля ются непро- 86 Глава 1 тиворечивыми относительно момента начала его выполнения. И менно это качество делает результат выполнения оператора, подобного следующей вставке , предсказуе­ мым набором дан н ых: for х 1n ( se l ect * f rom t ) loop in s e rt into t values ( x . username , x . user_id, x . created ) ; end loop ; Результат запроса S ELECT * FROM предопределен на момент начала его выполне­ ния. Оператор S ELECT не увидит никаких новых дан ных, сгенерированных операто­ ром INS ERT . Вообразите себе, что если бы он делал это - оператор мог бы превра­ титься в бесконечный цикл. Если бы оператор S E LECT мог " видеть" новые строки , вставленные в табли цу т оператором I N S E RT , то при веденный выше код создавал бы неизвестное количество строк. Скажем , если бы в начале табли ца т имела 1 0 строк, то в кон це она могла б ы содержать 20, 2 1 , 2 3 или бесконечное число строк. Поведение было бы совершенно непредсказуемым. Согласованное чтение обеспе­ чивается для всех операторов, поэтому оператор I N S E RT вроде показанного ниже также является предсказуемым: insert into t s e lect * f rom t ; Оператор I N S E RT будет работать с согласованн ы м п о чте н и ю представлен нем табли цы т. Он не увидит строки , которые только что вставил ; вместо этого он вста­ вит только те строки , которые существовали на момент начала выполнения опера­ тора S ELECT. Определенные базы данных вообще не допускают применения рекур­ сивных операторов, подобных приведен ному, т. к. они не в состоянии определить, сколько строк нужно н а самом деле вставить. Таким образом , если вы привыкли к способу поддержания целостности и парал­ лел изма запросов, принятому в других базах данных, или вам н икогда не приходи­ лось и меть дело с таким и кон цепциями ( например, из-за полного отсутствия опыта использования баз данн ых), то теперь важность понимания их работы должна быть ясна. Чтобы максимально задействовать потенциал Orac1e и реализовать корректно функционирующий код, необходимо хорошо понимать реал изацию этих концепций именно в Orac1e, а не в других базах дан н ых. Нужна ли независимость от базы данных ? К настоящему моменту вы уже можете догадаться , о чем пойдет речь в этом раз­ деле. Я ссылался на другие базы дан н ых и на то, что в каждой из них фун кциональ­ ные средства реализованы по-своему. Я убежден , что за исключен ием некоторых приложе н и й , предназначенн ых только для чтения данн ых, построение полностью независимого от базы данных и при этом хорошо масштабируемого приложен ия исключительно трудная задача. Фактически это почти невозможно, если только не знать совершенно точно, каким образом работает каждая база дан ных. А если вы очен ь хорошо знаете , как именно работает каждая база дан н ых, то должны пони­ мать, что независимость от базы дан н ых - вовсе не то, к чему следует действитель­ но стремиться . В целях иллюстрации вернемся к ранее рассмотренному примеру резервирован ия ресурсов (до добавления конструкци и FOR U P DAT E ) . П редположим , что это прило- Ра зрабо т ка усп ешн ых п рило же н и й Oracle 87 жение было разработано в базе данных, модель блокировкиjпараллелизма в которой совершенно отл ичается от модели , принятой в Oracle . Я собираюсь показать, что при переносе приложен ия из одной базы данных в друrую придется удостовериться в том , что она продолжает правильно работать в этих разных средах, и существенно его измен ить! Пусть первоначал ьное приложение резервирования ресурсов было развернуто в базе дан ных, в которой применяются блокирующие чтен ия (т. е . процессы чтения блокируются процессам и зап и с и ) . Учтем также , что бизнес-правило было реали ­ зовано с помощью три ггера базы данных (после выполнения операции I N S ERT , н о перед фиксацией транзакции необходимо убедиться , что табл и ца содержит только одну строку, соответствующую дан ному временному п ромежутку). В системе с бло­ кирующими чтениями из-за наличия недавно вставлен н ых данных справедл и во от­ метить, что операции вставки в эту табли цу должн ы выполняться последовательно. Первый пользователь вставил бы свой запрос на резервирование " помеще н ия N' с 1 4:00 до 1 5 :00 в пятницу, а затем выпол н ил запрос для выявления возможных накла­ док. Если бы следующий пользователь попытался вставить запрос, пересекающийся с первым, то во время просмотра на предмет нал ичия накладок этот запрос оказался бы заблокированным (ожидая , пока недавно вставленные дан ные станут доступны­ ми для чтения ) . Вполне очевидно, что в такой базе данн ых с блокирующими чте ни­ ям и наше приложение должно работать успешно, хотя легко могла б ы возникнуть взаимоблокировка (эта кон це пция раскрывается в главе 6), если бы мы одновремен­ но вставляли строки и затем пытались читать дан ные друг друга. П роверка наличия перекры вающихся интервалов для выделенных ресурсов будет вы полняться после­ довательно - и никогда параллельно. Если мы перенесем это приложение в Oracle и просто предположим, что оно бу­ дет вести себя аналогичным образом, то испытаем немалое потрясение. Окажется , что в среде Oracle, в которой производится блокировка на уровне строк и обеспе­ чи ваются неблакирующие чтения, приложение ведет себя некорректно. Как мы уже выясн ил и , для обеспечения последовательного доступа необходимо испол ьзовать конструкци ю FOR U P DAT E . Без этой конструкции два пользователя могли бы заре­ зервировать один ресурс на то же самое время . Это прямое следствие непони мания особенностей работы применяемой базы данн ых в м ногопользовательской среде . С подобного рода проблемами мне приходилось м ногократно встречаться при пе­ реносе приложения из базы данных А в базу данн ых Б . Когда приложение, которое безошибочно функционировало в базе данных А, не работает или работает странно в базе данных Б , прежде всего, первой приходит мысль об "ущербности " базы дан­ ных Б. И стинная правда заключается в том , что база данных Б всего л иш ь работает по-другому. Н и одна из этих баз данных не является неправильной или " ущербной" ; они просто различн ы . Знание и четкое понимание особен ностей функционирова­ ния каждой из них чрезвычайно помогает в решении таких проблем. П еренос при­ ложе ния из Oracle в SQL Server делает актуальны м и вопросы блокирующих чте н и й и взаимоблокировки - иначе говоря , проблемы возникают в обоих направлениях. Например, как-то ко мне обратились за помощью в преобразовании кода Transact­ SQL (язык хран имых процедур, разработанн ы й для S Q L Server) в код P L/SQL. Разработчик, занимающийся преобразованием, жаловался , что в среде Oracle запро­ сы SQL возвращали "ошибочные" ответы . Запросы выглядели следующим образом: 88 Глава 1 dec1are 1 s ome va riaЬle va rchar2 ( 2 5 ) ; begin i f ( some condi t i on ) then 1 some variaЬle : = f ( . . . ) ; end i f ; _ for х i n ( select * f rom Т where х = 1 s ome va riaЬle loop Цель здесь состояла в нахожде н и и в табли це т всех строк, в которых значен ие х было равно NULL при несобл юдении определенного условия или конкретному зна­ чению, если это условие бьmо соблюдено. Разработчи к утверждал , что в Oracle этот запрос не возвращал никаких данных, если переменная L _ S OME _VARIABLE не бьmа установлена в кон кретное значение (когда она оставалась равной N U L L ) . В Sybase или SQL Server все было в поряд­ ке - запрос н аходил строки , в которых значение переменной х было равно NULL. П одобная ситуация встречалась мне практически во всех переносах приложений из Sybase или SQL Server в Oracle. Язык SQL рассчитан на работу в контексте трехзнач­ ной логики , а в Oracle сравнения с NULL реализованы в соответствии с требования­ м и стандарта AN S I SQL (где NULL обозначает состояние неизвестной величины и не значение ) . Согласно этим правилам результат сравнения х с NULL будет ни истин­ ным, н и ложным - о н в действительности я вляется неизвестным. Это утверждение иллюстрирует следующий фрагмент кода: EODA@ORA12CR1> s e 1 ect * from dua l where nul l=nul l ; no rows selected строки не выбраны EODA@ORA1 2 CR 1 > s e l ect * from dual where nul l <> nul l ; n o rows selected строки не выбраны EODA@ORA 1 2 CR 1 > s e l ect * from dual where nul l i s nul l ; D х Поначалу этот фрагмент может показаться запутанны м . Он доказы вает, что в Oracle значение NULL не является ни равны м , ни не равным NULL. В SQL Server по умолчанию ситуация совершенно иная : в SQL Server и в Sybase значение NULL равно NULL (так принято по умолчанию; в текущих выпусках SQL Server стандартное пове­ дение может быть изменено, чтобы отразить стандарт AN S I ) . Нельзя считать, что в упомянутых базах данных обработка выполняется неправильно - она просто отлича­ ется. В действительности все эти базы данных совместим ы с AN SI (совместимость с AN S I отнюдь не означает стопроцентную поддержку стандарта; за деталями обращай­ тесь в раздел " Влияние стандартов" далее в главе) , но все же они функционируют по­ разному. Существуют неоднозначности , проблемы обратной совместимости и другие сложности, которые приходится преодолевать. Н апример, SQL Server поддерживает Ра з работ ка усnешн ых n р ил ожени й Oracle 89 АNSI-метод сравнения с NULL, но не по умолчанию (иначе нарушилась бы работа ты­ сяч унаследованных приложений, построенных на основе этой базы данных). В рассматриваемом случае одно из возможных решений проблем ы предусматри­ вает написание такого запроса: se1ect * from t whe re ( х = 1_s ome_va riaЬle OR ( х is nu1 1 and 1 s ome_va r i aЬle is NULL )) Однако это приводит к другой проблеме. В SQL Server такой запрос использовал бы индекс на х. В Oracle это может быть не так, поскольку и ндекс со структурой В-дерева вообще не будет индексировать запись NULL (технологии индексации опи­ саны в главе 1 1 ) Следовательно, если требуется искать значения NULL, то индексы со структурой В-дерева не особенно полезны . . Н а заметку! До тех пор пока хотя б ы оди н столбец индекса со структурой В-дерева опре­ делен как NOT NULL, все строки табл и цы будут в действительности присутствовать в ин­ дексе , так что предикат х is nu1 1 в whe r e при извлечении строк может - и будет ­ использовать индекс. В этом случае для миним изации влиян ия на код мы приеваили х значение, ко­ торое в реальности никогда не может встретиться . Здесь по определению значение х было положительным числом, поэтому м ы выбрали число - 1 . Таким образом, за­ прос приобрел следующий вид: se1ect * from t whe re nvl ( x , - 1 ) = nv1 ( 1_s ome_va r i aЬl e , - 1 ) Вдобавок мы создали индекс на основе функции: create index t_idx on t ( nvl ( x , - 1 ) ) ; За счет внесения м инимальных изменений мы добились того же самого конеч­ ного результата. Н иже перечислен ы важные выводы , которые должны быть сделаны на основе этого примера. • Базы данных отличаются друг от друга. Опыт работы с одной из них частично применим в другой , но при этом необходимо быть готовым к ряду как фунда­ ментальных, так и совсем мелких различи й . • Н езначительные отличия (вроде обработки значен и й NULL) могут оказывать столь же крупное влияние, как и фундаментальные отл ичия (такие как меха­ низмы управления параллельной обработкой) . • Единственным способом предотвращения таких проблем является знание базы данных, особенностей ее работы и реализации функциональных возможностей . Разработчики часто (обычно несколько раз в день) меня спрашивают, как сделать в базе данных специфичную работу, например, создать времен ную табли цу в храни­ мой процедуре. Я никогда не даю прямого ответа на подобные вопросы . Вместо это­ го я задаю встречный вопрос: почему вы хотите сделать это? В ответ я часто слышу: в SQL Server мы создавали временные таблицы в хранимых процедурах, и нам нуж­ но делать это в Oracle. Н ечто подобное я и ожидал услышать. В таких ситуациях мой 90 Глава 1 ответ прост: вам не нужно создавать временные таблицы в хран имых процедурах вы только думаете , что должны это делать. И действительно, создание таких таблиц в Oracle - очен ь неудачная затея . Если вы создадите таблицы в хранимой процедуре Oracle , то обнаружите следующие моменты . • Выполнение D D L-кoдa снижает возможности масштабирования . • Постоян ное выполнение DDL-кoдa сн ижает скорость работы . • Выполнение D D L-кoдa при водит к фиксаци и транзакции. • Для доступа к таким табли цам во всех хранимых процедурах придется исполь­ зовать динамически й , а не статический SQL-кoд (из-за того, что эти таблицы на этапе компиляции не существуют). • Динамически й SQL-кoд в PL/SQ L выполняется медленнее и оптимизирован в меньшей степени , чем статически й SQL-кoд. Итог всего сказанного состоит в том, что вовсе не обязательно поступать в точ­ ности так, как в SQL Server (если временная таблица вообще необходима в Oracle). Все задачи должны решаться наиболее эффективным способом , принятым в Oracle . Точно так же при переносе приложения из Oracle в SQL Server не следует создавать для всех пользователей единственную таблицу для совместного использования вре­ менных данных ( как делается в Oracle ) . Это ограничило бы масштабируемость и па­ раллелизм в S Q L Server. Все базы данных отличаются друг от друга. Речь не идет о том , что применять временные таблицы в Oracle невозможно. Вы можете и , скорее всего, будете использовать их. П росто вы будете применять их в Oracle не так, как в SQL Server (и наоборот). Влияние стандартов Раз уж все базы дан ных совместимы со стандартом SQL99, то они должны быть оди наковы м и . Во всяком случае, так часто полагают. В этом разделе я собираюсь развеять этот миф. SQ L99 - это стандарт баз данных, при нятый AN S ijiSO. Он был н аследн иком ANS I/I SO-cтaндapтa S Q L92, которы й , в свою, очередь, заменил собой AN S I/I SO­ cтaндapт SQL89. В настоящее время сам S Q L99 вытесняется обновлен иями стан­ дартов SQL2003 , SQL2008 и SQL20 1 1 . Стандарт определяет язы к (SQL) и поведение (транзакци и , уровни изоляции и т.д. ) базы дан н ых. Известно ли вам , что многие коммерческие базы дан н ых совместимы с SQL99 хотя бы до определенной степени? А знаете л и вы, что это обстоятельство означает оче н ь мало, когда речь заходит о переносимости запросов и приложений? Н ач иная с SQL92, стандарты определяют четыре уровня совмести мости . • Начальный уровень. Совместимость на этом уровне обеспечивают большинс­ тво поставщи ков баз дан н ы х. Он я вляется незнач ительным расширением предшествующего стандарта SQL89. Н и один из поставщиков баз дан ных не был сертифицирован на более высоком уровне. Более того , в действитель­ ности Н ациональный институт стандартов и технологий (National I nstitute of Standards and Technology - N I ST) , которы й обычно зани мается выдачей сер­ тификатов совместимости с SQL, вообще не сертифицирует совместимость на более высоких уровнях. Я был членом групп ы , которая в 1 993 году получила у Ра з работка усnе шных n р иложе н и й Oracle 91 N I ST сертифи кат совместимости с SQL92 на начальном уровне Д11Я Oracle 7 . 0 . Набор функциональных средств базы данн ых, совместимых с о стандартом на начальном уровне - это подмножество возможностей Oracle 7.0. • Переходный уровень. По объему набора функциональных средств этот уровен ь находится приблизительно посередине между н ачальным и промежуточн ы м уровнями. • Промежуточный уровень. Этот уровен ь включает многие дополнительные воз­ можности , в том числе (но не ограничиваясь ими): • динамический SQL; • каскадное удаление для обеспечен ия ссылочной целостности; • типы данных DATE и T IME; • области; • символьные строки перемен ной длины; • выражение CAS E; • функци и приведен ия Д11Я преобразований между ти пам и данных. • Уровень полной совместимости . Обеспечи вает поддержку перечислен н ы х ниже возможностей ( как и в предыдущем случае, список далеко не полон) : • управление подключе н иями ; • строкавый т и п данных BI T; • отклады ваемые ограничения целостности ; • производн ые таблицы в конструкци и FROM; • подзапросы в конструкциях проверочного ограничения целостности ; • временные таблицы. Стандарт совместимости начального уровня не включает такие фун кциональные особенности, как внешние соединения, новый синтаксис внутрен него соединения и т.п . Переходн ый урове н ь определяет си нтаксис внешних и внутре н н и х соеди н е ни й . Набор средств промежуточного уровня еще шире, а уровен ь полной совместимости , естественно, включает все, что определено в стандарте SQL92. В большинстве кни г, посвященных SQL92, различия между уровням и совместимости н и как не описаны , что создает путаницу. В этих кни гах демонстрируется , каким образом выглядела бы теоретическая реализация базы данн ых, полностью совместимая со стандартом SQL92. В резул ьтате не возможно взять какую-то кн и гу по SQL92 и применить из­ ложенный в ней материал к сколько-нибудь реальной базе дан н ых, совместимой с SQL92. Это обусловлено тем , что стандарт определяет не сли ш ком много функ­ циональных средств на начальном уровне , а испол ьзование любых средств проме­ жуточного или более высокого уровня увеличивает риск невозможности переноса приложения. Стандарт SQL99 определяет только два уровня совместимости : основной и рас­ ширенный. При разработке этого стандарта была предпринята попытка выхода да­ леко за рамки традиционного SQL и в нем были введен ы объектно-реляционные конструкции (массивы , коллекции и т.д. ) . Стандарт охватывает тип ММ (мультиме­ диа) SQL, объектно-реляционные типы и т. п . 92 Глава 1 Н и оди н поставщик не подтверждает сертификатом "совместимость" своих баз дан н ых со стандартом SQL99 на основном или расширенном уровне. Более того, я не знаю н и одного поставщика, которы й заявлял бы, что его продукт полностью совместим со стандартом на любом из упомянутых уровней. В ы не должн ы бояться применять специфич ные для поставщика функциональ­ ные средства - в кон це кон цов, вы заплатили за них немалые деньги . Каждая база данных обладает собствен н ы м набором ловких приемов и в каждой из них всегда можно найти способ выполнения требуемой операции . П оэтому используйте то, что лучше всего подходит для текущей базы данных, а при переходе на другие базы дан ­ н ых заново реализуйте соответствующие компоненты . Дr:Iя минимизации объема та­ ких изменений приме няйте подходящие технологи программирования. Те же самые приемы используются при написани и приложений, переносимых между операцион­ ными системами ; к примеру, их применяют разработчи ки ядра Oracle . Удостоверьтесь , что можете адаптироваться Целью должно быть полноценное использование доступ н ых средств, но убеди­ тесь, что можете изменять реал изаци ю от случая к случаю. В качестве аналоги и : Oracle является переносимым приложением, которое фун кционирует под управле­ н ие м м ногочисленных операционных систем. Тем не менее , в среде Windows база дан н ых Oracle работает в стиле Windows: применяет потоки и другие особенности , характерные для Windows. В проти воположность этому под управлением U N IX/ Linux база данных Огас!е запускается как сервер с множеством процессов, исполь­ зуя отдельные процессы для выполнения тех действий, для которых в Windows за­ действуются потоки - т.е. работает в стиле U N I X/Linux. Функциональность "ядра Oracle" доступна на обеих платформах, но внутренне она реализована совершенно по-разному. То же самое относится к приложе н ия м баз дан ных, которые должны вы полняться в средах нескольких СУБД. Н апример, распространенной функцией многих приложе н и й баз дан ных явля­ ется генерация ун и кального ключа для каждой строки . Когда вы вставляете стро­ ку, система должна автоматически сгенерировать ключ. Для этого в Oracle реали­ зован объект базы дан н ых, которы й называется S EQ U E N C E , кроме того, функция S Y S _GU I D ( ) также предоставляет уни кальные ключи . В l nformix имеется тип дан­ ных SERIAL, а в Sybase и SQL Serveг - тип I DENT I T Y . В каждой базе данных сущес­ твует какой-то способ решения этой задачи . Однако конкретные методы различают­ ся как способом выполнения , так и возможным результатом . Таким образом, перед хорошо осведомленным разработчи ком открываются две возможности : • разработка полностью н езависимого от базы данных метода генерации уни ­ кального ключа; • согласование отличающихся реал изаций и применение разн ых приемов при реализаци и ключей в каждой базе данных. На заметку! Теперь в Oracle также и м еется тип I DENT I TY , начиная с верси и Oracle 1 2с. В нутренне он создает последовательность и по умолчанию присваивает очередное зна­ чение столбцу, что по поведению очень похоже на тип I DENT I T Y в SQL Server. Ра зрабо т ка усn ешн ых n рил ожени й Oracle 93 Теоретическое преимущества первого подхода закл ючается в том , что для пе­ рехода от одной базы дан ных к другой ничего изменять не придется . Я назвал это преимущества "теоретическим " , поскольку недостаток такой реал изации настолько значителен , что делает все решение совершенно непригодным. Чтобы разработать полностью независимый от базы данн ы х процесс , пришлось бы создать табли цу вроде приведеиной ниже : EODA@ORA1 2CR1> create tаЫе id tаЫе 2 ( id_name va rchar2 ( 3 0 ) prima ry key 3 id va 1ue numЬer ) ; ТаЫе created . Таблица создана . 1 EODA@ORA12 CR1 > insert into id tаЫе va lues 1 row created . 1 строка создана . ' МУ_КЕУ ' 1 О ); EODA@ORA12CR1> commi t ; Commi t complete . Фиксация завершена . Затем для получения нового ключа лонадобилось бы вы пол н ить следующий код: EODA@ORA 1 2 CR 1> update id_taЫe 2 set id value = id val u e + 1 3 whe re id name = ' МУ_КЕУ ' ; 1 row updated . 1 строка обновлена . EODA@ORA1 2 CR1> sel ect id value from id tаЫе 2 3 where id name = ' МУ КЕУ ' ; I D VALUE 1 Все выглядит достаточно просто, но при водит к перечисленным далее последс­ твия м . • В каждый момент времен и обрабатывать строку транзакци и может только один пол ьзовател ь. Указан ную строку необходимо обновить, чтобы и н кре­ ментировать значение счетчика, а это вынудит программу выпол нять опера­ цию последовательно. В лучшем случае генерировать новое значен ие для этого ключа одновременно сможет только оди н пользователь. • В Oracle (и это поведение в других базах данных может отличаться) все поль­ зователи кроме первого, которые попытаются параллельна выполнить эту опе­ рацию при уровне ИЗОЛЯЦИИ S E RIAL I ZABLE, ДОЛЖ Н Ы будут получ ить ошибку "ORA-08 1 77: can't serialize access for this transaction" ( " ORA-08 1 77: невозможно обеспечить последовательный доступ для выполнения этой транзакции " ) . Например, использование последовательных транзакций (что более распростра­ нено в среде J2EE, где м ногие инструменты автоматически применяют этот режим изоляции как стандартный, часто без ведома разработчиков) обусловило бы н ижес­ ледующее поведение. 94 Глава 1 Обратите внимание, что приглашение командной строки SQL содержит информацию о том, какой сеанс активен в данном примере: ops $ t kyte s e s s ion ( 4 1 9 , 2 6 9 ) > s et transaction i s olation leve l seriali zaЬle ; Transaction s e t . Режим транзакций установлен . ops $ t kyte s e s s i on ( 4 1 9 , 2 6 9 ) > update id taЬl e 2 s e t id value = id value+ 1 3 where i d narne = 1 МУ КЕУ 1 ; 1 row updated . 1 строка обновлена . ops $ t kyte s e s s ion ( 4 1 9 , 2 6 9 ) > s e l ect id value frorn id table 2 3 where id narne = 1 МУ КЕУ 1 ; I D VALUE 7 Теперь м ы перейдем в другой сеанс SQL* Plus и выполним ту же самую операцию - параллельн ы й запрос уни кального идентификатора: ops $ t kyte s e s s i on ( 6 , 4 7 9 ) > s et transaction i s olat ion l eve l seri a l i z able ; Transact i on set . Режим транзакций установлен . ops $ t kyte s e s s i on ( 6 , 4 7 9 ) > update id table 2 s e t i d va lue = id val ue + l 3 whe re id narne = 1 МУ КЕУ 1 ; - - Этот запрос будет заблокирован , поскольку в каждый дан ный момент времени только одна транзакция может обновлять строку. Приведенный пример демонстри­ рует первый возможны й результат - блокирование и ожидание строки . Н о посколь­ ку в Oracle мы используем режим S ERIALI ZABLE, при фиксации транзакции перво­ го сеанса будем наблюдать следующее поведение: ops $ t kyte s e s s ion ( 4 1 9 , 2 6 9 ) > cornrnit ; Cornrnit cornplete . Фиксация зав ершена . Второй сеанс немедленно отобразит сообщение об ошибке: ops $ t kyte s e s s i on ( 6 , 4 7 9 ) > upda te i d table 2 s e t i d va lue = id value + l 1 МУ КЕУ 1 ; 3 whe re id narne update id_tabl e * ERROR at l ine 1 : ORA- 0 8 1 7 7 : can 1 t s e r i a l i ze acce s s for t h i s transaction ОШИБКА В С Т РОКЕ 1 : ORA- 08 1 7 7 : невозможно обеспечить по следова тельный доступ для выполнения этой транзакции Продемонстрированная ош ибка возн и кает независимо от порядка следования оператора фиксации . Все , что для этого необходимо сделать внутри транзакции попытаться модифицировать любую запись, которая была изменена каким-то дру­ гим сеансом после того, как транзакция началась. Ра зрабо т ка усn ешных n рил ожен и й Oracle 95 Таким образом, приведе н н ы й фрагмент кода, независимого от базы данных, в действительности таковым не является . В зависимости от применяемого уровня изоляции он может ненадежно выпол няться даже в какой-то одной базе данн ых! И ногда возн икает блокировка с ожиданием, а иногда и ошибка. Не стоит и гово­ рить, что в любом случае (длительное ожидание или длительное ожидание с получе­ нием в итоге сообшения об ошибке) конечн ы й пользователь будет недоволен . Проблема усугубляется тем , что в реальной ситуации транзакция значительно сложнее . Операторы U P DATE и S ELECT , приведеиные в примере - ли ш ь два из мно­ жества тех, которые могут входить в состав транзакции . Мы должн ы е ще вставить в таблицу строку с только что сгенерированн ым ключом и выполнить любую другую работу, требуемую для завершения этой транзакци и . Такое последовательное вы­ полнение операций будет фактором , которы й всерьез ограничит масштабирование. Подумайте о последствиях использован ия этой технологии на веб-сайтах, обраба­ тывающих заказы , и ее применения для генерации номеров заказов . П араллельная работа множества пользователей оказалась бы невозможной , так что пришлось бы выполнять все действия последовательно. Правил ьн ы й подход к решению этой проблемы заключается в испол ьзовани и кода, который наилучшим образом подходит для каждой базы данн ых . В Oracle 1 2с это будет следующий код ( предполагая , что генерируемый первичный ключ необхо­ дим таблице т): EODA@ORA12CR1> create sequence s ; Sequence created . Последова тельность создана . EODA@ORA12CR1> create taЬle t numЬer 2 ( х 3 de fault s . nextva l 4 constraint t_p k prirnary key , other_data va rchar2 ( 2 0 ) 5 б ) 7 1 ТаЬlе created . Таблица создана . В качестве альтернативы можно было бы применить атрибут I DENT I T Y и пропус­ тить генерацию последовательности : EODA@ORA12CR1> create taЬle t numЬer 2 ( х 3 generated as identity 4 constraint t_p k prirnary ke y , other_data va rchar2 ( 2 0 ) 5 б ) 7 1 ТаЬlе created . Таблица создана . На заметку! Столбец I DENT I TY должен иметь числовой тип данных. 96 Глава 1 Но обратите вниман ие , что генерация последовательности на самом деле не про­ пускается - последовательность генерируется автоматически базой дан ных. В ран­ них выпусках Oracle ( l lg и предшествующих версиях) для получения автоматически сгенерированного суррогатного первичного ключа обычно использовался следую­ щий код: EODA@ORA12CR1> create taЬle t 2 ( p k numЬer primary key , other_data varchar2 ( 2 0 ) 3 4 ) 5 1 ТаЬl е created . Та блица создана . EODA@ORA12CR1> create sequence t_s eq ; Sequence created . Последова тельность создана . EODA@ORA12CR1> create t r igger t before insert on t 2 for each row 3 begin : new . pk : = t_seq . nextva l ; 4 5 end ; 6 1 T rigger created . Триггер создан . На заметку! В в ы пусках, предшествующих Oracle 1 1 g, вместо присваивания необходимо было применять оператор S E LECT Т_S EQ . NEXTVAL I NTO : NEW . РК FROM DUAL ; . П рямое п рисваивание последовательности в PL/SOL является новой возможностью версии 1 1 g. В результате уни кальный кл юч будет автоматически - и прозрачно - присваи­ ваться каждой вставленной строке . Ориентированный на достижение более высокой производительности подход в Огас!е l lg и предшествующих версиях был бы прос­ тым : i n s e r t i n t o t ( p k , . . . ) va lues ( t_seq . NEXTVAL , . . . ) ; То есть м ы полностью избавляемся от накладных расходов, связанных с тригге­ ром (именно этому подходу я отдаю предпочтение). Того же самого эффекта можно достичь и в других базах данных, используя их тип ы . Синтаксис CREAT E TABLE бу­ дет отл ичаться , но общий результат останется таким же . Здесь мы воепользавались возможностью каждой базы дан н ых по генерации неблакирующего и обладающего высокой степенью параллелизма ун и кального ключа, причем не внесли никаких су­ ществен н ых изменен и й в код приложения - в этом случае вся логика содержится в D D L- кoдe . Уровневое программирование Теперь, когда вы понимаете , что каждая база данных будет реализовывать функ­ циональные средства по-разному, в качестве е ще одного примера безопасного про­ грамм и рования, направленного н а обеспечен и е переносимости , можно при вести уровневую организацию доступа к базе данных, когда это необходимо. Ра зрабо т ка усп ешных п рил ожени й Oracle 97 Давайте предположим, что вы программируете с применением J D BC. Если нуж­ но выполнять только тради ционные операции S ELECT, I N S ERT, U P DAT E И DELE T E , то, скорее всего, уровень абстракции не понадобится . В этом случае SQL-кoд вполне можно встраивать непосредственно в приложение, по крайней мере, если используе­ мые конструкции ограничены лишь теми , которые поддерживаются каждой целевой базой данных - и, конечно, если вся обработка выполняется оди наково (вспомните обсуждение NULL=NULL ) . Однако это означает, что вы будете располагать неэффек­ тивным SQL-кодом . К тому же вам определенн о п ридется обладать большим объ­ емом знаний о многих базах данн ых, чем большинство их тех, кого я знаю (в конце концов, это единственный способ узнать, есть ли у какого-нибудь кода шанс рабо­ тать одинаково во всех базах данных!). Еще один подход, обеспечи вающий как более высокую переносимость, так и более высокую производительность, предусматривает применение хранимых процедур для возврата резул ьтирующих наборов. Вы обнару­ жите, что база данных каждого поставщика может возвращать результирующие на­ боры из хранимых процедур, но способы их возврата отличаются . Действительный исходный код храни м ых процедур, которы й вам придется писать, будет вы глядеть по-другому для разных баз данных. У вас есть два варианта - отказаться от испол ьзования храни м ых процедур для возвращения результирующих наборов , либо реал изовать отличающий ся код для разных баз данных. Я предпочитаю следовать подходу с написан ием разного кода и интенсивно применять хранимые процедуры . На первый взгляд кажется , что при таком подходе реализация приложен ия в другой базе данн ых потребует большего времени. Однако вы убедитесь, что этот подход в действительности облегчает реа­ лизацию дЛЯ нескольких СУБД. Вместо того чтобы искать идеальн ый SQL-кoд, ко­ торый работает во всех базах данных (возможно, в одних лучше, в других хуже) , мы реализуем SQL-кoд, который наиболее эффективно функционирует в конкретной СУБД. Это можно делать вне самого п риложения, что обеспечит допол нительную гибкость в настройке приложения. Вы можете исправить плохо вьшолняющийся за­ прос в базе дан ных и развернуть и справление немедлен но , без необходимости во внесении корректировок в приложение. Кроме того, этот метод позволяет свобод­ но применять расширения SQL, предоставляемые поставщиком. Н апример, Oracle поддерживает широкое разнообразие расширений SQL, среди которых анал итичес­ кие функции , SQ L-конструкция MODEL, сопоставление строк по шаблонам и м ногие другие. В Oracle можно свободно использовать эти расширения SQ L, поскольку они действуют " вне" приложен ия (т. е . скрыты в базе данн ых) . Для достижения анало­ гичных целей в других базах данных, скорее всего, п ридется применять какие-то другие средства, предлагаемые этим и СУБД. Вы заплатили за эти возможности, так что вполне можете ими пользоваться. Еще оди н аргумент в пользу п одхода с разработкой специализированн ого кода для базы данных, в которой он будет развертываться , связан с тем, что практически невозможно найти одного разработчи ка (о команде не стоит даже упоминать) , до­ статочно профессионального для того, чтобы понимать все нюансы отличий между Oracle, SQL SeiVer и DB2 (давайте ограничимся всего тремя СУБД) . В течение пос­ ледних 20 лет мне приходилось работать, в основном, с базой данных Oracle (прав­ да, не только с ней). И ежедневно я узнавал о ней что-то новое. Весьма сомнитель­ но, что я мог бы выступать в качестве эксперта одновременно по трем упомянутым СУБД и понимать как отличия между всем и н и м и , так и влияние этих отличий на 98 Глава 1 уровен ь "обобщенного кода" , которы й пришлось бы разрабаты вать. Я не уверен , что смог бы качественно или эффективно справиться с такой задачей. Кроме того, примите во внимание, что здесь речь идет об отдельных представителях; сколько разработчи ков действительно пол ностью понимают либо задействуют ту базу дан­ ных, которая и меется в их распоряже н и и , не говоря уже о трех СУБД? П оиск ге­ ния, который способен разрабатывать безопасные, масштабируемые , не зависящие от баз данных процедуры, сродни поиску Святого Грааля . Формирование команды таких разработчи ков - задача невыпол н имая . Н айти эксперта по Oracle, эксперта по D B2 и эксперта по S Q L Server и сказать и м : " Нам нужна транзакция , чтобы сде­ лать Х, У и Z " относительно легко. Далее им следует сообщить: " Здесь находятся входные данные, здесь - дан н ы е , которые нужно получить на выходе , а вот - то, к чему приведет этот бизнес-процесс" , после чего они смогут создать транзакцион­ ные АРI - интерфейсы (хранимые процедуры), которые отвечают всем требованиям. Каждый АРI - интерфейс будет реализован наилучш и м образом для конкретной базы данных согласно ее ун и кальному набору возможностей . Эти разработчи ки вольны задействовать полную мощь (или в зависимости от случая отказаться от нее) лежа­ щей в основе платформы базы данн ых. Те же самые приемы испол ьзуют разработч и ки , реал изующие многоплатфор­ мен н ы й код. Н апример, в Oracle Corporation эта технология применяется при раз­ работке собствен ной базы дан н ых. Существует огромн ы й объем кода (хотя он со­ ставляет малую долю всего кода базы дан н ых) , именуемый кодом OSD (Operation System Dependent - зависи м ы й от операционной системы ) , который реал изуется специфическим образом для каждой платформ ы . За счет применения этого уровня абстракции в Oracle появляется возможность задействовать многие н изкоуровневые средств операцион ной системы для обеспече н ия высокой производительности и и нтеграции , что не требует переписывания большей части самой базы данных. Это подтверждается тем фактом , что Oracle может функционировать как многопоточное приложение в Windows и м ногопроцессное - в U N I X/Linux. Механизмы взаимо­ действия между процессами абстрагированы до такого уровня, что они могут быть реализованы повторно на основе операционной системы, позволяя радикально от­ личающимся реализациям вести себя так, как приложение, написанное напрямую и специально для дан ной платформ ы . В дополнение к синтаксическим различиям в S Q L , реализаци и и производитель­ ности одного и того же запроса в упомянутых ранее разных базах дан ных существу­ ют проблемы управления параллельным доступом , уровням и изоляци и , согласован ­ ности запросов и т.д. Некоторые подробности будут раскрыты в главе 7 настоящей книги, и вы увидите, как эти различия могут коснуться вас. Стандарт SQ L92/SQ L99 пытается предоставить прямолинейное определение того, каким образом должна ра­ ботать транзакция и какие уровн и изоляции должны быть реализованы , но, в конеч­ ном счете , вы все равно получите отличающиеся результаты от разных баз данных. Причина связана с реализацией . В одной базе данн ых внутри приложения возника­ ет взаимоблокировка, и его работа полностью парализуется . В другой базе данных то же самое приложение работает гладко. В одной базе данн ых факт установки бло­ кировки (физически последовательной обработки) обеспечивает преимущества, но при развертывани и в другой базе данных и отсутствии блокирования получается не­ корректны й ответ. П еренос приложен ия в другую базу данных требует массы затрат и усил и й , даже есл и вы на 1 00% следовали стандарту. Ра зрабо т ка усп ешн ых пр иложе н ий O racle 99 Средства и функции Естественным продолжением довода о том , что вовсе не обязательно стремиться к независимости от базы данн ых, является идея того, что вам необходимо доско­ нально понимать возможности, которые должна предлагать конкретная база дан ­ ных, и обеспечить полноцен ное и х использование . Это не раздел, посвяще н н ы й всем фун кциональным средствам , которые может предоставить Oracle 1 2с - дан ­ ная тема потребовала б ы отдельной книги большого объема. В наборе документации Oracle оп исание новых возможностей O racle9i, Oracle I Og, Oracle l lg и O racle 1 2с зан имает целую кни гу. При наличии более 1 0 000 стран и ц документаци и , предла­ гаемой Oracle, раскрытие каждого средства и функции б ыло бы довольно сложным предприятием. Вместо этого цель настоящего раздела заключается в выяснен и и п ре­ имушеств, которые дает даже поверхностное знание доступных возможностей . Как упом и н алось ранее , я отвечаю на вопросы п о Oracle в И нтернете . М огу сказать, что около 80% этих ответов - просто U RL-ссылки на документацию (на каждый опубликованн ы й ответ на вопрос, обычно представляющий собой ссылку на документацию, находятся минимум два неопубли кованных вопроса с ответами в форме " прочтите это " ) . Л юди спраши вают, как можно реализовать те или иные сложные функции в базе дан н ых (ил и за ее пределами) , а я л иш ь указываю на место в документаци и , где объясняется , каким образом необходимая функция реализована в Oracle, и описан способ работы с ней . Часто встречаются вопросы по репл и кации . Вот типичный пример вопроса, который м н е задают. Существует ли представление, которое показало бы выполняемый буквальный SQL­ oпepaтop ? Я имею в виду, что когда делаю выборку из V$ S QL, значение в столбце SQL _Т ЕХТ выглядит так: I N S ERT I NTO TAВLE l ( COL l , COL2 ) VALUES ( : 1 , : 2 ) . А мне нужно видеть реальные данные, переданные в базу, например: I N S E RT I NTO TABLE l ( COL l , COL2 ) VAL U E S ( ' F i r s t Va l ' , l 2 ) . Дeлo в тoм, что я пытаюсь получить список операторов вставки, обновления или удаления, выполненных в одной схеме, и запустить те же самые операторы SQL в другой схеме в таком же поряд­ ке. Мне бы хотелось иметь код следующего вида: Select SQL_FULLTEXT from V$ SQL where FI RST_LOAD_T IME > SYSDATE- ( 1 / 2 4 ) AND -. ( SQL_TEXT l i ke ' I NSERT % ' . . . ) order Ьу F I RST_LOAD_T IME Такой набор записей можно было бы отправить через веб-службу в другую схему, которая обработала бы эти же операторы. Возможно ли подобное ? Здесь кто-то пытается заново изобрести репликацию! Он не может получить бук­ вальный SQL (и это хорошо) , но даже если бы смог, то такой подход н икогда бы не заработал. Вы не можете просто взять параллельна выполняемый набор операторов SQL (что произойдет на м ногопроцессорной машине, где два оператора SQL выпол­ няются в точности одновременно?) и выпол н ить их последовательно ( могут полу­ читься разные ответы!). Вам пришлось бы воспроизвести их с примене н ием той же степени параллелизма, которая имела место в исходной системе. Например, если два пользователя в одно время выполнят оператор I N S ERT I NTO А_ TAB LE S E LECT * FROM А_TAB LE ; , ТО В таблице А_TAB L E получится утроен ное количество строк по сравне н и ю с ее исходным состоянием. Скажем , если перво­ начально в таблице А_TABLE бьшо 1 00 строк, и первый пользователь произведет та­ кую вставку, в ней окажется 200 строк. Если сразу за н им вставку выполнит второй 1 00 Глава 1 пол ьзователь (до того, как первый пользователь зафиксирует операцию), то он не увидит 200 строк первого пользователя , а вставит в A_TAB LE еще 1 00 строк, при­ водя в результате к появлению в таблице 300 строк. Если теперь сделать так, чтобы вместо первого пользователя вставку осуществляла веб-служба (увеличивая А_TABLE со ста до двухсот строк) и затем вставку выпол нял второй пользователь (увеличи­ вая А_TABLE с двухсот до четырехсот строк) , то возникнет проблема. Репликация вещь непростая , и на самом деле реализовать ее довольно трудно. В Oracle (и других базах дан н ых) репликация делалась на протяжении более двух десятилетий ; ее реа­ лизация и сопровождение требовали немалых усили й . Действительно, вы можете создать собствен н ы й механизм репликаци и , и это может даже оказаться интересн ы м , но по большому счету поступать так не слиш­ ком разумно. База данных выполняет массу разнообразных функций. В целом она способна решать задачи лучше, чем это удается нам самим. Например, репликация встроена в ядро, написан ное на языке С. Это быстр ы й , довольно простой в ис­ пользовании и надежны й механизм. Он работает в разных версиях и на различных платформах. Кроме того, для него обеспечивается поддержка, поэтому при возник­ новен и и проблем команда поддержки Oracle всегда окажет необходимую помощь. После модерн изации репл и кация поддерживается также и в новой версии, возмож­ но, предлагая какие-то новые свойства. А теперь представьте , что вы разработали этот механизм самостоятельно. В таком случае придется обеспечить поддержку для всех новых версий, с которыми вы собираетесь иметь дело. А как насчет достижения совместимости между новыми и старыми версиями? Это тоже ваша работа. В случае отказа вы не сможете позвонить в службу поддержки - по крайней мере, до тех пор, пока вы не получ ите достаточно компактны й тестовый сценарий , демонстри­ рующи й основную п роблему. При появлении нового вы пуска базы дан ных Oracle вам придется самостоятельно переносить в него собственный код репликации. nонимание происходящего Отсутствие полного пониман ия того, что доступно, в кон це концов, может обер­ нуться крупными неприятностями. Как-то мне пришлось сотрудничать с нескол ь­ кими разработч и кам и , обладающими м ноголетн им оп ытом создания приложений баз данных, но в других СУБД. О н и построили программвое обеспечение анали­ за (оценки тенде н ц и й , создания отчетов и визуализаци и результатов) . Программа работала с кли н ически м и дан н ы м и , имеющи м и отношение к здравоохранению. Разработчи к и н ичего не знали о таких с интаксических конструкциях SQL, как встрое н н ы е п редставлен и я , анал и тические фун кци и и скалярные подзапросы . Основная проблема заключалась в том , что им требовалось анализировать данные из одной родительской таблицы и двух дочерних таблиц. Диаграмма "сущность-от­ ношение" ( E ntity Relation Diagram - ERD) могла бы вы глядеть похожей на пока­ заиную на рис. 1 . 1 . Дочер н яя таблица 1 " / Родительская таблица / "\ Дочер н яя таблица 2 Рис. 1 . 1 . П ростая диаграм ма "сущност ь -отношение" Ра зрабо т ка усn ешных n риложе н и й O rac l e 1 01 Разработчикам была нужна возможность создания отчета на основе родительской записи с агрегированием данных из каждой дочерней таблицы. СУБД , с которыми разработчикам доводилось работать в прошлом, не поддержи вали н и разложен ие подзапросов на составля ющие ( конструкция W I T H ) , н и встроен н ы е представле­ ния - возможность "запраши вать запросы" вместо запрашивания таблиц. Не зная о существовани и этих функциональных средств, разработчи ки создали на промежу­ точном уровне своего рода собственную СУБД. Они собирались запраш ивать роди­ тельскую таблицу и для каждой возвращен ной строки выпол нять запрос агрегирова­ ния с каждой дочерне й таблицей. В результате получались тысячи мелких запросов для каждого запроса, вьщаваемого конечным пользователем. Или они должны был и загружать целые агрегированные дочерние таблицы промежуточного уровня в хеш ­ таблицы в памяти и реализовать хешираванное соединение. Короче говоря, разработчики заново изобретали СУБД, выполняя фун кциональ­ ные эквиваленты соединения посредством вложенных циклов или хешираванного соеди нения, и не располагая преимуществами време н н ых табличн ых пространств, оптимизации сложных запросов и т.п . Они потратили свое время на разработку, про­ ектирование, настройку и совершенствование программы, которая п ыталась делать то же, что и СУБД, которую они уже приобрели! Между тем конечные пользователи нуждались в новых функциональных средствах, но не получали их, поскольку ос­ новную часть времени разработчи ки посвящали построению этого "механизма" со­ ставления отчетов, которы й действительно был замаскированным механизмом базы данных. Я показал им, что для сравнения данных, которые были сохранены на разных уровнях детализации, можно вы пол нять такие действия , как соединение двух агре­ гаций . При этом возможны различные подходы, как продемонстрировано в листин ­ гах 1 . 1 - 1 . 3. Листинг 1 . 1 . Встроенные представления дл я запрашивания и з запроса select p . id, c l_surnl , c2_sum2 from р , (sel ect id, s um (ql ) cl s uml from cl gro up Ьу i d) cl , (select id, s um (q2) с2 s um2 from с2 group Ьу id) с2 where р . id = c l . id and p . id = c2 . id 1 Листинг 1 . 2 . Скалярные подзапросы, которые выполняют отдельный запрос для каждой строки se lect р . id, (select sum (ql ) from cl where cl . i d (sel ect sum (q2) from с2 wh ere с2 . i d from р where p . name = ' 1 2 3 4 ' 1 = = p . i d) cl_ s uml , р . i d) с2 s um2 1 02 Глава 1 Листинг 1 . 3 . Разложение подзапросов с помощью конструкции WIТН with c l vw a s (sel e c t i d , s um (ql ) c l s um l from c l group Ьу i d) , с2 vw a s (sel ect i d , s um (q2 ) с2 s um2 from с2 group Ьу i d) , cl с2 a s (sel ect cl . i d , cl . cl_ s um l , с2 . с2 s um2 from cl_vw cl , c2_vw с2 where cl . i d с2 . i d) s e lect p . id , c l suml , с2 sum2 from р , c l_с2 whe re p . id = c l_c2 . id = 1 В дополнение к тому, что вы видите в этих листи н гах, можно также делать за­ мечательные вещ и с помощью аналитических фун кций , таких как LAG , L EA D , ROW_NUMBER, функций ранжирования и м ногих других. Короче говоря , вместо того, чтобы потратить остаток дня на выяснение приемлемого способа настройки их ме­ хан изма базы данных промежуточного уровня , мы провели остаток дня за изучением выведенного на экран справочного руководства по SQL (вместе с SQL* Plus для созда­ н ия разовых демонстраций работы тех или иных функций ) . Конечной цел ью боль­ ше не была настройка промежуточного уровня; теперь они стремились как можно быстрее от него избавиться . А вот еще оди н пример. М н е приходилось наблюдать, как люди настраивали в базе данн ых Oracle процессы-демоны , которые читали сообщен ия из каналов (ме­ хан изм взаимодей ствия между п роцессам и базы дан ных, реал и зован ный через D B M S _ P I P E ) . Эти процессы -демоны выпол няли S Q L-кoд, содержащийся внутри сообщен ия канала, и ф и ксировали работу. О н и делал и это так, что можно было проводить аудит и регистрацию ошибок в транзакци и , которая не должна была от­ меняться при выпол н е н и и транзакци и более высокого уровня . Обычно если для аудита доступа к каким-то дан н ы м испол ьзуется триггер или что-то подобное , но позже оператор завершается неудачей , то произойдет откат всей работы . Таким об­ разом, за счет отправки сообщен ия другому процессу они могли поручить выполне­ ние работы и фиксацию отдельной транзакци и . Запись аудита сохранялась бы даже в случае отката родительской транзакции . В версиях Oracle , предшествовавших 8i, это был подходящий (и по большому счету единствен н ы й ) способ реализации та­ кой функционал ьности. Когда я рассказал им о средстве базы дан н ых под назва­ нием автономные транзакции, разработчи ки были обескуражен ы . Автономные тран­ закции , реализуемые с помощью единственной строки кода, делали именно то, что разработчи ки выполняли самостоятельно. Это означало, что можно было отказаться от множества строк кода и , следовательно, от его сопровожде н ия . Вдобавок система в целом начала функционировать быстрее и стала проще для пониман ия . Но вмес­ те с тем разработчи кам было жаль времен и , напрасно потраченного на повторное изобретение колеса. В частности, разработчик, который создал эти процессы-демо­ н ы , был весьма огорчен тем , что плоды его труда оказались не нужны. Ра зработка усn ешных n р иложени й O rac l e 1 03 М не часто приходится стал ки ваться с подоб н ы м и ситуациями - круп н ые и сложные решен ия задач , которые уже решены самой СУБД. Я и сам грешил этим. Хорошо помню тот день, когда мой консультант по Orac\e (тогда я выступал в роли клиента) застал меня окруженным ворохом документации по Orac\e. Я взглянул на него и спросил : " Неужели все это правда? " Нескол ько п оследующих дней я пот­ ратил тол ько на изучение документаци и . Я самонадеянно полагал , что знаю о ба­ зах данн ых абсолютно все, поскольку ранее работал с SQL/DS, DB2, l ngress, Sybase , Informix, SQ LBase , Orac\e и другим и СУБД. Вместо того чтобы найти время для выяснения возможностей , предлагаемых каждой из них, я л и ш ь применял знания о других базах дан н ых к той , с которой имел дело в текущи й момент. ( Переход на Sybase/SQL Server был для меня огромным шоком - эта СУБД работала совершен­ но не так, как остальные .) П о мере выяснения того, что могла делать СУБД Orac\e (и, откровенно говоря , другие базы данн ых) , я начал пользоваться предоставляемы­ ми ею преимушествами и смог работать быстрее, реализуя меньший объем кода. Это происходило в 1 993 году. Только представьте себе, что можно делать с помощью это­ го программнога обеспечения в наши дни , спустя более двадцати лет. Выделите время на изучение доступного арсенала средств. Пренебрегая этим , вы очень многое теряете . П рактически ежедневно я узнаю об Oracle что-то новое. Это должно войти в привычку; я по-прежнему ч итаю документацию. Простое решение проблем Любую проблему всегда можно реш ить двумя способами : простым и сложны м . То и дело мне приходится встречать л юде й , выбирающих сложный путь. Это не всегда происходит осознан но. Чаще такой выбор обусловлен недостатком знан и й . Люди просто н е подозревают, что база данных может делать то или и ное. Я же , на­ против, убежден , что база данных способна решать что угодно, и выбираю сложны й путь (самостоятельно п и ш у код), только когда обнаруживаю, что о н а что-то не мо­ жет сделать. Например, меня часто спрашивают: " Как можно обеспечить наличие у конеч­ ного пользователя только одного сеанса в базе данн ых?" (Я бы мог здесь привести сотни других аналогичных примеров . ) Такое требование должно присутствовать во многих приложен иях, но мне н икогда не приходилось заниматься решением этой задачи - я просто не вижу веской прич и н ы для подобного ограничения возможнос­ тей, доступных пользователям . Тем не менее, люди хотят делать это и, как правило, строят решение сложным способом . Например, речь может идти о пакетном зада­ нии, запускаемом операционной системой , которое будет п росматривать табл и цу V$ S E S S I ON и произвольно удалять сеансы пользователей , открывших более одного сеанса. В качестве альтернативы они будут создавать собственные таблицы , в кото­ рые приложение будет вставлять строку при входе пользователя в систему и удалять ее при его выходе . Такая реализация неминуемо приведет к множеству обращен и й в службу поддержки , поскольку при аварийном отказе приложения строка останется на месте . Мне встречалось немало " креативных" путей решения этой задачи , но н и один и з н их н е может сравниться по простоте с приведеиным н иже : EODA@ORA12CR1> create p ro f i l e one_s e s s ion l imit s e s s i on s_pe r_u s er 1 ; Profile created . Профиль создан . 1 04 Глава 1 EODA@ORA 1 2 CR 1 > alter user scott profi l e one_s e s s ion ; User a l te red . Пользова тель изменен . EODA@ORA 1 2 CR1 > alter sys tem set resource_l imi t=true ; Sys tem a l te red . Система изменена . Теперь мы попытаемел подключить пользователя sсотт два раза; вторая попытка должна потерпеть неудачу: EODA@ORA1 2 CR1 > connect s cott / t iger Connected . Подключено . SCOTT@ORA1 2CR1> host s qlplus s cot t / t iger SQL * Plus : Re lease 1 2 . 1 . 0 . 1 . 0 P roduction on Fri Ma r 1 4 1 1 : 1 2 : 0 4 2 0 1 4 Copyri ght ( с ) 1 9 8 2 , 2 0 1 3 , Oracle . Al l rights rese rved . ERROR : ORA- 0 2 3 9 1 : exceeded s imul taneous S E S S I ONS PER USER l imit ОПМБКА : ORA- 02391 : превышен лимит одновременных сеансов для пользователя Вот и все - теперь любой пользователь с профилем ONE _SESS ION может входить в систему только оди н раз. Когда я показы ваю это решение, собеседник обычно хлопает себя по лбу и восклицает: " Я даже не подозревал , что это можно было сде­ лать так". Ознакомление с возможностям и инструментов, с которыми приходится работать, может сэкономить массу времени и усилий в процессе разработки . Тот же самы й довод "сохраняйте простоту" приме н и м и на более широком ар­ хитектурном уровне. Я всегда советую хорошо подумать, прежде чем решаться на очень сложные реализации . Чем больше в системе движущихся частей, тем больше элементов, которые могут отказать, а выявлен ие точ ного места ошибки в изли шне сложной архитектуре - задача не простая . М ожет быть, действительно " круто" реа­ л изовать систему с использованием бесчисленных связующих звеньев, но это не яв­ ляется правильным вариантом , есл и простая хран имая процедура позволяет решить задачу луч ше, быстрее и с меньшим числом ресурсов. М не доводилось встречать проекты, в которых разработка приложений тянулась дол гие меся цы, а конца все не было видно . Разработчики применяли новейшие и наилучшие технологии и языки , но разработка все равно шла не особенно быстро. Приложение было не таким уж большим - вероятно, в этом и заключалась пробле­ ма. Когда вы строите конуру (небол ьшая деревообделочная работа), то не станете пригонять тяжелую технику. Вы будете использовать несколько небольших электро­ инструментов, а не что-то крупное и сложное. С другой стороны, при построен и и жилого комплекса вам придется нанять сотни специалистов для работы над проек­ том и располагать крупной техни кой - т.е. применять для решен ия этой задачи со­ вершенно другие инструменты. То же самое относится и к разработке приложений. Н е существует единственной " идеал ьной архитектуры " . Н е существует единствен ­ ного " идеального языка " . И , конечно, не существует еди нствен ного " идеального подхода" . Н ап р и м е р , для п острое н ия своего веб-сайта я и с п ол ьзовал среду АРЕХ (Application Express) . Веб-сайт был крошечным приложением, разработкой которого Ра зработка усп ешных п р иложени й Oracle 1 05 занимался один разработчик (или два) . Он содержал около 20 экранов. П рименение PL/SQ L и АРЕХ было правильным выбором дЛЯ этой реализации - я не нуждался в найме десятков программистов, кодирующих на Java, создающих EJ B , использую­ щих Нibemate и т.д. Задача бьша простой и решалась просто. Существует несколько сложных, круп номасштабных, огромных приложений (большинство из н их мы при­ обретаем в наши дни : системы учета кадров, системы планирования и управления ресурсами предприятия и т. п . ) , но есть и тысячи небольших приложе н и й . Для вы­ полнения каждой работы необходимо применять соответствующий подход и инс­ трументы. Я всегда стремлюсь использовать самую п ростую архитектуру, которая позво­ ляет полностью решить нужную задачу. Окупаемость может оказаться гигантско й . Каждая технология занимает свое место. Н е все задачи сводятся к забиван и ю гвоз­ дей , так что в нашем арсенале должен быть не только молоток. Открытость Я часто встречаю людей, которые решают задачи сложны м путем по другой при­ чине, и это снова связано с идеей о том , что мы должн ы стремиться к открытости и независимости от базы дан ных любой ценой. Разработчи ки хотят избегать приме­ нении закрытых, патентованн ых функциональных возможностей базы данных (даже когда они настолько просты , как хранимые процедуры или последовательности) , поскольку и х применение приведет к замыкани ю на кон кретную СУБД. Что ж , поз­ вольте мне выдвинуть идею о том , что даже при разработке приложения , ч итающего и записывающего данные, вы уже в какой-то мере замыкаетесь на СУБД. Вы об­ наружите тон ки е (а и ногда и не настолько тонкие) отличия между базами данных, как только приступ ите к выполнению запросов и внесени ю изменени й . Например, в одной СУБД может оказаться , что запрос S E LECT COUNT ( * ) FROM т попадает в состояние взаимоблокировки при простом обновлен и и двух строк. Вы обнаружите, что в Oracle запрос S E LE C T COUNT ( * ) н икогда не блокируется дЛЯ процесса, вы­ полняющего запись. Вы столкнетесь с ситуацие й , когда из-за побочных эффектов модели блокировки бизнес-правило выполняется в одной базы данн ых, но не вы­ полняется в другой. Выяснится, что при одном и том же наборе транзакций запросы дают отличающиеся ответы в разных базах дан н ых - и все это обусловлено фунда­ ментальными различиями в реализации . Вы обнаружите, что лишь очен ь нем ногие приложения могут быть перенесен ы из одной базы данн ых в другую без каких-либо изменений. Всегда будут присутствовать отличия в интерпретации и обработке SQL­ кoдa (например, вспомните обсужден ие NULL=NULL ) . В одном из проектов разработчи ки строили веб-приложение, используя Visual Basic, элементы управления ActiveX, сервер I I S и базу данных Oracle. М не сказали, что разработчики обеспокоен ы тем , что поскольку бизнес-логика бьша реализована на P L/SQL, приложен ие стало зависеть от базы дан ных, и спросил и : " Как мы мо­ жем это исправить? " Я бьш немного озадачен этим вопросом. Глядя на список выбранных технологий , я не мог понять, почему зависимость от базы дан ных вызвала обеспокоенность. • Разработчики выбрали язык, который привязал их к единственной операци­ онной системе, предлагаемой еди нственным поставщи ком (они вполне могли бы выбрать Java) . 1 06 Глава 1 • Разработчики выбрал и технологию построения компонентов, которая привя­ зала их к еди нственной операционной системе и поставщику (можно было выбрать J2EE). • Разработчи ки выбрали веб-сервер, который привязал их к единствен ному пос­ тавщику и одной платформе (почему бы не отдать предпочтение чему-то более открытому?) . Каждая из выбранных разработчи ками технологий привязывала их к очень спе­ цифичной конфигурации - фактически , единственной технологией, которая предо­ ставляла ш ироки й выбор в отношении операционных систем, была база данных. Н евзирая на это (для такого выбора технологий должны были существовать вес­ кие прич и н ы ) , целая групп а разработчи ков сознательно решила не пользоваться функциональностью одного из основных ком понентов архитектуры во имя откры­ тости. Я искренне убежден , что следует тщательно выбирать технологи и , а затем максимально их эксплуатировать. Вы заплатили за них огромные деньги - так разве не в ваших интересах выжать из н их максимум? П олагаю, что разработчики собира­ л ись максимально задействовать потенциал других технологий , так почему же база дан ных должна была стать исключен ием? Ответить на этот вопрос было еще труднее в свете того, что наиболее полное использование возможностей базы дан ных имело решающее значение для успеха всего проекта. С точки зрен ия открытости на довод можно взглянуть под несколько иным уг­ лом . Все данные помещаются в базу. СУБД - очен ь открытый инструмент. Она поддерживает доступ к данным с помощью ш ирокого многообразия открытых сис­ темных протоколов и механизмов доступа. Пока все звучит прекрасно: СУБД - на­ иболее открытый инструмент в мире. П осле этого вы размещаете всю логи ку приложения и, что еще более важно средства безопасности - за пределами базы данных. Возможно, это будут Jаvа-бины или J S Р-страницы, которые осуществляют доступ к данным. Может быть, это будет код на Visual Basic или код, сгенерированный H ibemate. В любом случае вы закры­ ваете базу данных - делаете ее " не открытой ". Пользователи больше не могут выби­ рать существующие технологи и , чтобы работать с этими данными; они обязаны при­ менять ваши методы доступа (ил и полностью обходить средства безопасности) . Все это звучит хорошо в текущий момент, но всегда следует помнить, что новейшее до­ стижение на сегодняш н и й ден ь завтра станет устаревшей технологией. Единственное что сохраняется в реляционном мире на протяже н и и более 30 лет ( и , вероятно, в большинстве объектных реализаций) - это сама база данн ых. И нтерфейсы доступа к данным меня ются почти ежегодно, в результате чего приложения, все средства бе­ зопасности которых встроен ы внутрь них, а не вынесены в базу дан ных, устаревают и становятся препятствием на пути дальнейшего прогресса. СУБД Oracle предоставляет средство под названием детальный контроль доступа (fine-grained access coпtrol - FGAC). Если кратко, то эта технология позволяет раз­ работчи кам встраивать в базу данных процедуры , которые могут изменять запросы во время их передачи базе данных. Такое изменение запросов направлено на огра­ н ичение строк, которые клиент будет получать или модифицировать. П роцедура мо­ жет следить за тем , кто выполняет запрос, когда он запускается , какое приложение запраш ивает данные, из какого терминала поступает запрос и т. п . , и соответствую­ щим образом ограничивать доступ к данным. Ра з работ ка у сп е ш н ых п рило ж е н и й Oracle 1 07 Средство FGAC дает возможность реализовать правила безопасности , такие как описанные н иже. • Любой запрос, выполненн ы й вне обычных рабочих часов определенным клас­ сом пользователей, будет возвращать ноль записей. • Любые данные могут быть выведены на терминал в защищен ном помеще н и и , но только несекретная информация может быть возвращена на терминал уда­ ленного клиента. По существу FGAC позволяет размещать элемент управления доступом в базе данных, непосредственно рядом с данными. Больше не и грает рол и , как пользователь обращается к дан ным - из Jаvа-бина, J S Р-страницы или приложе н ия Visual Basic через ODBC или SQL*Plus; в любом случае будут использоваться одн и и те же про­ токолы безопасности . Это позвол ит успешно применить технологию, которая поя­ вится следующей . А теперь я спраш иваю: какая ж е реализация более "открыта"? Та, которая дела­ ет возможным доступ к данным только посредством кода Visual Basic и элементов управления ActiveX (при желании можете заменить Visual Basic на Java, а ActiveX на EJ B - здесь речь идет не о выборе конкретной технологи и , а о реали зации ) , или же решен ие, которое обеспечивает доступ из любого приложения, способного вза­ имодействовать с базой дан н ых, через такие протоколы , как S S L, НПР и Oracle Net (и другие), либо с использованием АРI - и нтерфейсов, подобных O D BC , J D BC, OCI и т.д.? М не еще не приходилось встречать специализированного и нструмента генераци и отчетов, который мог бы "запраши вать" код на Visual Basic. Однако мне известны десятки приложений, которые запрашивают SQL-кoд. Конечно, люди вольны принимать решение о соблюден и и полной открытости и независимости от баз данных. М ногие п ытаются это делать, но я уверен , что такое решение ошибочно. Независимо от применяемой СУБД, ее следует эксплуатировать максимально полно, задействовав даже самые мелкие функциональные возможнос­ ти продукта. В любом случае вы обнаружите , что делаете это на этапе настрой ки (которую, как правило, приходится проводить сразу после развертывания) . П росто уди вительно, насколько быстро может быть забыто требование независимости от базы данных, когда появляется возможность создан ия приложения , которое работа­ ет в пять раз быстрее всего лишь за счет использован ия всех возможностей програм­ многа обеспечения базы данных. Как заставить при п ожение выполняться быстрее ? Вопрос, вынесенный в заголовок этого раздела, мне задают постоянно. Все и щут переключатель вроде "ускорить", полагая при этом , что " н астройка базы данных" означает выполнение настройки самой базы дан н ых. Н а самом деле , согласно мо­ ему опыту, более 80% (а часто все 1 00%) увеличения производительности должно обеспечиваться на уровне проектирования и реализации приложения - не на уров­ не базы дан ных. Вам не удастся провести настройку базы данных до тех пор, пока вы не настроите приложения , работающие с СУБД. По мере развития технологии появляются переключател и , которые можно уста­ навливать на уровне базы данных, и которые способствуют уменьшению влияния недостатков программирования. Например, в Oracle 8 . 1 .6 был добавлен новый па- 1 08 Глава 1 раметр C U RS O R S HAR I N G = FORC E . Этот п араметр позволяет при желани и реали­ зовать автоматическую привязку. Он будет молча преобразовывать запросы вида S E LECT * FROM ЕМР WHERE EMPNO = 1 2 3 4 В S ELECT * FROM ЕМР WHERE EMPNO = : х. Применение этого п араметра может радикально уменьш ить количество полных разборов и количество ожиданий освобождения библиотечных зашелок, которые рассматривались в разделе "Архитектура Oracle " ранее в главе , но (всегда есть "но") могут возни кать побочные эффекты . Распространенный побочный эффект с разде­ лением курсора выглядит примерно так: EODA@ ORA12CR1> s e 1 ect /* TAG * / subs t r ( use rname , 1 , 1 ) 2 from a l l users au1 3 whe re rownum = 1 ; s s EODA@ ORA1 2CR1> alter s e s s ion set cursor_s haring=force ; S e s s i on a l tered . Сеанс изменен . EODA@ORA 1 2 CR1 > s e lect / * TAG * / subs t r ( use rname , 1 , 1 ) 2 from a l l u s e rs au2 3 where rownum = 1 ; SUBSTR ( US ERNAМE , 1 , 1 ) s Что здесь случилось? Почему столбец, о котором сообщил SQL* Plus, неожиданно оказался настолько большим во втором запросе , который на первый взгляд н ичем не отличается от первого? Это (и кое-что еще) станет очевидным, если взглянуть на то, к чему приводит установка разделения курсора: EODA@ORA12CR1> select s ql_text from v$sql whe re sq1_t ext l i ke ' se 1ect / * TAG * / % ' ; SQL_TEXT select /* TAG * / subst r ( use rname , 1 , 1 ) f rom a l l users au1 whe re rownum = 1 s e l ect / * TAG * / s ub s t r ( use rname , : " SYS_B_O " , : " SYS В 1 " f rom a l l users au2 where rownum = : " SYS В 2 " Разделение курсора удаляет и нформаци ю и з запроса. Запрос нашел все литера­ л ы , в том числе константы встроен ной функци и s ub s t r , которые мы использовали. Они были удалены из запроса и заменены переменными привязки . Теперь механизм SQL не знает, что столбец является подстрокой с длиной 1 его длина не опреде­ лена. Кроме того, как видите, конструкция whe re r ownum 1 также стала привя­ занной. Н а первый взгляд это кажется хорошей идеей; тем не менее , оптимизатор только что лишился некоторой важной информации . Он больше не знает, что "этот запрос будет извлекать оди ночную строку"; он уверен , что " этот запрос будет воз­ вращать первые N строк, и N может быть любым числом " . Такой результат может отрицательно повлиять на сгенерированные планы выполнения запросов. = Ра зрабо т ка усп ешн ых п рил оже н и й Oracle 1 09 Кроме того, я убедился , что хотя режим CURSOR S HAR I NG = FORCE обеспечивает значительно более быстрое выполнение, чем си нтаксический разбор и оптимизация множества уникальных запросов (см. раздел " Используйте перемен н ые привязки " ) , о н работает все же медленнее, ч е м в случае применения запросов, где разработчи к делал привязку самостоятельно. Это происходит н е из-за какой-то неэффективнос­ ти в коде разделения курсора, а скорее из-за н еэффективности внутри самой про­ граммы. Во многих случаях приложение, не использующее переменные при вязки , не позволяет н и эффективно вы пол н ить синтаксический разбор, н и повторно ис­ пользовать курсоры . П оскольку приложение уверено, что кажды й запрос уни кале н (запросы построены в форме уни кальных операторов) , о н о н икогда не будет приме­ нять курсор более одного раза. Реальность заключается в том , что если программист с самого начала использовал переме н н ые привязки, то он может выполнить разбор запроса один раз, а затем применять его м ногократно. И менно н акладные расходы по синтаксическому разбору снижают общую производительность. _ На заметку! Важно также отметить, что установка CURSOR_ S HAR I NG= FORCE не устраня­ ет ошибку внедрения SQL. П р и вязка выполняется после того, как зап рос был перепи­ сан конечным пользовател е м ; внедрение SQL уже произошло. П осредством CURS OR_ S HA R I N G = F O R C E нел ьзя получ ить более в ы сокую степень защиты , ч е м она была. Соп ротивляемость внедрению SQL можно обеспечить тол ько за счет испол ьзования са­ мих переменных привязки . В основном важно иметь в виду, что сама по себе настрой ка CURSOR S НAR I NG= FORCE не обязательно решит проблем ы . Она вполне может породить новые слож­ ности . В некоторых случаях параметр CURSOR S НARI NG - очень полезный инстру­ мент, но он отнюдь не является панацеей от всех бед. В тщательно разработан ном приложении он никогда не понадобится. С точки зрения долговременной перспек­ тивы правильным подходом я вляется применение перемен н ых привязки там , где это уместно, и констант - когда это необходимо. _ _ Н а заметку! Не существует н и каких магических средств вообще никаких. Если бы они были, то превратились бы в стандартное поведение, и вы ни когда бы о них не усл ышали . - Хотя есть переключатели , которые можно использовать на уровне базы дан ных (они действительно немногочисленные и редко встречающиеся) , то проблемы , свя­ занные с параллел ьной обработкой и неэффективным выполнением запросов (из­ за плохо написанн ых запросов или плохо структурированных данн ых ) , решить с их помощью не удастся . Подобные ситуации требуют переписывания кода (и нередко изменения архитектуры ) . П еремещение файлов дан ных, настрой ка параметров и других переключателей уровня базы данных часто оказывает л и ш ь незначител ьное влияние на общую производительность приложения . Во всяком случае , эти действия определенно не обеспечат двух-, трех- или п-кратного повышения производитель­ ности , которое требуется для того, чтобы приложение стало приемлемым. Сколько раз вы получал и приложе н и е , которое работало на 1 0 % медлен нее желаемого? Н и кто не жалуется на 1 0-процентное замедлен ие. А вот пятикратное замедление непременно вызовет недовольство пользователей. П овторю е ще раз: пятикратного увеличения производительности не удастся достичь перемещением файлов дан ных. 1 10 Гл ава 1 Этого можно добиться только путем внесения в приложение корректировок, воз­ можно, направлен н ых на значительное уменьшение количества выполняемых опе­ раций ввода-вывода. На заметку! П росто чтобы отметить, как вещи меняются со времене м . Я часто пишу о том , что вы н е получ ите пятикратного роста п роизводител ьности , перемещая файлы данных с места на место . С появлением аппаратных реше н и й , таких как Oracle Exadata (устройс­ тво сети хранения дан ных, спроектированное в качестве расши рения базы данных), вы на самом деле можете получить 5-, 1 0- , 50-кратное и более сокращение времени ответа, п росто переместив туда файлы данных. Но это скорее история о том , как "мы полностью сменили нашу аппаратную архитектуру" , чем о том , как " м ы реорганизовали наше хра­ нилище". Кроме того, увел ичение скорости работы приложения лишь в 5 или 10 раз на Exadata лично меня бы разочаровало - хотелось бы получить 50- кратны й рост и более и потребовало переосмысления реализации самого приложения. П роизводительность - это характеристика, которую нужно учитывать при про­ ектировании, построен и и и тестировании на протяжении всего периода разработки. Ее учет н икогда не следует переносить на момент, когда приложение готово. Меня уди вляет, насколько часто люди дожидаются поставки приложения клиенту, его ус­ тановки и начала эксплуатаци и , прежде чем приступают к его тон кой настройке. М н е приходилось сталкиваться с ситуациями, когда приложен ия постамялись толь­ ко с первичными ключами - вообще без каких-либо других и ндексов. Запросы ни­ когда не настраивались и не подвергзлись н агрузочному тестированию. Приложенил н икогда не испытывались при наличии достаточно большого количества пользова­ телей. Настройка считалась частью процесса установки программнога продукта. На мой взгляд, этот подход совершенно неприемле м . Конечные пользовател и долж­ н ы с первого дня получить работоспособную и полностью настроенную систему. " Проблем с продуктом " будет более чем достаточно и без того, чтобы пользователи с самого начала сталкивались с низкой производительностью. Пользователи готовы к тому, что новое приложение будет содержать несколько программных ошибок, но не заставляйте их мучительно долго дожидаться появления результатов на экране. От но ш ения между администратором базы данных и разработчиком Не вызывает сомнений, что большинство успешных информационных систем ос­ новано на отношениях сотрудничества между администратором базы данных и раз­ работчи ком приложения . В этом разделе я хочу привести точку зрен ия разработчика на разделение труда между разработчи ком и администратором базы данных (исходя из предположения , что команда разработки каждого серьезного проекта включает в себя группу администраторов базы данн ых) . Разработчи ку не обязательно знать, как устанавли вать и конфигурировать про­ граммное обеспечение. Это задача адми н истратора базы данных и, возможно, сис­ темного администратора. Настройка Oracle Net, запуск проелушивающего процесса, конфигурирование сервера совместного использован ия, вкл ючение пула соедине­ н и й , установка СУБД, создание базы данных и т.п . - все эти функции я передаю в руки админ истратора базы дан н ых/системного администратора. В общем случае разработч ику не обязательно знать, каким образом настраивает­ ся операционная система. Обычно я оставляю эту работу системным администра- Ра зрабо т ка усп ешн ых п р ил оже н и й O racle 111 торам . Разработчик приложений баз данных должен быть компетентен в вопросах использования выбранной операционной системы, но от него не следует ожидать умения ее настраи вать. Еди нственная главнейшая ответствен ность администратора базы данных - вос­ становление базы дан ных. Обратите вниман ие, реч ь идет не о "резервном копиро­ ван и и " , а о " восстановлен и и " , и я готов присягнуть, что это - единствен ная от­ ветственность администратора базы данных. Понимание того, как работает откат и повторение - да, это то, что разработчи к должен знать. Знание того, как выполнять восстановление табличной области на кон кретный момент времен и - нечто такое , что без чего разработчик вполне может обойтись. Знать о том , что подобное возмож­ но, будет нелишним, но действительно делать его - нет ни какой необходимости . Н астройка на уровне экземпляра базы данных и выяснение оптимал ьн ого зна­ чения для параметра PGA AGGREGAT E TARGET , как правило, является задачей ад­ мин истраторов базы дан ных (и СУБД располагает достаточн ы м набором средств, облегчающих определение корректной конфи гураци и ) . В ряде исключительных случаев разработчи ку может понадобиться измен ить некоторые н астройки сеанса, но на уровне базы дан н ых за это отвечает адми нистратор. Типичная СУБД подде­ ржи вает приложения, реализованные более чем одни м разработчиком. Только ад­ министратор базы данных, который поддерживает все приложен ия , может принять правильное решение. Выделение дискового пространства и управление файлами - также задача ад­ министратора базы данных. Разработч ики могут вносить свои предложен ия относи­ тельно дискового пространства (указы вать, сколько, по их мнению, и м потребуется места), но обо всем остальном позаботится адми н истратор базы данных/системный администратор. В общем случае от разработчи ков не требуется знание способов эксплуатаци и СУБД. Они должны знать, как запускать программы в СУБД. Разработчи к и адми ­ нистратор базы дан ных совместно работают над различными частям и одной и той же головолом ки . Администратор базы дан н ы х будет обращаться к разработчи ку, если запросы потребляют слишком много ресурсов . Разработчи к будет обращаться к администратору, если ему не удается понять, каким образом еще больше ускорить работу системы (это именно тот случай , когда можно прибегнуть к настройке эк­ земпляра после того, как приложение полностью настроено) . Все это варьируется в зависимости от среды , но я - приверженец разделения труда. Хороший разработч и к обычно я вляется плохим адми н истратором базы дан ­ ных и наоборот. По моему убеждению, эти занятия требуют двух разных професси­ ональных навыков, двух отличающихся образов мышления и двух разных личност­ ных качеств. _ _ Р ез ю ме В этой главе мы несколько обобщенно рассмотрели прич и н ы , которые обуслов­ ливают необходимость знания СУБД. Приведеиные мною примеры отнюдь не вы­ думаны - они встречаются ежедне вно. С подобными проблемами мне приходится сталкиваться постоянно. Давайте кратко вспомн и м ключевые моменты . Есл и разработка выполняется с применением Oracle, важны перечислен н ые н иже аспекты . 112 Глава 1 • Н еобходимо понимать архитектуру Oracle . Н е обязательно знать ее до такой степени , чтобы быть в состоян и и заново написать код сервера, но в ней необ­ ходимо разбираться в достаточной мере, чтобы и меть понятие о последствиях использования конкретного функционал ьного средства. • Н еобходимо знать особенности блокировки и управления параллельной обра­ боткой и то, что в каждой базе данных они реализованы по-другому. В про­ тивном случае база дан н ы х будет в ыдавать " неправильные" ответы и у вас возни кнут большие проблем ы соперничества, ведущие к низкой производи­ тельности . • Не следует трактовать базу дан н ых как черны й ящик - т.е. то, что не требует понимания . База данных я вляется наиболее важным компонентом большинс­ тва приложе н и й . П опытка ее и гнорирования приведет к фатальным последс­ твиям . • Н е изобретайте колесо. Я видел н е одну команду разработч иков, которые сталкивались с проблемами - не только на техническом, но и на личностном уровне - и з-за неосведомленности о том , что свободно предлагается Oracle . Это происходит, когда кто-то обнаруживает, что средство, на реализацию ко­ торого потрачено п ару меся цев, уже есть в ядре базы дан ных. Ч итайте доку­ ментацию, которая поставляется вместе с программным обеспечением! • Решайте задачи наиболее простым способом , максимально используя встро­ енные функциональные возможности Oracle . За них был и уплачены немалые ден ьги . • П рограммн ые проекты приходят и уходят, равно как языки программирования и платформы. Разработчи ки могут заниматься обеспечением работоспособнос­ ти систем несколько недель, возможно, месяцев, а затем переходить к реше­ н и ю следующей задачи . Если снова и снова заниматься изобретением колеса, то н икогда не удастся добиться значительных успехов в разработке . Подобно тому, как вы н и когда не станете строить собствен н ы й класс хе ш -таблицы в J ava, поскол ьку в Java такой класс уже есть, вы должн ы применять имею­ щиеся в вашем распоряжен и и функциональные возможности базы данных. Естествен но, первый шаг на пути к этому - понимание того, чем вы распола­ гаете. Ч итайте документацию. Продолжая последнюю м ысль - проекты программною обеспечения и язы ки программ ирования приходят и уходят, но данные существуют всегда. М ы строим приложения, которые используют данные, а со временем эти данные будут приме­ няться многими приложе н ия м и . Таким образом , речь идет не о приложениях, а о данных. Задействуйте технологи и и реализации , которые допускают использование и м ногократное использование данн ых. Если вы применяете базу данных в качес­ тве хранилища, но открываете доступ к любым данным только через приложение, конечная цель не будет достигнута. В ы не сможете произвольно запраш ивать свое приложение и не сможете построить новое приложение поверх старого. Но если вы используете базу данных, то обнаружите, что с течен ием времен и добавление новых приложений, отчетов или чего-н ибудь другого становится значительно проще . ГЛ А В А 2 О б з о р ар хит ектур ы с истема управления базам и дан н ы х O rac\e б ыла спроекти рована как в вы­ сшей степени переносимая - она доступна на всех значимых платформах, от Windows и U N I X/Linux до мэйнфреймов. Однако физическая архитектура Oracle в разных операцион ных системах отл ичается . Н апример, в U N IX/Linux вы увидите , что СУБД Orac\e реализована как совокупность процессов операционной системы, фактически по одному процессу на каждую крупную функцию. Для U N IX/Linux та­ кая реализация вполне естественна, поскольку работа происходит в среде с множес­ твом процессов. Тем не менее, в Windows эта архитектура бьmа бы неподходящей и работала бы не особен но эффективно (оказалась бы медленной и не поддающей ­ ся масштабированию) . П оэтому на платформе Windows СУБД Orac\e реализована в виде одного процесса с множеством потоков. В прошлом на мэй нфреймах, работа­ ющих под управлением OS/390 и z/OS, архитектура Orac\e , специфичная для этих операционных систем, задействует набор адресн ых пространств OS/390, которые все функционируют как единственный экземпляр Oracle. Для одного экзем пляра базы данных можно сканфигурировать до 255 адресных пространств. Кроме того, СУБД Oracle работает совместно с диспетчером рабочей загрузки (Workload Manager WLM ) при установлении приоритета выполнения кон кретн ых рабочих нагрузок Orac\e по отношению друт к другу и ко всем другим задачам , выполняемым в систе­ ме OS/390. Несмотря на то что физические механизм ы , применяемые в реализациях Oracle, варьируются от платформ ы к платформе, архитектура в достаточной степени обобщена, чтобы можно было получить хорошее представление о ее работе на всех платформах. В настоя щей главе я представлю обширное описание этой архитектур ы . М ы взглянем на сервер Oracle и определ и м ряд терминов, таких как база данных, под­ ключаемая база данных, контейнерная база данных и экземпляр (терми н ы , которые практически всегда вызы вают путаницу). Мы посмотрим, что происходит при "под­ ключен и и " к Oracle, и ознакомимся с тем , как сервер управляет памятью на высо­ ком уровне. В трех последующих главах мы рассмотрим три основных компонента архитектуры Orac\e. • В главе 3 освещаются файл ы . В ней мы взглянем на пять основных категори й файлов, которые образуют базу данн ых: файл ы параметров, файлы данных, временные файл ы, управля ющие файл ы и журнальные файлы для восстанов­ ления. Мы также рассмотрим другие типы файлов, включая файл ы трасси ­ ровки , файлы предупреждений, файлы дампа ( D M P) , файлы помпы данн ых и простые плоские файл ы . Вы узнаете о файловой области (в Oracle 1 Og и пас- 1 14 Глава 2 ледующих версиях) , которая называется Fast Recovery Area (Область быстрого восстановления ) . М ы также обсудим влияние автоматического управления па­ мятью (Automatic Storage Management - AS M ) на файловое хранилище. • В главе 4 раскры ваются структуры памяти Oracle , назы ваемые SGA (System G lobal Area - систем н ая глобальная область) , PGA ( Process Global Area глобальная область процесса) и U GA ( User Global Area - глобальная область пользователя ) . М ы исследуем взаимосвязь между этими структурами, а также обсудим разделяемый пул , большой пул , пул Java и другие компоненты струк­ туры SGA. • В главе 5 рассматриваются физические процессы или потоки Oracle. Мы взгля­ нем на три отличающихся ти па процессов, которые будут выполняться в базе данн ых: серверные процессы, фоновые процессы и подчиненные процессы. М не было нелегко реш ить, какие из этих компонентов раскры вать первы м и . Структура S G A используется процессами , поэтому рассмотрение SGA д о ознаком­ ления с процессами может быть лишено смысла. С другой стороны, при обсуждении процессов и выполняемых ими действий неизбежн ы ссылки на SGA. Эти два ком­ понента тесно связаны: процессы воздействуют на файлы, и рассмотрение файлов без предварительного ознакомления с тем , что делают процессы , было бы лишено смысла. П оэтому я определ ю некоторые терми н ы и предоставл ю общи й обзор о том , на что похожа база данн ы х Oracle (так, как если бы изучение начиналось с нуля ) . Обсудить предстоит две архитектуры . Первая из н их - это архитектура, которую база дан ных Oracle применяла всецело, начиная с версии 6 и заканчивая версией I Ig (здесь она назы вается архитектуро й с единственным владельцем (single tenant)), и новой архитектурой с множеством владельцев (multi-tenant) , поя вившейся в вер­ сии Oracle 1 2с. П осле этого можно будет приступать к ознакомлению с некоторыми подробностям и . Определе н ие базы дан ных и э кзе м пляра Существуют два термина, которые при использовании в контексте Oracle, по­ хоже , вызывают наибольшую путаницу: база данных и экземпляр. В терми нологии Oracle они определяются следующим образом . • База данных. Коллекция физических файлов или дисков операционной систе­ м ы . В случае применения разделов AS M или RAW база данн ых может не вы­ глядеть как отдельные файлы в среде операцион ной системы, однако это оп­ ределение остается в силе. В верси и Oracle Database 1 2с существуют три типа баз дан ных. • База данных с единственным владельцем (single tenant). Это обособленный н абор файлов дан н ых , управляющих файлов, журнальных файлов для вос­ становлен и я , файлов параметров и т.д. , который вдобавок ко всем метадан­ н ы м , данн ы м и коду приложен ия содержит все метаданные Oracle (например, определение ALL OBJEC T S ) , дан ные Oracle и код Oracle (такой как код для DBMS OUT P UT ) . В версиях, п редшествующих 1 2с, это был еди нственный тип базы данных. _ _ Об зор архите к туры 115 • Контейнерная (container) или корневая (root) база данных. Это обособлен ный набор файлов данных, управляющих файлов, журнальн ых файлов для восста­ новле н ия , файлов параметров и т.д. , которы й включает тол ько метаданн ые Oracle, данные Oracle и код Oracle. В таких файлах данных отсутствуют какие­ либо объекты или код приложения - только метаданные и объекты кода, пре­ доставленные Oracle. База дан н ых я вляется обособленной в том смысле, что она может быть смонтирована и открыта без доп олнительных поддержи ваю­ щих физических структур. • Подключаемая (pluggaЬie) база данных. Это набор одних лишь файлов данных. Такая база данных не я вляется обособленной. Чтобы появилась возможность открытия и доступа, подключаемая база данных должна быть " вставлена" в контейнерную базу данн ых. Файлы данных содержат только метаданные для объектов приложений, данные приложений и код для приложений. Метаданные или любой код Oracle в этих файлах данных отсутствует. Нет каких-либо жур­ нальных файлов для восстановления , управляющих файлов, файлов парамет­ ров и т. п . - только файл ы данных, ассоциированные с подключаемой базой дан ных. Подключаемая база данных наследует другие тип ы файлов от контей­ нерной базы данных, к которой она подключена в текущий момент. • Экземпляр. Набор фоновых процессов или потоков и области разделяемой па­ мяти Oracle , представляющей собой память, которая совместно используется этими потоками или процессами , выполняющимися на одном ком пьютере. Это место для изменяющихся, непостоянных данных, часть которых сбрасы ва­ ется на диск. Экземпляр базы данн ых может существовать вообще без какого­ либо дискового хранил и ща. Возможно, это и не самая полезная вещь в мире, но такое представление о нем позволяет проводить линию между экземпляром и базой данных. И ногда эти два термина, экземпляр и база данных, применяют взаимозаменяемо, но они отражают очень разные конце п ци и , особенно теперь, в архитектуре с мно­ жеством владельцев. Отношение между ними заключается в том , что база данных с единственным владельцем или контейнерная база данных (в главе под просто базой данных подразумевается либо база дан ных с единствен н ы м владельце м , л ибо кон­ тейнерная база данных; при обсужде н и и подключаемых баз данных характеристика подключаемая указывается явно) может быть смонтирована и открыта нескольким и экземплярами . Экземпляр может монтировать и откры вать тол ько одну базу дан­ ных в каждый момент времен и . Фактически , правильно сказать, что экземпляр бу­ дет монтировать и открывать самое большее одну базу данных на протяжен и и всего времени своего существования ! Вскоре мы рассмотрим пример. Подключаемая база данн ых будет ассоциирована с одной конте йнерной базой данн ых за раз и только непрямо связана с экзем пляром ; она будет совместно ис­ пользовать экземпляр, созданный для монтирования и открытия конте й нерной базы данных. Таким образом , подобно контейнерной базе дан ных, в каждый момент вре­ мени подключаемая база данных может быть ассоциирована с одн и м или несколь­ кими экземплярам и . Однако в отличие от базы данн ых с еди нственным владельцем, экземпляр может предоставлять доступ ко м ногим (прибл изительно до 250) под­ ключаемым базам данн ых одновременно. То есть единстве н н ы й экземпляр может 1 16 Глава 2 предлагать службы для множества подключаемых баз данных, но только для одной контейнерной базы данных или базы данных с еди нственным владельцем. Еще больше запутались? Дальнейшие пояснения должн ы облегчить понимание этих концепций . Экземпляр представляет собой просто набор процессов операционной системы или оди н п роцесс с множеством потоков и определен ной областью памяти . Эти п роцессы могут действовать в еди нствен ной базе дан н ых. База дан ных является всего л и ш ь коллекцией файлов (файлов данных, временных файлов, журнальных файлов для восстановления и управляющих файлов). В любое время экзем пляр бу­ дет связан только с одним набором файлов (одной контейнерной базой данных или базой данн ых с единственным владельцем). Можно открывать и получать доступ к нескольким подключаемым базам данных, которые подч и няются контейнерной базе данн ых, но все они будут совместно использовать единственный экземпляр, создан­ ный для открытия этой контейнерной базы данных. В больш и н стве случаев обратное утверждение также справедливо: контей нер­ ная база данн ых или база данных с единственным владельцем будет иметь только один работающий с ней экзем пляр. Однако в особом случае применения техноло­ гии Oracle RAC ( Real Application Clusters - кластеры для реальных приложений), которая позволяет Oracle функционировать на множестве ком пьютеров в кластери­ зоваиной среде , мы можем иметь несколько экземпляров, одновременно монтиру­ ющих и открывающих одну базу дан н ых, которая размещена на наборе разделяемых физических дисков. Это позволяет получать доступ к единствен ной базе данных из м ножества разных ком пьютеров в одно и то же время . Технология Oracle RAC пред­ назначена для систем с исключительно высокой готовностью и обладает потенциа­ лом для проектирования в высшей степени масштабируемых решений. Давайте начнем с рассмотрения простого примера. П редположим , что мы толь­ ко что установили Oracle 1 2с версии 1 2. 1 .0. 1 на компьютер, функционирующий под управлением UN IX/Linux. Было установлено только программное обеспечение без каких-либо начальных баз данн ых и других компонентов - т.е . ничего кроме про­ граммнаго обеспечения. Команда pwd отображает текущий рабочи й каталог, dЬ s (в Windows это был бы каталог dat aba s e ) , и команда ls -1 показывает, что он пуст. Он не содержит ни файла ini t . o r a , н и файлов S P F I LE (файл ы хранимых параметров, которые под­ робно обсуждаются в главе 3 ) : [ or a 1 2 c r 1 @del lpe dЬs ] $ pwd /home /ora 1 2 cr l /app/ora 1 2 c r 1 /product / 1 2 . 1 . 0 /dЬhome_1 /dbs [ or a 1 2 c r 1 @de1 lpe dЬs ] $ l s - 1 total О С помощью команды p s (process status - состоя ние процесса) можно вы вести и нформацию обо всех процессах, выпол няемых пользователем ora 1 2 c r l (владелец программ наго обеспечения Oracle в этом случае) . В дан ный момент процессы базы данных Oracle вообще отсутствуют: [ or a 1 2 c r 1 @del lpe dЬs ] $ ps -aef 1 grep ora 1 2 c r 1 0 0 : 0 0 : 0 0 s u - ora 1 2 c r 1 root 1 8 3 92 1 5 4 1 6 О 1 4 : 3 1 pt s / 1 ora 1 2 c r 1 0 0 : 0 0 : 0 0 -bash 1 8 4 0 1 1 8 3 9 2 О 1 4 : 3 1 pt s / 1 o ra 1 2 c r 1 1 8 4 6 1 1 8 4 0 1 О 1 4 : 3 4 pts / 1 0 0 : 0 0 : 0 0 p s -aef ora 1 2 cr 1 1 8 4 62 1 8 4 0 1 О 1 4 : 3 4 pts / 1 0 0 : 0 0 : 0 0 grep ora 1 2 c r 1 Об зо р архитектуры 1 17 Теперь можно ввести i p c s - команду U N IIX/Liпux для отображен ия сведе н и й об устройствах взаимодействия между п роцессами, таких как разделяемая память, семафоры и т.п . В настоящее время в системе такие устройства не используются : [ ora 1 2 c r 1 @ de1 lpe dbs ) $ ipcs а ---- - - Shared Memory Segments - - - - - - - - - - - - - Сегмен ты разделяемой памяти - - nattch status key s hmid owner pe rms bytes ---- - - Semaphore Arrays - - - - - - - - - - - - - Ма ссивы сема форов - - - - - - nsems semid key owner perms ------ Me ss age Queues - - - - - - - - - - - - - Очереди сообщений - - - - used - bytes me s sages owner msqid pe rms key - Те перь запустим S Q L* Plus ( интерфейс командной строки O racle) и подкл ю­ чимся к базе данных как s y s dba (учетная запись, которая позволяет делать в базе данных практически что угодно) . Изначально, предполагая , что переменная среды ORACLE_S I D еще не установлена, вы увидите следующий вывод: [ ora 1 2 c r 1 @ del lpe dЬs ) $ sqlplus 1 as s ysdt)a SQL* Plus : Release 1 2 . 1 . 0 . 1 . 0 Production on Mon Sep 2 1 4 : 3 5 : 52 2 0 1 3 Copyri ght ( с ) 1 9 8 2 , 2 0 1 3 , Oracle . All ri ghts rese rved . ERROR : ORA- 1 2 1 62 : TNS : net se rvice nате i s inco п:ectl y speci f ied ОПМБКА : ORA- 1 2 1 62 : ТNS : имя сетевой службы указано некорректно Эта ошибка происходит из-за того, что программному обеспечению базы дан н ых ничего не известно о том , куда следует подключаться. Когда производится подключе­ ние, программ ное обеспечение Oracle ищет строку соединения TNS (сетевое соеди­ нение). Если строка не предоставлена, как в этом примере, Oracle ищет переменную среды ORACLE_S I D (в Windows также проверяется параметр реестра O RACLE_S I D) . Переменная ORACLE_S I D - это " идентификатор сайта" Oracle, т.е. своего рода ключ мя получения доступа к экземпляру. Если установить ORACLE_S I D, как показано ниже: [ o ra 1 2 c r 1 @del lpe dЬs ) $ export ORACLE_S Ш=ora 1 2 c то подключение будет успешным и SQL* Plus сообщит о соединении с простаиваю­ щим экземпляром: [ o ra 1 2 c r 1 @ del lpe dbs ) $ sqlplus 1 as s ysdt)a SQL* Plus : Release 1 2 . 1 . 0 . 1 . 0 Production on Mon Sep 2 1 4 : 3 6 : 5 4 2 0 1 3 Copyri ght ( с ) 1 9 8 2 , 2 0 1 3 , Oracl e . Al l r i ghts rese rved . Connected to an idle instance . Подключено к простаивающему экземпляру. SQL> 1 18 Глава 2 Прямо сейчас наш " экземпляр " состоит только из процесса сервера Oracle, кото­ рый в следующем выводе выделен полужирным. Пока еще не существует н и выде­ ленной разделяемой памяти , н и других процессов. SQL> ! ps - a e f 1 g rep ora 1 2 c r 1 root 1 8 3 92 1 5 4 1 6 О 1 4 : 3 1 pts / 1 o ra 1 2 c r 1 1 8 4 0 1 1 8 3 92 О 1 4 : 3 1 pts / 1 ora 1 2 c r 1 1 8 4 7 4 1 8 4 7 3 О 1 4 : 3 6 pts / 0 0 0 : 0 0 : 0 0 su - ora 1 2 cr 1 0 0 : 0 0 : 0 0 -bash 0 0 : 0 0 : 0 0 . .. /dЬhome_1 /Ьin / s q1p1us as sysdba ora12cr1 18475 18474 О 14 : 36 ? 0 0 : 00 : 00 oracleora12c (DESCRIPTION= (LOCAL=YES) (ADDRESS= (PROTOCOL=Ьeq) ) ) ora 1 2 c r 1 1 8 4 8 2 1 8 4 7 4 О 1 4 : 3 8 pts / 0 ora 1 2 cr 1 1 8 4 8 3 1 8 4 8 2 ora 1 2 c r 1 1 8 4 8 4 1 8 4 8 2 О 1 4 : 3 8 pts / 0 О 1 4 : 3 8 pts / 0 0 0 : 0 0 : 0 0 /Ьin/bash с ps - ae f 1 g rep ora 1 2 c r 1 0 0 : 0 0 : 0 0 ps - ae f 0 0 : 0 0 : 0 0 grep o ra 1 2 cr 1 - SQL> ! ipcs - а - - - - - - Sha red Memo ry Segments - - - - - - Сегменты разделяемой памя ти - - s tatus nattch key s hmid owner perms bytes - - - - - - S emaphore Arrays - - - - - - - - - - - - - Ма ссивы сема форов - - - - - - s emid owner perms nsems key - - - - - - Mes sage Queue s - - - - - - - - - - - - - Очереди сообщений - - - - owne r perms used - bytes mes sages msqid key На заметку! В среде Windows програм м ное обеспечение Oracle выполняется как единствен­ ный п роцесс с потокам и ; в ы не увидите отдел ьных процессов , как в среде U N IX/Liп ux. Более того, потоки Windows не будут иметь таких же и м е н , как у только что показанных процессов. Я специально испол ьзую здесь U N IX/Linux, чтобы м ы могли различать индиви­ дуальные п роцессы и четко " видеть" их. В этом выводе команды p s и нтересно отметить процесс по имени oracl eora l 2 c . Как б ы тщательно вы н и просматривали систему, вы не найдете исполняемого фай­ ла с таким именем. На самом деле этот процесс запускается двоичным файлом $ 0RACLE HOME / b i n / o ra c l e . Н а заметку! П редполагается, что в переменной среды ( в U N IX/Linux) или в параметре реест­ ра (в Windows) по имени ORACLE_ НОМЕ был указан полностью определенный путь к месту, где установлено программное обеспечение Oracle . Разработчики Oracle п росто переименовывают этот процесс при его загрузке в память. Именем единственного процесса Oracle, которы й выполняется прямо сей­ час (наш выделенный серверный процесс, о котором речь пойдет позже ) , является o rac l e $ 0RACLE S I D. Такое соглашение об именовании позволяет очень легко уви­ деть, каким образом процессы ассоциируются с экземплярами . Итак, попробуем за­ пустить экземпляр: _ Обзор архитектуры 1 19 SQL> sta rtup ORA- 0 1 0 7 8 : fai 1 u re i n p roce s s ing system pa rameters LRМ- 0 0 1 0 9 : could not open parameter f i l e ' /home /ora 1 2 c r 1 /app /ora 1 2 c r 1 / product / 1 2 . 1 . 0 /dbhome_1 /dЬ s / initora 1 2 c . ora ' ORA- 0 1 0 78 : отказ при обра ботке системных параметров LRМ-001 0 9 : не удалось открыть файл параметров ' /home/ora 1 2cr1 /app/ ora 1 2cr1 /produ ct/1 2 . 1 . 0/dЬhome_ 1 /dЬs/i n i tora 1 2c . ora ' Обратите внимание на ошибку, возниЮIIу ю из-за отсутствия файла ini toral2c . ora. Этот файл , в простаречи и называемый файлом i n i t . ora или более точно файлом параметров, является еди нственным файлом, который должен существовать, что­ бы можно было запустить экземпляр - необходимо и меть либо файл п араметров (простой плоский файл , который будет более подробно описан ниже ) , л ибо файл хранимых параметров. Давайте создадим файл параметров и поместим в него м и н имальную и нформа­ цию, требуемую для запуска экзем пляра базы данн ых . (Обычно приходится задавать значительно больше параметров, в ч исле которых размер блока базы данных, место­ положения управляющих файлов и т. п . ) По умолчани ю этот файл находится в ката­ логе $0RACLE_HOME /dЬs и имеет и мя i n i t $ { 0RACLE_S I D } . or a : [ ora 1 2 c r 1 @ de l lpe dbs ] $ c d $ 0RACLE НОМЕ /dЬ s [ ora 1 2 c r 1 @ de l lpe dbs ] $ echo dЬ name=ora 1 2 c > initora 1 2 c . ora [ ora 1 2 c r 1 @del 1pe dbs ] $ cat initora 1 2 c . ora dЬ name=ora 1 2 c Теперь возвратимся в SQL*PLus: [ ora 1 2 c r 1 @del lpe dbs ] $ sqlplus 1 as s ys dЬa SQL* Plus : Release 1 2 . 1 . 0 . 1 . 0 Production on Mon Sep 2 1 4 : 4 2 : 2 7 2 0 1 3 Copyright ( с ) 1 9 8 2 , 2 0 1 3 , Oracle . Al l rights rese rved . Connected to an idle instance . Подключено к простаивающему экземпляру. SQL> startup nomount ORACLE ins tance sta rted . Экземпляр ORACLE запущен . Total System Globa1 Area 329895936 Вся системная глобальная обла сть 2287 960 Fixed S i ze Фиксированный размер 272631464 VariaЬle S i ze Переменный размер 5 0 3 3 1 64 8 Database Bu ffers Буферы базы данных 4 64 4 8 64 Redo Bu ffers Журнальные буферы bytes bytes bytes bytes bytes Мы используем опцию nomount команды s t a rtup, т. к. пока еще нет базы дан ­ ных, подлежащей монтировани ю (все опции команд запуска и завершения можно найти в документации по SQL* Plus) . 1 20 Глава 2 На за метку! В среде Windows nеред заnуском команды s t a r t up nонадобится выnолнить оnератор создания службы с nрименением утилиты o radim . е х е . Теперь м ы получили то, что можно было бы назвать экземпляром. Все фоновые процессы, необходимые для действительного запуска базы дан н ых, такие как мони­ тор процессов (process moпitor - pmon), процесс записи в журнал ( l gwr) и т.д. (все они подробно описаны в главе 5), запущен ы . Давайте взглянем на н их: SQL> ! ps - ae f 1 grep o ra 1 2 c r 1 root 1 8 3 9 2 1 5 4 1 6 О 1 4 : 3 1 pts / 1 0 0 : 0 0 : 0 0 su - ora 12 c r 1 0 0 : 0 0 : 0 0 - bash ora 1 2 c r 1 1 8 4 0 1 1 8 3 92 О 1 4 : 3 1 pts / 1 0 0 : 0 0 : 0 0 r1wrap /home /ora 1 2 c r 1 /app/ ora 1 2 c r 1 1 8 4 9 9 1 8 4 0 1 О 1 4 : 4 2 pts / 1 o ra 1 2 c r 1 /product / 1 2 . 1 . 0 /dЬhome_1 /bi n / s qlplus 1 as sysdЬa ora 1 2 c r 1 1 8 5 0 0 1 8 4 9 9 О 1 4 : 4 2 pts / 0 0 0 : 0 0 : 0 0 /home / o ra 1 2 c r 1 /app / o ra 1 2 cr 1 /product / 1 2 . 1 . 0 /dЬhome_1 /bi n / s qlplus as s ysdЬa ora 1 2 c r 1 1 8 5 0 8 0 0 : 0 0 : 0 0 ora_pmon_ora 1 2 c 1 О 14 : 43 ? ora 1 2 c r 1 1 8 5 1 0 1 О 14 : 43 ? 0 0 : 0 0 : 0 0 ora_psp0_ora 1 2 c ora 1 2 c r 1 1 8 5 1 2 0 0 : 0 0 : 0 0 ora vktm ora 1 2 c 1 О 14 : 43 ? ora 1 2 c r 1 1 8 5 1 6 1 О 14 : 43 ? 0 0 : 0 0 : 0 0 ora_genO _ora 1 2 c ora 1 2 c r 1 1 8 5 1 8 0 0 : 0 0 : 0 0 ora mman ora 1 2 c 1 О 14 : 43 ? ora 1 2 c r 1 1 8 52 2 0 0 : 0 0 : 0 0 ora_diag_ora 1 2 c 1 о 14 : 43 ? 1 о 14 : 43 ? ora 1 2 c r 1 1 8 5 2 4 0 0 : 0 0 : 0 0 o r a dЬrm ora 1 2 c 1 о 14 : 43 ? 0 0 : 0 0 : 0 0 o r a diaO ora 1 2 c ora 1 2 c r 1 1 8 5 2 6 ora 1 2 c r 1 1 8 5 2 8 0 0 : 0 0 : 0 0 o r a dЬwO ora 1 2 c 1 о 14 : 43 ? ora 1 2 c r 1 1 8 5 3 0 1 о 14 : 43 ? 0 0 : 0 0 : 0 0 ora_lgwr_ora 1 2 c 0 0 : 0 0 : 0 0 ora_ckpt_o ra 1 2 c 1 о 14 : 43 ? ora 1 2 c r 1 1 8 5 3 2 ora 1 2 c r 1 1 8 5 3 4 0 0 : 0 0 : 0 0 o ra_l g 0 0_ora 1 2 c 1 о 14 : 43 ? 1 о 14 : 43 ? 0 0 : 0 0 : 0 0 ora_lg 0 1 _ora 1 2 c ora 1 2 c r 1 1 8 5 3 6 0 0 : 0 0 : 0 0 o r a smon ora 1 2 c ora 1 2 c r 1 1 8 5 3 8 1 о 14 : 43 ? 1 о 14 : 43 ? 0 0 : 0 0 : 0 0 o r a- reco-ora 1 2 c ora 1 2 c r 1 1 8 5 4 0 1 о 14 : 43 ? 0 0 : 0 0 : 0 0 ora_l reg_ora 1 2 c ora 1 2 c r 1 1 8 5 4 2 0 0 : 0 0 : 0 0 o r a mmon ora 1 2 c 1 о 14 : 43 ? ora 1 2 c r 1 1 8 5 4 4 0 0 : 0 0 : 0 0 o r a mmnl o ra 1 2 c ora 1 2 c r 1 1 8 5 4 6 1 о 14 : 43 ? 0 0 : 0 0 : 0 0 oracleora 1 2 c ora 1 2 c r 1 1 8 5 4 7 1 8 5 0 0 о 1 4 : 4 3 ? ( DESCRI PT ION= ( LOCAL=YES ) ( ADDRESS= ( PROTOCOL=beq ) ) ) 0 0 : 0 0 : 0 0 /bin/bash - с ps - ae f 1 ora 1 2 c r 1 1 8 5 6 6 1 8 5 0 0 О 1 4 : 4 5 pts / 0 grep ora 1 2 c r 1 ora 1 2 c r 1 1 8 5 67 1 8 5 6 6 О 1 4 : 4 5 pts / 0 0 0 : 0 0 : 0 0 p s - ae f 0 0 : 0 0 : 0 0 grep ora 1 2 cr 1 ora 1 2 c r 1 1 8 5 68 1 8 5 6 6 О 1 4 : 4 5 pts / 0 Кроме того, команда i p c s впервые сообщает о б использовании разделяемой па­ мяти и семафоров - двух важных устройств взаимодействия между процессам и в системе U N IX/Linux: SQL> ! ipcs - а - - - - - - Shared Memo ry Segments - - - - - - - - - - - - - Сегменты разделяемой памя ти - - pe rms owner shmid ke y O x 1 0 d1 c 8 9 4 1 3 0 7 4 4 3 5 o ra 1 2 c r 1 660 ОхО О О О О О О О 1 3 1 0 7 2 0 4 o ra 1 2 cr 1 660 nattch bytes 1 0 4 8 5760 38 322 961408 1 9 status Обзор архитектуры ------ Semaphore Arrays - - - - - - - - - - - - - Массивы сема форов - - - - - - key s emid owner pe rms 660 ora 1 2 c r 1 Oxfc4 6e 8 3c 4 2 5 9 8 6 o ra 1 2 c r 1 660 Oxfc4 6e 8 3d 4 5 8 7 5 5 o ra 1 2 c r 1 660 Oxfc4 6e 8 3 e 4 9 1 5 2 4 ora 1 2 c r 1 660 Oxfc4 6e 8 3 f 5 2 4 2 9 3 ora 1 2 c r 1 660 Oxfc4 6e 8 4 0 5 5 7 0 62 - - - - - - Me s s age Queues - - - - - - - - - - - - - Очереди сообщений - - - - key owner msqid pe rms 1 21 n s ems 171 171 171 171 171 used - bytes me s sages Обратите внимание, что пока еще нет какой-либо "базы данных " . М ы имеем имя базы данных (в созданном файле параметров) , но не саму базу данных. Если попро­ бовать "смонтировать" эту базу данных, то попытка закончится неудачей, посколь­ ку база данных попросту не существует. Давайте создади м ее. Как уже упоми налось, создание базы данных Oracle требует выполнения совсем небольшага кол ичества действий, но судите сам и : SQL> create databa s e ; Database created . База данных создана . Это де йствител ьно все , что нужно для создания базы данных. Однако в ре­ альности, скорее всего , п ридется применять н есколько более сложную форму команды C REAT E DATABAS E , т. к . п рограмм ному обеспеч е н и ю Oracle потребует­ ся указать, куда поместить оперативные журн альные файл ы , файлы данных, уп­ равля ющие файл ы и т. п . Но мы теперь имеем полноцен но фун кцион и рующую базу дан н ых. Для построе н ия остал ь н ы х словаре й дан н ых, испол ьзуе м ых п р и повседневной работе ( н апример, представл е н ия наподобие ALL O B J E C T s п ока что не присутствуют в этой базе дан н ых) , понадобится е ще запустить сценар и й $ 0RACLE НОМЕ / rdЬms 1 admi n / c a t a l og . s q l и другие сценар и и , связанные с ката­ логами, однако сама база данных уже существует. Мы можем применять простой за­ прос к некоторым представления м V$ в Oracle, в частности V$ DATAFILE, V$ LOGFILE и V$CONTROL FILE, для получения списка файлов, образующих эту базу данных: _ _ SQL> select nате from v$data fi1e ; NАМЕ /home /o ra 1 2 c r 1 / app /ora 1 2 c r 1 /product / 1 2 . 1 . 0 /dЬhome_1 /dЬ s /dbs 1 o ra 1 2 c . dЬ f /home /ora 1 2 c r 1 / app /ora 1 2 cr 1 /product / 1 2 . 1 . 0 /dЬhome_1 /dЬ s /dЬx 1ora 1 2 c . dЬ f /home/ ora 1 2 cr 1 /app/ora 1 2 cr 1 /product / 1 2 . 1 . 0 /dЬhome_1 /dЬs /dЬu 1 o r a 1 2 c . dЬ f SQL> select memЬer from v$logfi l e ; MEMBER /home/ ora 1 2 c r 1 / app/o ra 1 2 c r 1 /product / 1 2 . 1 . 0 /dЬhome_1 /dЬs / l og 1 o ra 1 2 c . dЬ f /home /ora 1 2 cr 1 / app /ora 1 2 cr 1 /product / 1 2 . 1 . 0 /dЬhome_1 /dЬ s /log2ora 1 2 c . dЬ f SQL> select nате from v$ cont ro l f i l e ; NАМЕ /home /ora 1 2 c r 1 / app /ora 1 2 c r 1 /product / 1 2 . 1 . 0 /dЬhome_1 /dЬs /cnt rlora 1 2 c . dЬ f 1 22 Глава 2 СУБД Oracle использовал а стандартные значен ия параметров для сбора всей сведений воедино и создан ия базы данн ых в виде набора постоян н ых файлов. Если закрыть эту базу данных и попробовать открыть ее снова, выяснится , что это невоз­ можно: SQL> alter databas e clos e ; Database a l t e red . База данных изменена . SQL> a l te r database open ; a lt er databas e open * ERROR at l ine 1 : ORA - 1 6 1 9 6 : databas e has been p reviou s l y opened and closed ОПМБКА в строке 1 : ORA - 1 61 9 6 : база данных была ранее открыта и закрыта Н а протяжен и и периода своего существования экземпляр может монтировать и открывать максимум одну базу дан н ых - с единственным владельцем или контей­ нерную. Вспомните , что экземпляр состоит просто из процессов и разделяемой па­ мяти . Они запущен ы и работают. Все, что мы сделали - закрыл и базу данных, т.е. физические файл ы . Чтобы открыть текущую или любую другую базу данных, потре­ буется отбросить этот экземпляр (завершить) и создать новы й . Н иже перечислены моменты , которые необходимо запомнить. • Экземпляр - это набор фоновых процессов и разделяемой памяти . • База данных (с единственным владельцем или контейнерная ) - это обособ­ ленная коллекция данных, хранящихся на диске. • Экзем пляр всегда может монтировать и открывать только одну базу данных. Как будет показано позже , он может предоставлять доступ к нескольким подключа­ емым базам дан н ых, а также "открывать" и "закрывать" их много раз; тем не менее, экземпляр будет открывать только одну обособленную базу данных. • База данных может быть смонтирована и открыта одн им или большим числом экземпляров (с применением RAC) , а количество экземпляров, монтирующих одну базу дан н ых , со временем может изменяться . Как отмечалось ранее, в большинстве случаев экземпляр и база данных связаны отношением " один к одному". Вероятно, именно этим обстоятельством объясняет­ ся путан ица в использован и и этих терминов. Согласно личному опыту большинства л юдей, база данных - это экземпляр, а экзем пляр - база данных. Однако во многих тестовых средах это не так. Скажем , на моем диске может присутствовать пять отдельных баз данных. На тестовом компьютере в каждый кон ­ кретны й момент времени фун кцион ирует тол ько оди н экземпляр Oracle, но база данн ых, к которой он обращается , может отличаться изо дня в ден ь или от часа к часу в зависимости от текущих потребностей . Просто и мея множество разных фай ­ лов конфигураци и , я могу монтировать и открывать любую одну из этих баз данных. Таким образом , существует оди н экземпляр, но м ного баз дан ных, только одна из которых доступна в каждый конкретный момент. Об зор архите ктуры 1 23 Итак, если теперь кто-то заговорит об экземпляре, то вы будете знать, что реч ь идет о процессах и памяти Oracle. Когда же упоми нают базу дан н ых , то имеют в виду физические файлы , которые хранят данные. База данн ых может быть доступна из множества экземпляров, но в каждый момент времени экземпляр будет предо­ ставлять доступ только к одной базе данных (с еди нственным владельцем или кон­ тейнерной) . С исте м ная глобал ьн ая област ь и ф оновые процессы Теперь вы, пожалуй , готовы к восприяти ю абстрактной картины того, на что по­ хожи экземпляр и база данных Oracle (рис. 2. 1 ). Э кземпляр База данны х Рис . 2 . 1 . Экземпляр и база данных Oracle На рис. 2. 1 показаны экземпляр и база данных Oracle в своей простейшей форме. В Oracle имеется большая область памяти под называнием SGA (system global area системная глобальная область) , которая применяется , например, для выпол не н ия следующих действи й . • Поддержка многих внутрен н и х структур дан ных, к которым должн ы обра­ щаться все процессы . • Кешированне дан ных с диска; буферизация журнальных данных для восстановления перед их зап исью на диск. • Хранение планов SQL-операторов, прошедших разбор. • И Т.Д. В Oracle существует набор процессов, которые " присоединен ы " к этой области SGA, и механизмы , с помощью которых производится присоединение, зависят от операционной системы. В среде U N IX/Linux процессы будут физически присоеди­ няться к большому сегменту разделяемой памяти - области памяти , выделенной в операционной системе, которая одновременно может быть доступна м ножеству процессов (в основном , с использованием фун кций s hmget ( ) и s hmat ( ) ) . 1 24 Глава 2 В среде Windows для выдел е н и я памяти эти процессы п росто вызы вают С-функцию ma l l oc ( ) , поскольку в действительности они являются потоками внут­ ри одного большого процесса и, следовательно, разделяют одно и то же пространс­ тво виртуальной памяти . СУБД Oracle также и меет набор файлов, в которых процессы ил и потоки базы данн ых выполняют чтение и запись (чтение или запись в эти файлы имеют право осуществлять только процессы Oracle) . В архитектуре с единственным владельцем эти файлы содержат все табличные данные, и ндексы, времен н ые области , журналы для восстановления , код P L/SQL и т.д. В архитектуре с множеством владельцев кон­ тейнерная база данных будет хранить все относя щиеся к Oracle метаданные, данные и код; дан ные вашего приложен ия будут содержаться отдельно в подключаемой базе данн ых, которую нам еще предстоит создать. База дан ных, созданная нами ранее, по умолчани ю я вляется базой данн ых с единственным владельцем; доступные под­ ключаемые базы данн ых в ней отсутствуют. Обособленный набор файлов вкл ючает файлы данных, которые содержат и данные Oracle, и данные приложения . Если вы запустили Oracle в системе U N IX/Li nux и вводите команду p s , то уви­ дите множество выполняющихся физических процессов с разнообразными имена­ ми. Примеры были продемонстрированы ранее при изучен и и pmon , smon и других процессов. Эти процессы рассматриваются в главе 5, а пока достаточно знать, что обычно их назы вают фоновыми процессами Oracle. Это постоя нно существующие процессы , которые образуют экземпляр, и вы будет видеть их с момента запуска эк­ земпляра до момента завершения его работы . И нтересно отметить, что это именно процессы , а не отдел ьные программы. В системе UN IX/Linux есть только оди н двоич н ы й исполняемый файл Oracle; он и меет множество " воплоще н и й " в зависимости от того, что во время запуска ему было указано делать. Тот же самы й двоичный исполняемый файл , который запус­ калея для создания процесса o r a _pmon o r a 1 2 c , также применялея для создания процесса o r a _c kp t o r a 1 2 c . Существует только одна двоичная исполняемая про­ грамма, которая называется просто o ra c l e . Она всего лишь выполняется много раз с разными именам и . В среде Windows с п омощью и нструмента p s t a t (часть набора Wi ndows Х Р Resource Кit; есл и вы е щ е н е располагаете эти м набором , поищите в И нтернете " pstat download" ) мы найдем только оди н процесс - o r a c l e . е х е . Опять-таки , в среде Windows существует только один двоичный исполняемый файл ( o r a c l e . е х е ) . Внутри этого процесса м ы обнаружим множество потоков, представляющих фоно­ вые процессы Oracle . С помощью ps l i s t ( или любого другого аналогичного инструмента, такого как t a s k l i s t , которы й поступает со многими версиями Windows) эти потоки можно просмотреть: C : \WINDOWS > pstat Pstat ve r s i on 0 . 3 : memo ry : 5 2 3 7 6 0 kb uptime : О 1 : 37 : 54 . 37 5 Page Fi l e : \ ? ? \C : \page fi le . sys Current S i ze : 67 8 9 1 2 kЬ Total Used : 2 2 8 3 1 6 kb Pea k Used 6 0 5 4 8 8 kb Memory : 5 2 3 7 60К Ava i l : 2 2 4 4 92К TotalWs : 2 7 6932К InRam Kernel : 8 7 2К Р : 2 0 540К Commit : 4 1 8 4 68К/ 372 2 0 4 К Limi t : 1 1 6 9 0 4 8 K Peak : 1 1 8 7 3 9 6K Pool N : 1 0 620K Р : 2 4 5 8 8 К Об зор архитектуры 1 25 User Time Kernel Time Ws Fau l t s Commit P r i HndThd Pid Name File Cache 5б8б0 2348193 о 1 0 I d1e Proce s s о о о 28 0 : 00 : 0 0 . 00 0 1 : 02 : 23 . 1 0 9 4 S ys tem 2В в б94 52 43В5 32 0 : 00 : 0 0 . 00 0 0 : 0 1 : 50 . 8 12 172 11 224 1 9 3 3 3 2 sms s . exe бО 0 : 00 : 00 . 0 1 5 0 : 00 : 00 . 1 0 9 1 9 В О 1 3 3 9 б 1 4 5 5 бc s r s s . exe 2144 3 3 4 б7 0 : 00 : 33 . 2 34 0 : 00 : 32 . 0 4 б 7 7 92 1 3 5 7 В 2 0 5 B Owinlogon . exe 3б84 бВ 1 1 0 : 00 : 0 0 . 34 3 0 : 00 : 0 1 . 7 50 1бВО 9 2 7 5 1 б б 2 4 s ervices . exe 3022 194В 0 : 00 : 00 . 078 0 : 00 : 01 . 7 34 3932 9 3 б 3 2 5 б 3 бl s as s . exe 595В 1В9б 0 : 00 : 00 . 2 1 8 0 : 00 : 03 . 5 1 5 5 92 ВО4 в 2 5 1 B 1 2vmacthlp . exe во 0 : 00 : 00 . 015 0 : 00 : 00 . 078 301б B 2 B s vchos t . exe 2 7 б5 в 195 17 141б 0 : 00 : 00 . 093 0 : 00 : 00 . 359 17б4 в 244 10 B 9 бs vchos t . exe 1340 35бб О : О О : О О . О б2 0 : 0 0 : 0 0 . 4 5 3 О : ОО : ОО . В2 В 0 : 0 1 : 1 б . 5 93 9б32 363В7 1170В В 1 2 0 б 5 9 1 0 2 4 svchos t . exe 0 : 00 : 00 . 04 б О : ОО : ОО . б4 0 1020 2315 1300 В В1 6 1 1 0 0 svchos t . exe 0 : 00 : 00 . 0 1 5 0 : 00 : 00 . 2 3 4 73б 2330 1 4 92 В 1 б 5 11 1 2 7 2 s vchos t . exe 0 : 00 : 00 . 015 0 : 00 : 00 . 2 1В 12В 1959 37 В В В 1 1 7 10 1 4 4 0 spool s v . exe 0 : 00 : 01 . 312 0 : 00 : 1 9 . В2В 13б3б 3 5 5 2 5 1 4 7 32 В 575 19 1 9 52explorer . exe 0 : 0 0 : 0 0 . 2 5 0 0 : 0 0 : 0 0 . 93 7 95б 1705 В5б В 2 9 1 2 2 BVМwareTray . exe О : О О : О О . В 1 2 0 : 0 0 : 0 4 . 5 б2 1044 4б19 3ВОО В 1 б 5 4 2 4 0VМwareUser . exe 0 : 00 : 0 0 . 0 1 5 0 : 00 : 00 . 1 5 б ВВ 1049 1 1 92 В В В 4 3 9 бs vchos t . exe 0 : 00 : 00 . 109 0 : 00 : 04 . б40 744 1229 2432 В В1 3 4 б 0cvpnd . exe 0 : 00 : 02 . 0 15 0 : 00 : 12 . 07 В 147б 1757В 1 9 0 4 1 3 139 3 60 0VМwareService . exe 0 : 00 : 0 0 . 03 1 0 : 0 0 : 00 . 0 93 124 1004 1172 В 1 0 5 б 1 92 a l g . exe 0 : 0 0 : 0 0 . 0 62 0 : 0 0 : 0 0 . 9 3 7 2б4В 1 3 977 2 2 б 5 б 8 1 0 1 3 7 2 0 TNS LSNR . EXE В 5 5 0 2 9 1 92 B o racle . exe 0 : 04 : 0 0 . 35 9 0 : 02 : 57 . 7 34 1 б 4 В 4 4 2 0 0 9 7 В 5 2 7 9 1 бВ 231б 2720 в 141 б7 3 6 б 1 2 2 4ms iexec . exe 0 : 00 : 00 . 0 93 0 : 0 0 : 00 . 4 37 3 4 1 B 0 4 cmd . exe 1 9 92 701 в 2 б бВ 0 : 00 : 00 . 015 0 : 00 : 00 . 031 1 1 1 2 B 5 бpstat . exe в 33б 235 9б4 0 : 00 : 00 . 015 0 : 00 : 00 . 000 Здесь мы видим (в колонке Thd) , что в единствен ном процессе Oracle содержатся 29 потоков. Эти потоки представляют то, что в среде U N IX/Linux является процес­ сами pmon, a rch, l gwr и т.д. Каждый из них представляет отдельную часть про­ цесса Oracle. П родвигаясь далее по отчету p s t a t , м ы можем просмотреть дополни­ тельные сведения о каждом потоке: - pid : 7 B B pri : В Hnd : 5 5 0 P f : 2 0 0 9 7 B 5 Ws : 1 б 4 В 4 4 К oracle . exe tid pri Ctx Swtch S t rtAddr User T ime Kernel Time State 4 9В 9 б 5 1 7 СВ 1 0 7 0 5 0 : 0 0 : 0 0 . 0 0 0 0 : 0 0 : 0 0 . 2 0 3 Wai t : Executive 1 б4 В 9 1 7 СВ 1 0 б F 9 0 : 0 0 : 0 0 . 0 0 0 0 : 0 0 : 0 0 . 0 0 0 Wai t : UserReques t а6В В 4 2 7СВ 1 0 б F9 0 : 00 : 00 . 000 0 : 00 : 00 . 03 1 Wai t : UserReque s t В этом выводе отсутствуют " имена" потоков, подобные отображаем ы м в U N IX/ Linux (ora_pmon_o ra 1 2 c и т. п . ) , но есть идентификаторы потоков ( T i d) , приорите ­ т ы ( P r i ) и другая учетная и нформация о потоках операционной системы. П од кл юч е ние к Oracle В этом разделе мы рассмотрим механизмы, лежащие в основе двух наиболее рас­ пространенных методов обслуживания запросов сервером Oracle: подключения к вы­ деленному серверу и подключения к разделяемому серверу. Мы выясним, что происходит на компьютерах клиента и сервера для установки подключений, чтобы можно бьmо выполнить вход и делать действительную работу в базе данных. Наконец, мы кратко 1 26 Глава 2 рассмотрим установку соединений TCP/I P (TCP/I P - это основной сетевой протокол, используемый для подключения к базе данных Oracle по сети) и особен ности работы проелушивающего процесса, который отвечает за установление физического подклю­ чен ия к серверу, в случае подключений к вьщеленному и разделяемому серверу. В ыделенный сервер Диаграмма н а рис. 2 . 1 и следующий вы вод команды ps представляет картину того, как база данн ых Oracle по имени ora 1 2 c r l может выглядеть непосредственно после запуска. [ t kyte @del lpe ] $ ps -aef 1 g r ep _$0RACLE_S I D ora 1 2 c r 1 1 9 6 0 7 1 о 15 : 1б ? 0 0 : 0 0 : 0 0 ora_pmon_ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora_psp0_ora 1 2 c r 1 ora 1 2 c r 1 1 9 6 0 9 1 о 15: 1б ? 0 0 : 0 0 : 0 0 ora vktm ora 1 2 cr 1 ora 1 2 c r 1 1 9 6 1 1 1 о 15 : 1б ? 1 о 15: 1б ? 0 0 : 0 0 : 0 0 ora_gen0_ora 1 2 cr 1 ora 1 2 c r 1 1 9 б 1 5 0 0 : 0 0 : 0 0 ora mman ora 1 2 c r 1 ora 1 2 c r 1 1 9 6 1 7 1 1 15 : 1б ? ora 1 2 cr 1 1 9 6 2 1 0 0 : 0 0 : 0 0 ora_diag_ora 1 2 c r 1 1 о 15 : 1б ? 0 0 : 0 0 : 0 0 ora dЬrm ora 1 2 cr 1 1 о 15: 1б ? ora 1 2 c r 1 1 9 б 2 3 0 0 : 0 0 : 0 0 ora diaO ora 1 2 cr 1 ora 1 2 c r 1 1 9 б 2 5 1 о 15 : 1б ? ora 1 2 c r 1 1 9 б 2 7 1 о 15 : 1б ? 0 0 : 0 0 : 0 0 ora dЬwO ora 1 2 cr 1 ora 1 2 cr 1 1 9 6 2 9 1 о 15 : 1б ? 0 0 : 0 0 : 0 0 ora_lgwr_ora 1 2 c r 1 ora 1 2 c r 1 1 9 б 3 1 1 о 15 : 1б ? 0 0 : 0 0 : 0 0 ora_ckpt_ora 1 2 cr 1 ora 1 2 cr 1 1 9 б 3 3 1 о 15: 1б ? 0 0 : 0 0 : 0 0 ora_l gO O_or a 1 2 c r 1 1 о 15: 1б ? ora 1 2 c r 1 1 9 б 3 5 0 0 : 0 0 : 0 0 ora_1g0 1_or a 1 2 c r 1 ora 1 2 c r 1 1 9 б 3 7 0 0 : 0 0 : 0 0 ora smon ora 1 2 c r 1 1 о 15: 1б ? ora 1 2 c r 1 1 9 б 3 9 0 0 : 0 0 : 0 0 ora reco ora 1 2 cr 1 1 о 15: 1б ? 0 0 : 0 0 : 0 0 ora_1 reg_ora 1 2 cr 1 ora 1 2 c r 1 1 9 б 4 1 1 о 15 : 1б ? 0 0 : 0 0 : 0 0 ora mmon ora 1 2 cr 1 ora 1 2 c r 1 1 9 6 4 3 1 1 15: 1б ? 0 0 : 0 0 : 0 0 ora mmnl ora 1 2c r 1 ora 1 2 c r 1 1 9 6 4 5 1 о 15: 1б ? 1 о 15 : 1б ? ora 1 2 c r 1 1 9 б 4 7 0 0 : 0 0 : 0 0 ora d O O O ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora s O O O ora 1 2 cr 1 1 о 15 : 1б ? ora 1 2 cr 1 1 9 б 4 9 0 0 : 0 0 : 0 0 ora tmon ora 1 2 cr 1 ora 1 2 c r 1 1 9 6 б l 1 о 15 : 1б ? 1 о 15: 1б ? ora 1 2 c r 1 1 9 6 б 3 0 0 : 0 0 : 0 0 ora t t O O ora 1 2 c r 1 ora 1 2 cr 1 1 9 б б 5 0 0 : 0 0 : 0 0 ora smco ora 1 2 cr 1 1 о 15 : 1б ? ora 1 2 c r 1 1 9 б б7 1 о 15 : 1б ? 0 0 : 0 0 : 0 0 ora fbda ora 1 2 cr 1 ora 1 2 c r 1 1 9 6 7 1 1 о 15 : 1б ? 0 0 : 0 0 : 0 0 ora_aqpc_ora 1 2 cr 1 1 о 15 : 1б ? ora 1 2 c r 1 1 9 б 7 5 0 0 : 0 0 : 0 0 ora_cj q0_ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora wO O O ora1 2 cr 1 1 о 15 : 1б ? ora 1 2 c r 1 1 97 0 5 1 о 15 : 1б ? 0 0 : 0 0 : 0 0 ora_qm02_ora 1 2 c r 1 ora 1 2 c r 1 1 97 0 8 1 о 15 : 1б ? 0 0 : 0 0 : 0 0 ora_qm0 3_ora 1 2 cr 1 ora 1 2 c r 1 1 9 7 1 0 ora 1 2 c r 1 1 97 1 2 0 0 : 0 0 : 0 0 ora_q 0 0 2_ora 1 2 c r 1 1 о 15: 1б ? 0 0 : 0 0 : 0 0 ora_q0 0 3_ora 1 2 cr 1 ora 1 2 c r 1 1 9 7 1 4 1 о 15 : 1б ? 1 97 2 0 1 5 4 1 б О 1 5 : 1 б pts / 1 0 0 : 0 0 : 0 0 grep _ora 1 2 c r 1 t kyte Если вы вошли в эту базу данных с применением вьщеленного сервера, то увидите новый процесс ( ил и поток в другой операционной системе), который был создан как раз для вашего обслуживания: OPS$ TKYTE@ORA1 2CR1> ! ps - aef 1 grep $ 0RACLE_S I D ora 1 2 c r 1 1 9 6 0 7 1 о 15 : 1б ? 0 0 : 0 0 : 0 0 ora_pmon_ora 1 2 cr 1 0 0 : 0 0 : 0 0 ora_pspO_ora 1 2 c r 1 1 о 15: 1б ? ora 1 2 c r 1 1 9 б 0 9 0 0 : 0 0 : 0 0 ora vktm ora 1 2 cr 1 ora 1 2 c r 1 1 9 б 1 1 1 о 15: 1б ? 0 0 : 0 0 : 0 0 ora_gen0_ora 1 2 c r 1 ora 1 2 c r 1 1 9 б 1 5 1 о 15: 1б ? Об зо р архитектуры 1 о 15 : 16 ? ora 1 2cr1 1 9 6 1 7 ora 1 2 c r 1 1 9 62 1 1 о 15 : 16 ? 1 о 15: 16 ? ora 1 2 c r 1 1 9 6 2 3 ora 1 2 c r 1 1 9 6 2 5 1 о 15: 16 ? 1 о 15 : 16 ? ora 1 2 c r 1 1 9 6 2 7 1 о 15: 16 ? ora 1 2 c r 1 1 9 6 2 9 1 о 15: 16 ? ora 1 2 c r 1 1 9 6 3 1 ora 1 2 c r 1 1 9 6 3 3 1 о 15: 16 ? ora 1 2 c r 1 1 9 6 3 5 1 о 15: 16 ? ora l 2 c r 1 1 9 6 37 1 о 15: 16 ? ora l 2cr1 1 9 6 3 9 1 о 15 : 16 ? ora 1 2 c r 1 1 9 6 4 1 1 о 15 : 16 ? ora 1 2 c r 1 1 9 6 4 3 1 о 15 : 16 ? ora 1 2 c r 1 1 9 6 4 5 1 о 15 : 16 ? ora 1 2 c r 1 1 9 6 4 7 1 о 15 : 16 ? ora 1 2 c r 1 1 9 6 4 9 1 о 15 : 16 ? ora 1 2 c r 1 1 9 6 6 1 1 о 15: 16 ? ora 1 2 c r 1 1 9 6 6 3 1 о 15: 16 ? ora 1 2 c r 1 1 9 6 6 5 1 о 15 : 16 ? ora 1 2 cr 1 1 9 6 6 7 1 о 15: 16 ? ora1 2 c r 1 1 9 6 7 1 1 о 15: 16 ? ora 1 2 c r 1 1 9 6 7 5 1 о 15: 16 ? ora 1 2c r1 1 97 0 5 1 о 15 : 16 ? ora 1 2 c r 1 1 97 0 8 1 о 15: 16 ? 1 о 15 : 16 ? ora 1 2 c r 1 1 97 1 2 ora 1 2 c r 1 1 9 7 1 4 1 о 15 : 16 ? 1 97 3 2 1 9 7 3 1 О 1 5 : 1 7 pts / 0 t kyte 1 27 0 0 : 0 0 : 0 0 ora пunan ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora_diag_ora 1 2 c r 1 0 0 : 0 0 : 0 0 o r a dЬrm ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora diaO o r a 1 2 c r 1 0 0 : 0 0 : 0 0 ora dЬwO ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora_l gwr_ora 1 2 cr 1 0 0 : 0 0 : 0 0 ora_c kpt_ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora_l g 0 0_ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora_l g 0 1_ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora smon ora 1 2 c r 1 0 0 : 0 0 : 0 0 o r a reco ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora_l reg_ora 1 2 c r 1 0 0 : 0 0 : 0 0 o r a пunon ora 1 2 c r 1 0 0 : 0 0 : 0 0 o r a пunnl o ra 1 2 c r 1 0 0 : 0 0 : 0 0 ora dO O O ora 1 2 cr 1 0 0 : 0 0 : 0 0 o r a s O O O ora 1 2 c r 1 0 0 : 0 0 : 0 0 o r a tmon ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora t t O O ora 1 2 c r 1 0 0 : 0 0 : 0 0 o r a smco ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora fbda ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora_aqpc_ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora_cj q0_ora 1 2 c r 1 0 0 : 0 0 : 0 0 o r a w O O O ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora_qm0 2_ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora_q 0 0 2_ora 1 2 c r 1 0 0 : 0 0 : 0 0 ora_q 0 0 3_or a 1 2 c r 1 0 0 : 0 0 : 0 0 / home /ora 1 2 c r 1 / app /ora 1 2 c r 1 / product / 1 2 . 1 . 0 /dbhome_ 1 / bin / s qlplus - - - - - - - - - - - - - - 0 0 : 00 : 0 0 oracleora12cr1 ora12cr1 1 9733 1 9732 О 15 : 1 7 ? (DESCRIPTION= (LOCAL=YES) (ADDRESS= ( PROТOCOL=Ьeq) ) ) tkyte 1 9 7 4 4 1 9 7 4 2 О 1 5 : 1 8 pts / 0 0 0 : 0 0 : 0 0 grep o ra 1 2 c r 1 Теперь в ы можете отметить наличие нового процесса o r a c l e o r a 1 2 c r l , создан­ ного как процесс выделенного сервера. После выхода из базы данных дополнитель­ ный поток/процесс исчезнет. Все сказанное подводит нас к следующей итерации диаграмм ы . П одключение к базе данных Oracle в ее наиболее распространенной конфигурации в результате дает то, что показано на рис. 2.2. Как уже отмечалось, обычно Oracle будет создавать новый п роцесс после вхо­ да пользователя в базу дан н ых. В общем случае это называют конфигурацией с выделенным сервером , поскольку процесс сервера будет предназн ачен специально для обслуживания пользователя на п ротяжен и и всего е го сеанса. Для каждого се­ анса будет создаваться новый выделенный сервер. П о определен и ю такой процесс выделенного сервера не является частью экзем пляра. Клиентский процесс (любая программа, пытающаяся подключиться к базе дан ных) будет напрямую взаимодейс­ твовать с этим выделенным сервером через определен н ы й сетевой канал, подобны й сокету TC P/I P. Именно этот процесс сервера будет прин имать от пользователя SQL­ команды и выполнять их. При необходимости он будет ч итать файлы данных и ис­ кать нужные данные в кеще базы данных. Он будет выполнять операторы обновле­ ния и код PL/SQL. Его единствен ное назначение - реагировать на отправляемые пользователем SQ L-операторы. 1 28 Глава 2 Э кземп л я р Кл иентское подключ ение Рис. 2 . 2 . Тиn ичная конфигурация с в ыделенны м сервером Р азделяемый сервер СУБД O racle может также при н имать подключен ия в стиле так назы ваемого раз ­ деляемого сервера , при котором для каждого нового подключения пользователя до­ полн ительный поток или новы й процесс UN IX/Linux появляться не будет. На заметку! В версиях Oracle 7.х и Oracle 8.х разделяемый сервер назывался MTS (multithread­ ed server - многопоточный сервер ) . Это устаревшее название больше не используется. В случае разделяемого сервера Oracle применяет пул разделяемых nроцессов для большой груnп ы пользователей . Разделяемые серверы являются просто механизмом орган изации пула подключе н и й . Вместо использования для 1 0 000 сеансов базы дан н ы х 1 0 000 выделенных серверов (что предполагает наличие многочисле нных процессов или потоков) разделяем ы й сервер позволяет иметь небольшой процент от этого множества процессов или потоков, которые совместно применяются (раз­ деляются) всеми сеансами . В итоге у Oracle появляется возможность подключения значительно большего ч исла пол ьзователей , чем это было бы в противном случае . Компьютер может не справиться с нагрузкой , связанной с управлением 1 0 000 про­ цессами , но управление 1 00 или 1 000 процессами - вполне реальная задача. В ре­ жиме разделяемого сервера разделяемые процессы в основном запускаются базой данн ых и появляются в списке p s . Существенное различие между подключениями посредством разделяемого и вы­ деленного сервера состоит в том , что клиентский процесс , подключен ный к базе дан н ых, н икогда не обращается н апрямую к разделяемому серверу, как это было бы в случае выделен ного сервера. Он не может взаимодействовать с разделяемым сер­ вером , потому что фактически этот процесс является разделяемым. Для совместного исnользования таких процессов необходим еще оди н механизм, через которы й nро­ изводится взаимодействие. В Oracle для этой цели применяется процесс ( или набор процессов) , назы ваемый диспетчером. Клиентский процесс будет обмениваться дан­ ными с процессом диспетчера по сети . П роцесс диспетчера поместит заnрос кли ­ ента в очередь запросов внутри области SGA (в этом заключается одна и з многих Об зо р архитектуры 1 29 функций SGA) . П ервый незанятый разделяемый сервер примет этот запрос и обра­ ботает его (например, запросом мог бы служить U P DAT E т S ET Х=Х + 5 WHERE У=2 ) . П о завершении этой команды разделяемый сервер поместит ответ в очередь ответов вызывающего диспетчера. Процесс диспетчера будет отслеживать эту очередь и, об­ наружив результат, переправит его клиенту. В общих чертах прохождение запроса к разделяемому серверу выглядит так, как показано на рис. 2 . 3 . Рис . 2 . 3 . Шаги выполнения запроса к разделяемому серверу На рис. 2 . 3 видно, что клиентское подключение отnравляет запрос диспетчеру. Диспетчер сначала поместит этот заnрос в очередь запросов внутри SGA ( l ) . Первый свободны й разделяемый сервер извлечет этот заnрос из очереди (2) и обработает его. Когда разделяемый сервер завершит обработку, ответ (коды возврата, данн ые и т.д. ) будет помещен в очередь ответов ( 3 ) , после чего извлечен оттуда диспетчером (4) и передан обратно клиенту. С точки зрения разработчи ка подключение посредством выделенного сервера концептуально ничем не отличается от подключен ия с использованием разделяемо­ го сервера. Архитектурно они существенно разнятся , но приложе н и ю это не видно. Теперь, когда вы понимаете, что собой представляют подключения через выделенный и через разделяемый сервер, могут возникнуть перечисленные ниже вопросы. • Как осуществить собственно подключение? • Как запустить выделенный сервер? • Как связаться с диспетчером? Ответы зависят от применяемой платформ ы , но общее в последующих разделах приведено общее описание процесса. Механизмы подключения через ТСР/ IP Рассмотрим наиболее распространенный случай обмена данными по сети - за­ прос сетевого подключения через ТСРji P. В этом случае клиент находится на одном компьютере, а сервер - н а другом, и оба компьютера подключен ы к сети TC P/I P. Все действия и н ициируются кли ентом . Клиент делает запрос на подключение к базе данн ых, используя клиентское программное обеспечение Oracle (набор готовых nрограммных и нтерфейсов приложения , или АРI - интерфейсов) . Например, клиент выдает следующий запрос: 1 30 Глава 2 [ t kyte @ de l lpe - ] $ s qlplus s co t t / t iger@ora 1 2 cr 1 S QL * P lus : Release 1 2 . 1 . 0 . 1 . 0 Production o n Mon Sep 2 1 5 : 2 5 : 0 6 2 0 1 3 Copyright ( с ) 1 98 2 , 2 0 1 3 , Oracl e . Al l rights reserved . Last Succe s s ful login t ime : Mon Sep 0 2 2 0 1 3 1 3 : 4 4 : 4 9 - 0 4 : 0 0 Conne cted to : Oracle Database 1 2 с Enterprise Edi tion Release 1 2 . 1 . 0 . 1 . 0 - 64bit Production With the Pa r t i tioning , OLAP , Advanced Ana lytics and Real Application T e s t i ng opt ions SCOTT@ORA12CR1> Н а заметку! Присутствующая здесь строка o r a 1 2 c r 1 уникальна для моей конфигураци и . У меня есть заnись t n s name s . o r a (о которой речь nойдет н иже ) n o имени or a 1 2 c r l . Это строка соединения TNS, которая указывает н а существующий , установленный и скон­ фигурированный э кземnляр Oracle 1 2с Release 1 в моей сети . В ы будете nриме нять собс­ твенные строки соединений TNS, уникальные для вашей систе м ы . Клиентом я вляется программа SQL* Pius, s co t t / t i g e r - это и мя пользователя и пароль, а o r a 1 2 c r l - имя службы TN S . Аббревиатура TN S расш ифровы вается как Tгansparent Network Substrate (прозрачн ая сетевая среда) и представляет собой " базисное" Программное обеспечение, встроен ное в клиент Oracle, которое обра­ батывает удаленные подключен ия , обеспечивая возможность одноранговых комму­ н и каций . Строка подключен ия TN S сообщает программному обеспечению Oracle, каким образом следует подключаться к удаленной базе данных. Как правило, кли­ ентская программа, выпол ня ющаяся на локальном комп ьютере, будет читать файл по имени t n s name s . o r a . Это простой текстовый конфи гурационный файл , кото­ рый обычно расположен в каталоге $0RACLE_HOME/network/ admin ( $0RACLE_HOME представляет пол н ы й путь к каталогу с установленной копией Oracle). Он будет со­ держать записи, подобные показанным н иже: SCOTT@ORA 1 2 CR 1 > ! cat $0RACLE HOME /networ k/ admi n / tnsnames . ora # tns name s . ora Netwo r k Conf i guration File : /home / or a 1 2 cr 1 / app /ora 1 2 c r 1 /product / 1 2 . 1 . 0 / dЬhome_l /ne twor k/ admin/ tnsname s . ora # Generated Ьу Oracle con figuration tool s . # tn snames . ora Файл конфигурации сети : # Сгенерировано инструментами конфигурирования Ora cle . ORA1 2 CR1 = ( DESCRI PT I ON = (ADDRES S = ( PROTOCOL = ТСР ) ( HOST = s omehost . somewhere . com ) ( РОRТ = 1 5 2 1 ) ) ( CONNECT_DATA = ( SERVER = DED I CAT E D ) ( SERVICE_NAМE = ora 1 2 cr 1 ) Эта конфигурационн ая и н формация п озволяет клиентской программе Oracle сопоставить указанную строку соединения TN S ( o r a 1 2 c r l ) с более полезной ин­ формацие й : именем хоста, номером порта на этом хосте, через которы й проелуши­ вающий процесс будет принимать подключения, именем службы базы дан н ых на этом хосте , к которой нужно подключиться , и т.д. И мя службы представляет группы Обзор архитектуры 1 31 приложений с общи ми атрибутами , порогами уровня обслуживания и п риоритета­ ми. Круг экземпляров, предлагающих службу, прозрачен для приложения , и каждый экзем пляр базы дан н ых может быть зарегистрирован проелуши вающим процессом как готовы й предоставлять множество служб. Таким образом, службы отображаются на экземпляры физической базы данн ых и позволя ют адми нистратору базы данных связать с ними определенные пороговые значен ия и приоритеты . Эта строка, o r a l 2 c r l , может быть распознана и другим и способами . Например, ее можно было бы распознать с использованием службы имен, предоставляемой сер­ вером LDAP (Lightweigt Directшy Access Protoco1 - облегчен ный протокол доступа к каталогам) , которы й по своему назначен и ю похож на сервер DN S ( Domain Name Server - сервер доменных имен), выполняющий преобразование имен хостов. Однако применение t n s narne s . o r a распространено в большинстве небольших и средних систем (измеряемых числом хостов, нуждающихся в подключении к базе данных), в которых количество копий такого файла конфигурации помается управлению. М етод Easy Connect Метод Easy Соппесt (легкое подключение) позволяет подключаться к удаленной базе дан ­ н ы х без необходимости в наличии файла tns name s . ora ( ил и других м етодов распознава­ ния местоположения базы дан ных). Если известны имя хоста, серве р , порт и имя службы , то и х можно в вести непосредственно в командной строке. Синтаксис в ы глядит следующим образом : sqlplus имя_nоль зователя@ [ / / ] хост [ : порт ] [ /имя_службы] [ : сервер] [ /имя_экземпляра ] Например, предположим , что и менем хоста является he s t a , номером порта - 1 52 1 , а име­ нем службы - ora 1 2 c r l . Тогда подключиться можно так: $ sqlplus u s e r / pa s s @ he s ta : 1 5 2 1 /o ra 1 2 c r l Метод Easy Соппесt удобно использовать в ситуациях, когда п роводится поиск и устранение проблем с подключаемостью или нет доступного файла tn sname s . ora (либо других путей распознавания удаленного подкл ючения). Теперь, когда клиентской программе известно, куда подключаться, она откроет сокетное подключение TCP/I P к серверу с именем хоста s orneho s t . s ornewhe r e . сот через порт 1 52 1 (стандартный номер порта для прослушивания ; можно сканфигури­ ровать запуск и на другом порте). Если администратор базы данных сервера устано­ вил и сканфигурировал сеть Orac1e Net, а проелуш ивающий процесс проелуши вает порт 1 52 1 на предмет поступле н ия запросов о подключ е н и и , то это подключен и е может быть принято. В сетевой среде на сервере будет действовать процесс, называ­ емый проелушивающим процессом TNS. И менно этот проелуши вающий процесс будет обеспечивать физическое подключение к базе данн ых. П олучив входящий запрос на подключение, проелуши вающи й процесс первым делом анализирует запрос. Затем, основываясь на собственных файлах конфигурации , он либо отклоняет запрос (на­ пример, из-за отсутствия такой службы или по причине запрета I Р-адресу подклю­ чаться к этому хосту) , л ибо принимает и производит подключение. При подключен и и посредством выделенного сервера проелуш и вающий процесс создаст выделен н ы й сервер . В системе U N IX/Linux это осуществляется с помо­ щью системных вызовов f o r k ( ) и е х е с ( ) (единственным способом создания но- 1 32 Гл ава 2 воrо процесса после и н ициализации в U N I X/Linux является применение f o r k ( ) ) . Новый п роцесс выделен ного сервера наследует подключение, установленное про­ елуш ивающим процессом , в результате появляется физическое подкл ючение к базе дан н ых. В среде Windows проелушивающий процесс запрашивает у процесса базы дан ных создание нового потока для подключен ия . После того как этот поток со­ здан, клиент " перенаправляется " на него, устанавли вая в итоге физическое подклю­ чение. Описанные выше действия для системы U N IX/Linux можно проиллюстриро­ вать диаграммой , представленной на рис. 2.4. Рис . 2.4. Проелуш и вающий п роцесс и подключения посредством выделенного сервера Тем не менее, проелуш и вающий процесс будет вести себя по-другому, есл и в ыдается зап рос н а подкл юче н и е с и с п ол ьзован и е м разделяемого сервера. Проелушивающему процессу известен диспетчер (ил и диспетчеры ) , фун кциониру­ ющий в экзем пляре. При получении запросов на подключение проелуш ивающи й процесс будет выбирать п роцесс диспетчера из пула доступ ных диспетчеров. Он л ибо возвратит клиенту информацию о подкл ючен и и , описывающую то, как кли­ ент может подкл ючиться к процессу диспетчера, либо, если это возможно, передаст подкл ючение процессу диспетчера (поведение зависит от верси й операционной системы и СУБД, но конечн ы й результат будет таки м же) . Когда проелушивающий процесс отправляет и нформацию о подключе н и и , это делается потому, что он вы­ полняется на хорошо известном хосте и порте этого хоста, но диспетчеры также прин и мают подкл ючения от произвол ьно назначаемых портов на дан ном сервере . Диспетчер осведомлен об этих произвольных назначениях портов диспетчером и са­ мостоятельно выберет диспетчера. Затем кл иент отключается от проелуши вающего процесса и подключается непосредстве нно к диспетчеру. В итоге устанавли вается физическое подключение к базе дан ных. Оп исанн ы й процесс показан на рис. 2.5. П од кл ю ч ае м ые базы дан ных Н ачиная с версии Oracle Database 1 2с, появился новы й подход к трактовке кон­ цепции "база дан н ых" . До сих пор в этой главе мы был и сосредоточены на базах данных с еди нствен­ н ы м владельцем или контейнерных базах данных и их связью с экземплярами (база дан ных может иметь один и более экземпляров; экземпляр будет монтировать и от­ крывать максимум одну базу данных). Об з о р архитектуры 1 33 Рис. 2 . 5 . П роелуш и вающий п роцесс и подключен и я посредством разделяемого сервера Теперь мы готовы взгля нуть на концепцию подключаемой базы дан ных - что она собой представляет и как работает. П одключаемые базы дан н ых в архитектуре с множеством владельцев являются необособленными наборами файлов дан ных, ко­ торые состоят исключительно из данных и метаданных приложений. В них нет ка­ ких-л ибо специфичных дЛЯ Oracle данных/метаданных; эта информация находится в контейнерных базах данных, которые в текущи й момент ассоци ированы с н и м и . Для того чтобы подключаемую базу данных можно было использовать и запраши­ вать, она должна быть связан а с контей нерной базой дан ных. Эта контейнерная база данных будет содержать в себе тол ько данные и метаданные Oracle - просто информацию, которая нужна Oracle дЛЯ "запуска " . П одкл ючаемые базы дан н ы х хранят "остальные" метаданные и дан ные базы данных. Таким образом , например, контейнерная база дан н ых могла бы и меть определе­ ние пользователя S Y S (метаданные для пользователя SYS), а также скомп илирован­ ный И ИСХОДНЫЙ КОд дЛЯ объектов, подобных DBMS_OUT PUT И UTL_F I LE . С другой стороны, подключаемая база данных содержала бы определение схемы приложения, такой как sсотт, все метаданные, описывающие таблицы в схеме sсотт, весь исход­ ный код PL/SQL дЛЯ схем ы sсот т , все привилегии , выданные схеме s с о т т , и т.д. Одним словом , подключаемая база данных имеет все, что описывает набор схем при­ ложения - метаданные дЛЯ учетных записей, метаданные для табли ц в этих учетных записях и действительные данные для этих таблиц. П одключаемая база дан н ых яв­ ляется обособленной в отношении содержащихся в ней учетных записей приложе­ ния, но чтобы иметь возможность "откры ваться " и запрашиваться, ей необходима контейнерная база дан ных. Следовательно, можно сказать, что подключаемая база данных " необособленна"; дЛЯ открытия и работы с ней требуется кое-что еще . Подключаемая база дан ных не откры вается экземпляром напрямую - взамен должен быть запущен экземпляр Oracle , который смонтирует и откроет контей нер­ ную базу дан ных. П осле того, как экземпляр контей нера запущен , а контейнерная база дан н ых открыта, она может откры вать до 250 отдельных подкл ючаемых баз дан ных. Каждая такая подключаемая база дан н ых действует так, как есл и бы она была "автономной " базой данн ых. То есть все они выглядЯт так, как будто бы явля­ ются обособленными, автономными базами данных "с единственным владельцем " . 1 34 Глава 2 Одн ако все они совместно испол ьзуют одну и ту же контей нерную базу данных и экземпляр контейнера. Н иже перечислены основные цел и , на достижен ие которых направлена подклю­ чаемая база данных, т.е . архитектура с множеством владельцев. • Для заметного умен ьшения объема ресурсов, необходимых при разме щении многих баз данных - многих приложений - на единственном хаете. • Для сокращен ия объема работ по обслуживанию, выполняемых адм ин истра­ тором баз данных в отношении множества баз данных - множества приложе­ ний - на единственном хаете. Снижение коэ фф и циента использования ресурсов Как вы уже видел и , после запуска экземпляра Oracle появляется много ассоци­ ированн ых с ним процессов. В главе 5 вы ознакомитесь с каждым из них и узнаете, что они делают; но уже сейчас несложно заметить, что каждый экземпляр подде­ рживается с помощью 20-40 процессов. Если вы попытаетесь настроить 50 баз дан­ ных с единственным владельцем (где каждая база данных имеет связан ный с ней эк­ земпляр или собствен н ы й экземпляр) , то получите свыше \ 000 процессов, которые нужны просто для запуска этих баз данных! Это порождает исключительно высокую нагрузку на операционную систему, как в плане создания множества процессов, так и в плане управлен ия ими. Кроме того, каждый экзем пляр может иметь собствен ную область SGA. В главе 4 будет показано, что находится в SGA, но достаточно сказать, что там присутствует множество дублированных дан н ых. Каждая область SGA будет иметь кешираванную копи ю овмs _OUT PUT в своем разделяемом пуле, а также журнальный буфер и много других дублирующих структур данн ых. Благодаря подключаемым базам данн ых , вы получаете возможность разделить относящиеся к приложению метаданные, пользователей , данные, код и тому подоб­ ное, но при этом и збежать наличия избыточных экземпляров. Другими словами , вы можете и меть еди нственный экземпляр с одной контей нерной базой дан н ых (мета­ данные, код и данн ые O racle ) , предоставляющей доступ к 250 подключаемым базам данн ых, в каждой из которых размещается отдельное приложение. Вместо \ 000 про­ цессов для поддержки 50 разных баз дан ных приложений у вас будет возможность располагать 5 1 базой дан н ых (одной контейнерной и 50 базам и данных приложе­ н и й ) , которые разделяют те же самые 20-40 процессов. Это крупное снижение ко­ эффициента утилизации ресурсов. Вдобавок все они разделяют общую область SGA, позволяя совместно испол ьзовать п овторя ющиеся части 50 отдельных областей SGA, которые существовали бы в противном случае. В целом размер одной области SGA, которую понадобилось бы выдел ить для этих 50 баз данных приложений, бу­ дет меньше сум марного размера 50 отдельных областей SGA, которые пришлось бы выделять иначе. Сокра щение объема работ по обслуживани ю Если адми н истратору баз дан н ых было поручено управление 50 отдельными ба­ зами данных в рамках архитектуры с еди нственным владельцем, у него окажется 50 баз данных, для которых придется выполнять действия по резервному копированию, Об зор архитектуры 1 35 мон иторингу, управлен и ю , исправлению, модерн изации и т.д. Каждая база данных должна будет управляться независимо от всех остальных. В архитектуре с множест­ вом владельцев имеется одна "база данных", для которой необходимо проводить ра­ боты , связанные с резервным коп ированием , мониторингом, управлением, исправ­ лением, модерн изацией и т. п . Н апример, действие по и справлению базы данн ых Oracle включает обновление исполняемых файлов Oracle (обновление экземпляра) и обновление метаданных Oracle - словаря данных Oracle. Когда администратор баз дан ных применяет исправления к базе данных, он совершенно не затрагивает свя­ зан ные с Приложениями метадан ные, схемы, данные, код и т.д. - он воздействует только на экземпляр Oracle и метадан ные, данные и код Oracle. В условиях архитектуры с множеством владельцев все 50 подключаемых баз дан­ ных, содержашие дан ные приложе н и й , совместно используют общий экземпляр; поэтому при внесени и адми н истратором баз данн ы х исправлений в экзем пляр ко всем 50 подключаемым базам данных применяются исправления со стороны экзем­ пляра. Аналогично, когда адми н истратор баз данных вносит исправлен ия в конте й ­ нерную базу данных, т.е. обособленн ы й набор файлов, которые хранят метадан ные, код и данные Oracle, эти исправления наследуются всеми 50 подключаемыми базами данных. Они разделяют метаданные, код и данные Oracle . Таким образом, действие по исправлению еди нстве н ной контей нерной базы данных фактически приводит к применению исправлений ко всем связанным подключаемым базам данных. Есл и эта ситуация нежелательна (исправление всех 50 баз данных за раз), можно воспользоваться альтернативным подходом . Вместо внесен ия исправлен и й в сущес­ твующую контей нерную базу данных адм и н истратор может просто создать новую контей нерную базу данных, которая уже исправлена. Теперь есть два экземпляра Oracle с двумя контейнерными базами данн ых: одна версии Х, а другая версии У. Для применения исправлений к подключаемой базе данных адми н истратор "отключает" ее от контей нерной базы дан н ых, к которой она в текущий момент присоединена. Отключение приводит к созданию ХМ L-файла манифеста с оп исан иями файлов, принадлежащих к подключаемой базе данных. После этого администратор " подклю­ чает" эти подключаемые данные к новой конте йнерной базе данных. Действие по отключению подкл ючаемой базы данных я вляется легковесным и очень быстрым необходимо лишь создать ХМ L-файл манифеста. Действие по подключению тоже отличается легковесностью и высокой скоростью - ХМ L-файл манифеста ч итает­ ся , файл ы , которые ассоциированы с подключаемой базой данных, регистрируют­ ся в контейнерной базе данных и подключаемая база данных может использоваться снова. П одключаемая база данных исправляется или модернизируется просто путем ее подключения к контейнерной базе дан н ых, к которой уже применены исправле­ ния . В итоге администратору приходится управлять, исправлять, модернизировать и выполнять другие действия по отноше н и ю к одной конте йнерной базе данн ых. Подключаемые базы дан ных всего лишь наследуют эту работу. Отличия подкл ю чае м ой ба з ы дан н ых С точки зрения разработчика подключаемая база данн ых ничем не отличается от базы данных с единственным владельцем. Приложеине подключается к такой базе данных тем же самым способом, как это делалось для базы данных с единственным владельцем в ранних выпусках. Предшествующие примеры создания подключений с использованием 1 36 Глава 2 разделяемых и вьщеленных серверов по-прежнему применимы. Оrличия касаются лежа­ щей в основе архитекrуры - наличие единственного экземпляра для многих подключа­ емых баз данных и, как результат, снижение коэффициента использования ресурсов на сервере, а также простота управления для администратора баз данных. С точ ки зрения адми н истратора баз дан н ых в методах администрирования базы данных появилось много изменений - позитивных изменений. Например, если ад­ министратор сканфигурировал контейнерную базу данных для RAC, то любой под­ ключаемой базе дан н ых, относящейся к этому контейнеру, будут доступны возмож­ ности RAC . Аналогичная ситуация и со средством Data Guard, резервными копиями RMAN и т.д. У адми н истратора баз дан ных есть оди н экземпляр, предназначенный для конфигурирования и работы с ним, а не по одному экземпляру на приложение, как было в прошлом . Р ез ю ме Н а этом краткое знакомство с архитектурой Oracle завершено. В этой главе были определены тер м и н ы экземпляр, база данных и подключаемая база данных, а также показано, каким образом выполняется подключение к базе данн ых посредством вы­ деленного ил и разделяемого сервера. На рис. 2.6 обобщен ы материалы, раскрытые в главе , и показано взаимодействие с базой данных клиента, применяющего под­ ключение через разделяемы й сервер, и клиента, которы й использует подключение посредством выделенного сервера. На нем также видно, что экземпляр Oracle может применять оба типа подключен и й одновременно. (В действительности база данных Oracle всегда поддерживает подключен ия с использованием выделенного сервера даже если она сконфигурирована для разделяемого сервера. ) Теперь можно приступать к более подробному анализу файлов, образующих базу данных, и процессов, действующих на сервере - выполняемых ими функций и вза­ и модействия друг с другом . Вы также готовы к ознакомлению с областью SGA, ее содержимым и назначением. Следующая глава начнется с описания типов файлов, которые Oracle применяет для управления данными, и ролью, которую играет каж­ дый ти п . Рис . 2 . 6 . Обзор подключений ГЛ А В А 3 Ф айл ь1 в этой главе мы рассмотрим восемь главных тиnов файлов, которые образуют базу данных и экземпляр. Перечислен н ые н иже файлы связаны с экземпляром. • Файлы параметров (parameter file). Эти файлы указы вают экзем пляру базы данных Oracle, где искать управляющие файлы , а также задают набор п арамет­ ров инициал изации , которые определяют размеры ряда структур памяти и т.д. Мы рассмотрим два доступных варианта хранения файлов параметров. • Трассировочные файлы (trace file). Эти диагностические файл ы создаются процессом сервера по большей части в ответ на возникновение некоторых не­ обычн ых ошибок. • Сигнальный файл (alert file). Этот файл подобен трассировочным файлам , но содержит и нформацию об "ожидаемых" событиях, а также служит един ы м централизован ным файлом для хранения оповеще н и й адми н истратора базы данных о многих событиях, связанных с базой данных. Следующие файлы образуют базу данн ых. • Файлы данных (data file). Эти файлы предназначен ы для базы данных; они хранят таблицы, и ндексы и все остальные сегменты . • Временные файлы (temp file). Эти файлы испол ьзуются для выполнения дис­ ковых сортировок и в качестве временного хранили ща. • Управляющие файлы (control file). Эти файлы указы вают м естоп оложе н и е файлов данн ых, времен ных файлов, журнальных файлов повторения действий (файлов с измененными данными), а также содержат другие важные метадан­ ные об их состоян и и . Они также хранят и нформаци ю резервных копи й , под­ держиваемую диспетчером восстановлен ия ( Recovety Manageг - RMAN ) . • ,Журнальные файлы повторения действий (redo log file). Эти файлы представля­ ют собой журналы транзакций . • Файлы паролей (password file). Эти файлы применяются для аутентификации пользователей , выполняющих адми нистративные действия через сеть. Мы не будем подробно обсуждать файлы такого типа, поскольку они не я вляются обязательным компонентом любой базы данных Oracle . 1 38 Глава 3 В Oracle J Og и последующих версиях существует пара необязательных типов фай­ лов, которые используются Oracle для содействия ускоренным операциям резервно­ го коп ирования и восстановления . • Файл отслеживания изменений (change-tracking file). Этот файл обеспеч ивает по-настоя щему И н крементное резервное копирован ие дан н ых Oracle . Он не обязательно должен находиться в области для быстрого восстановления ( Fast Recovery Area} , но из-за того, что он связан исключ ительно с резервным ко­ пированием и восстановлением дан н ых, м ы рассмотрим его в контексте этой области . • Файлы ретроспективного журнала (flashback log file). Эти файлы хранят " пред­ шествующие образы " блоков базы дан ных для содействия команде FLAS HBACK DATABAS E . М ы также взглянем н а другие тип ы файлов, обычно связанных с базой дан ных. • Файлы дампа (dump (DMP) file). Эти файлы генерируются утилитой экспорта базы данных (Export) и используются утилитой импорта базы данных ( l mport). Следует отметить, что в текущих выпусках Oracle утилита Export устарела - пол­ ностью поддерживается только утилита l mport. Она поддерживается для того, чтобы обеспечить перемещение данн ых из старых выпусков Oracle (где утилита Export поддерживалась полностью) в более новые выпуски базы данных. • Файлы помпы данных (Data Pump file). Такие файлы генерируются в Oracle процессом Data Pump Export (EX P D P} и потребляются процессом Data Pump l mport ( IM P D P ) . Этот файловы й формат может также создаваться и использо­ ваться внешними табли цами . • Плоские файлы (flat file). Это простые старые файл ы , которые можно про­ сматривать в текстовом редакторе. Обычно их применяют для загрузки данных в базу. И з всех перечислен н ых файлов наиболее важными я вля ются файл ы дан ных и журнальные файлы повторения действий , т. к. они содержат дан ные, к сбору кото­ рых вы приложили большие усили я . Утеря любых или даже всех остал ьн ых файлов не приведет к безвозвратной утрате данн ых. Утеря журнальных файлов может при­ вести к потере некоторых данных. Утеря файлов данных и их резервн ых коп ий не­ избежно приведет к безвозвратной потере дан ных. Далее м ы рассмотрим каждый из упомянутых типов файлов: где они обычно рас­ полагаются , как и менуются и что в них можно ожидать найти . Ф айлы пара м етров С базой данн ы х Oracle связано много разн ых файлов параметров, например, файл t n s n ame . o r a на рабоче й стан ц и и клиента ( используемый для " нахожде­ н ия " сервера в сети ) , файл l i s t e n e r . o r a на сервере (предназначен н ы й для на­ чал ьного запуска проелуш и вающего процесса) , файлы s q l n e t . o r a , cma n . o r a и l dap . o r a и это далеко не пол н ы й перечень. Однако наиболее важным из них я вляется файл параметров базы данных. Как было продемонстрировано в главе 2, без него невозможно даже запустить экземпляр. Остальные файл ы также важны; - Файл ы 1 39 все они имеют отношение к работе в сети и подкл юче н и ю к базе данн ых. Тем не менее, они выходят за рамки нашего обсужде н и я . И нформаци ю по их установке и конфи гурирован и ю можно найти в руководстве адми н истратора сетевых служб (Net Services Administrator's Guide) . Как правило, разработчи ку не приходится настра­ ивать эти файлы - все уже сделано. Файл параметров базы дан н ы х обыч н о назы вают i nit-файлом или файлом i n i t . o r a . Это объясняется его исторически сложившимен стандартным именем, которое выглядит как i n i t < O RACLE_S I D > . o r a . Я назы ваю это и мя " и сторичес­ ки сложившимся " , потому что в версии Oracle9i Release 1 был введен чрезвычай­ но усовершенствованный метод сохранен ия параметров настрой ки базы данных файл параметров сервера, или просто S P F I L E . По умолчани ю этот файл и меет и мя s p f i l e <ORACLE_ S I D> . o r a . М ы рассмотрим оба вида файлов параметров. На заметку! Для тех, кто не знаком с термином S I D или ORAC L E S I D, здесь nриводится его nолное определение. Аббревиатура S I D означает site identifier ( идентификатор сайта ) . В среде U N IX/Linux идентифи катор S I D и ORACLE_HOME ( м есто , где установлено nро­ грам мнее обесnечение Oracle) совместно хеш ируются с целью образования уни кально­ го имени ключа для создания или nрисоеди нения к области nамяти SGA ( System Global Area - систем ная глобальная область) . Если значения ORACLE _ s I D или ORACLE _ НОМЕ установлены некорректно, и вы исnользуете локальное ( не сетевое) подкл ючение (све­ дения о локальных/удаленных nодключениях ищите в главе 2 ) , то это nриведет к возник­ новению ошибки "ORACLE N OT AVAILABLE" (база данных Oracle недостуnн а ) , т. к. невоз­ можно присоеди ниться к сегменту разделяемой nамяти, который идентифици рован этим уникальным ключом . В среде Windows разделяемая память эксплуатируется не так, как в U NIX/Linux, но nараметр S I D nо-прежнему важен. В одном и том же месте , указанном в ORAC LE _ НОМЕ , может существовать более одной базы данных, nоэтому необходим сnо­ соб уникальной идентификации каждой из них наряду с их файлами конфи гурации . Без файла параметров запуск базы данн ы х Oracle невозможен . Это обстоятель­ ство делает файл параметров очен ь важны м . Нач и н ая с Oracle9i Release 2 ( верси и 9.2 и последующих) , инструмент резервного копирования и восстановления RMAN (Recovery Manager - диспетчер восстановления) учитывает важность этого файла и позволяет включать в набор резервного копирования файл параметров сервера (но не унаследованный файл параметров i n i t . ora ) . Тем не менее, поскольку i n i t . ora является простым текстовым файлом, которы й можно создавать с помощью любого текстового редактора, его не стоит защищать л юбой ценой . Он всегда может быть воссоздан при услови и , что его содержимое известно ( например, эту и нформацию можно извлечь из сигнал ьного файла базы данных, есл и к нему есть доступ , и ре­ конструировать полный файл i n i t . ora ) . Н иже мы по очереди рассмотри м оба типа файла параметров ( i n i t . o r a и S P FILE ) , но сначала давайте выясним, на что похож файл параметров базы данных. Ч то собой представляют параметры Выражаясь простыми терминами, параметр базы данных можно представлять как пару "ключ-значен ие " . В предыдущей главе вы сталкивались с важны м параметром dЬ_name . Этот параметр бьm сохранен как db_name o r a l 2 c. Ключом здесь я вля ­ ется dЬ_name , а значением - o ra l 2 c . Это и есть наша пара "ключ-значен ие " . = 1 40 Глава 3 Для выяснения текущего значен ия параметра экземпляра можно запросить пред­ ставление V$ по име н и V$ PARAМETER. В качестве альтернативы в SQL* Pius можно ввести команду SHOW PARAМETER, например: EODA@ORA 1 2 C R 1 > se 1ect va1ue from v$pa rameter 2 3 where name = 1 dЬ Ьlock s i ze 1 4 1 VALUE 8 1 92 EODA@ ORA1 2CR1> show pa rameter db_Ьlock s NАМЕ ТУРЕ VALUE dЬ Ьlock s i ze integer 8 1 92 Оба вывода отображают в основном ту же самую и нформацию, хотя представле­ н ие V$ PARAМETER предоставляет значительно больше сведений (для выбора доступ­ но знач ительно больше столбцов, чем показано в этом примере ) . Однако я отдаю предпочтение команде s нow PARAМETER из-за простоты ее применения и того фак­ та, что она автоматически использует " групповые символ ы " . Обратите внимание , что было введено только db_Ы о с k s ; команда SHOW PARAМETER добавляет символ % в начало и конец. _ Н а заметку! В се представлен и я V$ и все словар н ы е п редставления полностью доку­ м е нтированы в руководстве Oracle Database Reference ( Справоч н и к по СУБД Oracle ) . Рассматр и вайте это руководство как наиболее полный источник сведений о том , что до­ ступ но в заданном п редставлении. Есл и бы вы выпол н ил и предыдущ и й пример от имени менее привилегирован­ ного пользователя (для работы с примерами этой кни ги пользователю EODA была выдана роль DBA) , то увидели бы взамен следующий вывод: EODA@ ORA1 2CR1 > connect s cott /t i g er Connected . Подключено . S COTT @ORA1 2CR1> s e l ect va lue 2 from v$pa rameter 3 whe re name = 1 dЬ Ьlock s i ze 1 4 1 from v$pa ramete r * E RROR at l i ne 2 : ORA- 0 0 9 4 2 : taЬle or view doe s not exi s t ОIIМБКА в строке 2 : ORA - 0 0 9 4 2 : та блица или представление не существует S COTT @ORA1 2CR1> s how paramet er dЬ_Ьlock_s ORA- 0 0 9 4 2 : taЬle or view doe s not exi s t ORA - 0 0 9 4 2 : та блица или представление н е существует Файлы 1 41 По умолчанию "обычным" учетн ым записям не предоставлен доступ к представ­ лениям производительности V$ . Однако пусть вас это не сбивает с толку. Существует документирован н ы й АР I - интерфейс, как правило, доступ н ы й всем п ол ьзовате ­ лям, который позволяет видеть содержимое V$ PARAМET ER; следующая небольшая вспомогательная фун кция поможет увидеть, что установлено в качестве параметра, например: SCOTT @ORA1 2CR1> create or rep1ace 2 function get_param ( p_name in varchar 2 3 return va rchar2 4 as numЬer ; 5 1_param_type binary_intege r ; 1 intva1 б 7 va rchar2 ( 2 5 6 ) ; 1 s t rva1 8 inva1 id_parameter exception ; 9 pragma exception_init ( inva 1 i d_parame te r , - 2 0 0 0 0 ) ; 1 0 begin 11 begin 1_param_type : = 12 13 dЬms_ut i 1 i t y . get_parameter va1ue 14 ( parnam = > p_name , 15 i ntva 1 => 1_intva1 , 16 s t rva 1 = > 1_st rva1 ) ; exception 17 18 when inva 1 i d_pa rameter 19 then 20 return ' * acce s s denied* ' ; end ; 21 i f ( 1_param_t ype = О ) 22 then 23 24 1_s trva1 : = to_char ( 1_intva 1 ) ; end i f ; 25 26 return 1 s t rva1 ; 2 7 end get_param; 28 1 Function created . Функция создана . На заметку! Если вы применили последнее исправление безопасности для версии 1 1 g R2 или 1 2с, то вам может понадобиться выдать пользователю , выполняющему эту функцию , привилегию s e 1 ect на v_ $p ar ame t e r и л и s e 1 e c t_ c a t a 1 og_ r o 1 e . Если вы запустите эту функци ю в SQL* Plus, то увидите такой вывод: SCOTT@ORA1 2CR1> ехес dЬms_output . put_1ine ( get_param ( ' dЬ Ыосk s i ze ' ) ) ; 8 1 92 PL/ SQL procedure succe s s fu 1 1 y comp1eted . Процедура PL/SQL успешно выполнена . Через АРI -вызов dbms_ut i l i t y . ge t_p a rame t e r_va l u e доступен не кажды й параметр. В частности, параметры, связанные с памятью, такие как s ga_max_s i ze , dЬ_c a che_s i z e , pga_a ggregate_t a rget и тому подобные, видны не будут. 1 42 Глава 3 М ы обрабатываем эту ситуацию в строках кода с 1 7 по 2 1 , возвращая 1 * a c ce s s den i ed* 1 (доступ запрещен ) п р и обращен и и к параметру, видеть который н е разре­ шено. Есл и вас и нтересует пол н ы й список параметров с ограниченным доступом, можете (как и любая учетная запись, которой выдано право EXECUTE на эту функ­ цию) запустить следующий запрос: EODA@ORA 1 2 CR 1 > se l ect name , s cot t . get_param ( name ) val 2 f rom v$pa rameter 3 where scott . get_pa ram ( name ) = 1 * acce s s denied* ' ; NАМЕ VAL s ga_max_s i z e shared_pool_s i ze large_pool_s i z e j ava_pool s i ze s t reams_pool_s i z e * acce s s denied* * acce s s denied* * acce s s den i ed* *acce s s denied* * acce s s denied* cl i ent_resul t_cache_lag ol ap_page_pool_s i z e * a cce s s denied* * acce s s denied* 2 5 rows s e l ected . 25 строк выбрано . На заметку! В разных версиях будут получаться разные результаты . С течением времени вам следует ожидать изменений количества и значений недоступных параметров в большую или меньшую сторону по мере того , как изменяется общее ч исло параметров. Если подсчитать количество документированных параметров, которые можно ус­ тю;�авливать в каждой верси и базы данных - 9i Re1ease 2 , 1 Og Release 2, 1 1g Release 1 , 1 1g Release 2 и 1 2 с Release 1 , - то получится , соответственно, 258, 259, 294, 342 и 368 разных параметров (я уверен , что могут быть и дополнительные параметры, до­ ступные в конкретной операционной системе ) . Другими словами , количество пара­ метров (и их имена) варьируются в зависимости от выпуска. Большая часть пара­ метров вроде db_Ь l o c k_ s i z e сушествует очень долго (они не исчезают от выпуска к выпуску), но многие другие параметры со временем устаревают из-за изменений, вносимых в реализации . Например, в Oracle 9.0. 1 и предшествующих версиях - вплоть до Oracle 6 - при ­ сутствовал параметр d i s t r ibuted_ t ra n s a c t i on s , которы й можно было устанав­ ливать в какое-то положительное значение и управлять количеством параллельных распределенных транзакций, выполняемых базой данн ых. Он был доступен в более ран них выпусках, но отсутствует во всех выпусках, вышедших после 9.0. 1 . П опытка его использования в этих выпусках вызовет ошибку, например: EODA@ORA 1 2 CR 1 > a l t er s ys tem set d i s t r ibuted_transactions = 1 0 ; alter system s e t di s t ributed_transactions = 1 0 * ERROR at l ine 1 : ORA- 2 5 1 3 8 : DI STRI BUTED_TRANSACTIONS inltial i zatlon parameter has been made obsolete ОШИБКА в строке 1 : ORA-251 3 8 : Параметр инициализации DISTRIBUTED_ TRANSACTIONS устарел Файлы 1 43 Есл и вы хотите просмотреть эти параметры и получить представление о том , ка­ кие из них доступ ны и что они делают, обращайтесь в руководство Oracle Database Reference. В первой главе этого руководства подробно описаны все документирован­ ные параметры. В большинстве случаев значения, присваиваемые этим параметрам по умолчани ю (либо производные значения, получаемые на основе других парамет­ ров), вполне подходят для больш и нства систем. В то же время , значения парамет­ ров, таких как cont r o l_ f i l e s (определяет местоположение управляющих файлов системы), db_Ь l o c k_ s i z e и различных параметро в, связанных с памятью, требуют индивидуальной настройки для каждой базы данных. Обратите внимание, что в предыдущем абзаце я использовал тер м и н "доку­ ментированн ы е" . Существует также м ножество недокументированных параметров . Их можно определ ить по и менам , нач инающимся с символа подчеркивани я (_) . Относительно н их ведется множество споров. П оскольку о н и не документирова­ ны, некоторые верят в их " магические возможности " , и многие считают, что о н и хорошо известны и применяются и нсайдерами Oracle . Н а самом деле я убежден в обратном . Эти параметры не очен ь хорошо исследованы , и с н и м и трудно работать. Больш инство из недокументированных параметров довольно скуч н ы , т. к. представ­ ляют устаревшую фун кциональность и флаги обратной совместимости . Другие по­ моrают в восстановлен и и данных, а не самой базы данн ых; например, некоторые из этих параметров позволяют выпол н ить запуск базы данных в определенн ых экстре­ мальных условиях, но только на время , достаточное для вы вода данных. П осле этого база данных требует повторного построения . Если только в ы н е получили прямого указания от службы поддержки Oracle, то нет ни какой необходимости включать недокументированные параметры в реальную конфигурацию. М ногие из них вызывают побочные эффекты , которые могут приво­ дить к разрушительным последствиям. В своей производственной базе данных я не использую недокументированные параметры. Внимание! П рименяйте недокументированные параметры только по запросу из службы под­ держки Oracle (Oracle Support ) . Их испол ьзование может привести к поврежде н и ю базы данных, а их реализация может - и будет - меняться от верси и к версии . Разнообразные значения параметров можно устанавливать одни м из двух спосо­ бов: либо только для текущего экзем пляра, либо постоянно. Обеспечение наличия нужных значений в файле параметров - как раз ваша задача. В случае применения унаследованных файлов параметров ini t . ora это делается вручную. Для измене­ ния значения параметра на постоян ной основе, чтобы оно сохранялось между пере­ запусками сервера, вы должны вручную редактировать файл параметров i n i t . o r a . Используя файлы параметров сервера, вы увидите, что эта работа более-менее авто­ матизирована в единствен ной команде . Унаследованные ф айлы параметров ini t . ora Структура унаследованного файла i n i t . o r a очен ь проста. Он представляет со­ бой последовательность пар "ключ-значение". 1 44 Глава 3 Н иже приведен пример содержимого этого файла: control_fi les= ' / u 0 1 / dЬ f i l e / ORA1 2CRl /control O l . ctl ' , ' /u 0 2 /dЬfile/ ORA1 2CR1 / control 02 . ctl ' dЬ Ьlock s i ze=8 1 92 dЬ name= ' ORA1 2 CR 1 ' П о существу этот пример бли зко отражает наиболее элементарное содержимое файла i n i t . o r a , с которы м можно было бы столкнуться в реальности . Если на кон кретной платформе можно применять стандартный размер блока (который ва­ рьируется в зависимости от платформы ) , то строку с параметром db_Ь l o c k_s i z e можно удалить. Файл параметров испол ьзуется , по меньшей мере , для получения имени базы данн ых и местоположен ия управляющих файлов. Управляющие файлы сообщают Oracle местоположение всех остальных файлов, поэтому они очень важны для процесса "начальной загрузки " , который запускает экземпляр. Теперь, когда вы знаете , что собой представляют унаследованные файлы пара­ метров базы данных, и где можно найти дополнительную и нформацию о допусти­ мых параметрах, которые можно устанавли вать, осталось также выяснить, где эти файлы искать на диске. По умолчани ю для этих файлов при няты следующие согла­ шения , касающиеся их имен: • i n i t $ 0RACLE_ S I D . ora (переменная среды U N I X/Linux) • i n i t % ORACLE_S I D% . ora (переменная среды Windows) По умолчани ю они будут находиться в следующих местах: • $ 0RACLE_HOM E / dЬ s (UN IX/Linux) • % 0RACLE_НОМЕ% \ DATAВAS E (Windows) И нтересно отметить, что во м ногих случаях все содержимое этого файла пара­ метров будет выглядеть приблизительно так: I FI LЕ= ' / некоторьм / пут ь / к/ каталогу/ i n i t . оrа ' Директива I F I LE работает подобно директи ве # i n c l ude в языке С. Она вклю­ чает содержимое указанного файла в текуший файл . Здесь директива включает файл i n i t . o r a из нестандартного местоположен ия . Следует отметить, что файл п араметров н е обязательно должен размещаться в каком-то определен ном местоположе н и и . При запуске экземпляра можно исполь­ зовать опцию рt i l е =имя_файла команды запуска. Это особенно удобно, если тре­ буется оценить влияние различных параметров i n i t . ora на базу данных. Унаследованные файлы параметров можно обслуживать с помощью любого тек­ стового редактора. Н апример, в среде U N IX/Linux я использую vi; во многих верси­ ях Windows я применяю Notepad, а в среде мэйнфрейма, вероятно, воспользовался бы Xedit. Важно понимать, что именно вы пол ностью отвечаете за редактирование и обслуживание этого файла. Внутри самой базы данных нет никаких команд, ко­ торые можно б ыло бы применить для и зменения значе н и й в файле i n i t . o r a . Например, когда используется файл параметров i n i t . o r a , то выполнение команды ALT ER S Y S TEM для изменения размера компонента SGA не приведет к постоянному измене н и ю в этом файле. Если нужно, чтобы изменен ие стало постоянным (дру­ гим и словами , чтобы оно стало стандартн ым при последующих перезапусках базы Файл ы 1 45 данных) , вы должны обеспечить ручное обновление содержимого всех файлов пара­ метров i n i t . o r a, которые могут применяться для запуска этой базы данных. И последняя и нтересная особенность унаследованного файла параметров связана с тем , что он не обязательно должен располагаться на сервере базы данных. Одной из причин ввода файла параметров (которые мы вскоре обсудим) было исправление этой ситуаци и . Унаследованный файл параметров должен присутствовать на ком ­ пьютере клиента, пытающегося запустить базу данных. Это значит, что в случае ис­ пользования сервера U N IX/Linux, но его администрировании через сеть с помощью интерфейса SQL* Pius, установленного на настольном ком пьютере Windows, файл параметров базы данных должен находиться на настольном компьютере . До сих пор помню ситуацию, когда я сделал болезненное открытие, что файлы параметров не хранятся на сервере . Это произошло много лет назад, как только по­ явился совершенно новый (теперь изъятый из обращения) и нструмент под названи ­ е м SQL*DBA . Он позволял выполнять удаленные операции , в частности , удаленное адми нистрирование. Со своего сервера (функцион и рующего тогда под управле­ нием SunOS) я мог удаленно подключаться к серверу базы дан н ых мэйнфрейма. Также была возможность выдачи команды завершения. Тем не менее, именно тогда я и понял , что не все так просто - при попытке запуска экземпляра инструмент SQL*DBA сообщал о невозможности н ахождения файла параметров. Я знал , что эти файлы параметров - простые текстовые файлы i n i t . o r a - размешались на ком­ пьютере клиента; они должн ы были существовать на стороне клиента, а не сервера. И нструмент SQL* D BA искал файл параметров в моей локальной системе, чтобы за­ пустить базу данных мэй нфрейма. Мало того, что на моем компьютере этот файл отсутствовал , я еще и не имел ни малейшего понятия о том , что в него нужно было поместить, чтобы запустить систему! Я не знал ни значения параметра db name , н и местоположений управляющих файлов (даже получение информаци и о соглашени­ ях по именовани ю файлов на мэйнфрейме оказалось довольно сложной задачей ) , и не имел доступа для входа в саму систему мэйнфрейма. С тех пор я больше не пов­ торял эту ошибку; урок был достаточно болезненным, чтобы хорошо его усвоить. Когда администраторы баз дан н ых осознал и , что файл параметров i n i t . o r a должен находиться н а компьютере клиента, запускающего базу данных, это привело к быстрому размножению таких файлов. Каждый администратор базы данных желал запускать инструменты администрирования со своего рабочего стола, поэтому ему требовалась копия файла параметров на его настольном ком пьютере . Такие средс­ тва, как ОЕМ (Oracle Enterprise M anager - диспетчер предприятия Oracle), добав­ ляли в общую смесь еще один файл параметров. И н струменты подобного рода пы­ тались централизовать задач и администрирования всех баз данных предприятия на одном компьютере, который и ногда н азывали сервером управления. Н а этом единс­ твенном комп ьютере должно был о фун кционировать программ ное обеспече н и е , которое все администраторы базы данных применяли бы для запуска, завершения , резервного копирования и выполнения других действий по адми нистрировани ю баз данных. На первый взгляд такое решение - сосредоточение всех файлов парамет­ ров в одном месте и использование инструментов с графическим пользовательским интерфейсом для выполнения всех операций - выглядит идеальн ы м . Однако ре­ альность состоит в том, что и ногда при проведении некоторых административных задач значительно удобнее выдавать команду администрирования из среды SQ L* Pius _ 1 46 Глава 3 самого сервера баз дан ных. В результате снова возникла ситуация существования нескольких файлов параметров: одного н а сервере управления и одного на сервере баз данн ых. Кроме того, эти файлы параметров требовали бы синхронизации друг с другом, и пользователям пришлось бы удивляться , почему параметр, который они изме н или в прошлом месяце, вдруг " исчез " , а затем по непонятной причине снова "поя вился " . В итоге это привело к введен и ю файла параметров сервера ( S P F I LE ) , который теперь может служить единственным " критерием истин ы " для базы данных. Ф айлы пара м етров сервера ( S PFILE ) Файл ы S P F I L E представляют фундаментальное изменение в способе доступа Oracle к параметрам настройки для экземпляра и их сопровождения . Файл S P FILE устраняет две серьезные проблемы , связанные с унаследованными файлами пара­ метров. • Он предотвращает размножение файлов параметров. Файл S P F I LE всегда хра­ н ится на сервере базы данн ых; он должен находиться на комп ьютере самого сервера и не может быть размещен на ком пьютере клиента. Это обстоятель­ ство обусловл ивает целесообразность наличия единствен ного источника " ис­ тинных" значений параметров. • Он устраняет необходимость (фактически лишает возможности) поддерживать файлы п араметров вручную с помощью текстовых редакторов вне базы дан ­ ных. Команда ALTER SYSTEM позволяет записывать значен ия непосредственно в файл S P F I LE . Администраторам больше не нужно находить и обслуживать все файлы параметров вручную. П о умолчан и ю для этого файла действует следующее соглашение по именова­ нию: • $0RACLE_HOME/dЬs / sp f i le$0RACLE_S I D . ora (переменная среды Unix/Linux) • % 0RAC L E_HOME / d a t a b a s e / s p f i l e % 0RAC LE S I D % . o r a (перемен ная среды Windows) Я настоятельно рекомендую применять стандартное местоположение; в против­ ном случае простота использования файла S P F I LE будет сведена на нет. Когда этот файл н аходится в стандартном каталоге , все действия выполняются более или ме­ нее автоматически . П еремещение файла S P F I LE в другой каталог требует указания Oracle этого местоположен ия , снова приводя к возникновению проблем, которые присущи унаследованным файлам параметров! Преобразование в файлы SPFILE П редположим , что у вас есть база данных, в которой применяется унаследован­ н ы й файл параметров. П ереход на файл S P F I LE довольно прост - вы используете команду CREAT E S P FI LE . Н а заметку! М ожно также n р и м енять "обратную" ком анду для создания файла nара­ метров ( P F I LE ) из файла S P F I L E . Вскоре я объясн ю , чем может быть вызвана такая необходимость. Файлы 1 47 Итак, при наличии файла параметров i n i t . ora в стаJЩартном местоположен и и н а сервере достаточно выдать команду CRT EATE S P F I L E и перезапустить экземпляр сервера: EODA@ ORA12CR1> show parameter spfi l e ; NАМЕ ТУРЕ VALUE spfile s t ring EODA@ORA1 2CR1 > create spfile from p f i l e ; create spfile from p f i l e * ERROR at line 1 : ORA- 0 1 0 3 1 : i n s u f f i cient privi leges ОШИБКА в строке 1 : ORA-01 031 : недоста точно привилегий Что же, команда S HOW PARAМETER показывает, что мы не создали S P F I L E : зна­ чение в колонке VAL UE пустое. Мы не располагаем достаточн ы м и привилегия м и , чтобы создать S PFILE, хотя вход б ыл совершен о т имени администратора базы дан­ ных. Создание S P F I LE считается очень высокопривилегированной операц ие й , и ее можно выполнять, только в случае подключен ия с использованием учетных дан н ых, которые позволяют запускать и останавли вать базу данных. Давайте сделаем это: EODA@ORA1 2CR1 > connect 1 a s s ysope r ; Connected . Подключено . PUBLIC@ORA1 2 CR1 > create spfile f r om p f i l e ; File created . Файл создан. PUBLIC@ORA1 2CR1> startup force ; ORACLE instance s tarted . Database mounted . Database opened . Экземпляр ORACLE запущен . База данных смонтирована . База данных открыта . Я воспользовался наименее привилегирован ной учетной записью, от и ме н и ко­ торой можно выполнить эту операцию - зап исью (принадлежащей мне) с адми ­ н истративной привилегией S Y S O P E R. Привилегия S Y S O P E R позволяет управлять файлами параметров, запускать и останавливать базу данн ых, но н ичего сверх этого; вот почему вывод комаJЩы s t a rtup выглядит и наче - отсутствует поддержка SG, и фактически не видны параметры памяти : PUBLIC@ORA1 2CR1 > show parameter spfi l e ; ORA- 0 0 9 4 2 : taЬle or view does not exi s t ORA-00942 : та блица или представление н е существует Хотя привилегия S YSOPER дает право запускать и останавливать базу данных, она не имеет доступа к Представлениям V$ и т.д. Ее возможности весьма ограничены . Мы можем проверить, что файл S P F I LE применяется , п одключившись от имени учетной записи с достаточными привилегиями : 1 48 Глава 3 EODA@ ORA12CR1> show parameter spfi l e ; NАМЕ ТУРЕ VALUE /home / o ra1 2 c r 1 /app / ora 1 2 cr 1 /pr oduct/ 1 2 . 1 . 0 /dЬhome_ 1 / dЬs / spfi leora 1 2 c r 1 . ora Мы использовали здесь команду SHOW PARAМETER, чтобы показать, что изначаль­ но файл S P F I LE не применялся , но после его создания и перезаnуска экземпляра он используется и имеет стандартное имя. spfile string Н а заметку! В кластеризованной среде , в которой применяется Oracle RAC , все экземпля­ ры совместно используют тот же сам ый файл SPFILE , поэтому процесс п реобразования файла PFILE в файл SPFILE должен производиться в управляемой манере. Еди нственный файл SPFILE может содержать все значения параметров, даже специфичные для экземп­ ляра, но все необходимые файлы параметров п ридется объединить в единый файл PFILE с описанным ниже форматом. В кластеризованной среде для перехода от отдельных файлов S P F I LE к общему файлу S P F I LE и ндив идуальные файл ы S P FI LE понадобится объедин ить в еди ный файл , подобный показанному н иже: * . cluster databa s e ins tances=2 * . cluster databa se=TRUE * . cluster inte rconnects= ' 1 0 . 1 0 . 1 0 . 0 ' * . compatiЬle= ' 1 2 . 1 . 0 . 0 . 0 ' * . control_f i l e s= ' / u 1 / d 1 / 0 1 2 C / control 0 1 . ct l ' , ' /u 1 /d2 /0 1 2 C / contro l 0 2 . ctl ' * . dЬ name= ' 01 2 C ' - - * . proces ses=1 5 0 * . undo_management= ' AUTO ' 0 1 2 C 1 . ins tance numЬer=1 0 1 2 C2 . ins tance numЬer=2 0 1 2 C 1 . local l i stener= ' LI STENER 0 1 2 С 1 ' 0 1 2 C2 . local l i s tener= ' LI STENER 0 1 2С2 ' 0 1 2 C 1 . remote l i s tener= ' L I STENER O l 2 C 2 ' O l 2 C2 . remote l i s tener= ' LI S TENER 0 1 2 C l ' 0 1 2 C 1 . thread= l O l 2 C2 . thread=2 O l 2 C l . undo_taЬle space= ' UNDOTBS l ' O l 2 C2 . undo_taЬle space= ' UNDOTBS 2 ' - То есть имена nараметров, общих для всех экземпляров в кластере, будут начи­ наться с символов * И мена параметров, характерн ых для отдел ьного экземпляра, вроде I N S TANCE_NUMBE R и T HREAD, должн ы быть предварены и менем экземпляра (идентификатором Oracle S I D) . В предыдущем примере: . . • • • файл P F I LE будет предназначен для двухузлового кластера, который содержит экземпляры с именами O l 2 C l и O l 2 C 2 ; присваивание * . dЬ_name = 1 0 1 2 С ' указывает, что все экземпляры, использу­ ющие этот файл S P F I LE, будут монтировать базу данных по имени 0 1 2 с; присваиванне 0 1 2 C l . undo t ab l e space= 1 UNDOTBS l 1 отражает то, что экзем­ пляр O l 2 C l будет применять эту конкретную табличное пространство, и т.д. _ Файл ы 1 49 Установка значений в файлах SPFILE П осле того как база данных запущена с участием S PFILE, возникает вопрос о том , как устанавливать и изменять значения , содержащиеся в этом файле . Вспомните , что файлы S P F I LE являются двоичными , и их нельзя редактировать в простом текс­ товом редакторе. Ответом будет команда ALTER SYSTEM с показанным ниже синтак­ сисом (элементы , заключен н ые в скобки < > , являются необязательными, а символ канала 1 указывает на необходимость выбора одного элемента из списка): Alter s ys tem set параметр=значение <comment= ' тe кcт ' > <de f e r red> <s cope=memory l sp f i l e l both> <sid= ' системный_идентификатор l * ' > <container=current l al l > По умолчан ию команда ALT ER S Y S T EM SET будет обновлять выпол няющийся в текущи й момент экземпляр, а также вносить изменения в файл S P F I L E или в слу­ чае подключаемой базы дан ных - в словарь данных этой подключаемой базы дан­ ных (дополн ительные сведения будут приведе н ы в разделе " П одключаемые базы данных" далее в главе). Это значительно облегчает адми нистрирование и устраняет проблемы, возникшие во время установки или модификаци и параметров посредс­ твом команды ALTER S Y S T EM, если при этом адми нистратор забыл обновить файл параметров ini t . ora или этот файл вообще отсутствует. Давайте взглянем на каждый элемент этой команды. • Присваиванне параме тр=значение предоставляет имя параметра и его новое значение. Н апример, элемент pga_a g g r e g a t e_t a r g e t = 1 0 2 4m установил бы значение параметра PGA_AGGREGATE_TARGET в 1 024 Мбайт ( 1 Гбайт) . • Присваиван не comment = ' т е к: с т ' - необязательный комментарий , который можно связать с данным значением параметра. Этот комментарий будет отоб­ ражаться в поле U P DAT E_COMMENT представления V$ PARAМETER. При исполь­ зовании варианта сохранения изменения в S P FI LE комментари й будет записан в этот файл , и также сохраняться при последующих перезапусках сервера, так что впоследствии он будет видимым для базы данных. • Параметр de f e r red указывает на то, что системные изменения должны всту­ пить в силу только в последующих сеансах (т.е. не в текущих сеансах, вклю­ чая тот, в котором производится изменение). По умолчанию команда ALT E R SYSTEM будет вступать в силу сразу же , но некоторые параметры не могут быть изменены немедленно - это допускается только для вновь созданных сеансов. Выяснить, какие параметры требуют применения de f e r red, можно с помо­ щью следующего запроса: EODA@ORA1 2CR1> s e lect name from v$pa rameter 2 3 whe re i s s ys_modi fiaЬle= ' DE FERRE D ' 4 1 NАМЕ backup_tape_io_s lave s recyclebin audit file de s t obj ect_cache_optima l_s i ze 1 50 Глава 3 obj ect_cache max s i ze_pe rcent sort area s i ze sor t-area -retained s i ze olap_page_pool_s i z e - 8 rows s e lected . В строк выбрано . На заметку! Результаты , nолученные вам и , могут отличаться ; сnисок nараметров, которые могут быть установлен ы в оnеративном режиме, но их установка должна быть отложена, от версии к версии может - и будет - отличаться . В выводе видно, что параметр s o rt_a r e a_s i z e можно изменять на системном уровне , но только отложен н ы м образом . Показанный н иже код демонстрирует, к чему приводят попытки изменения значения s o rt_area_ s i ze с и без de ferred: EODA@ORAl2 CRl > a l t er s ys tem set s o rt_a rea_s i ze = 6 5 5 3 6 ; a l t e r system s e t s o r t-area-s i ze = 6 5 5 3 6 * ERROR at l ine l : ORA- 0 2 0 9 6 : speci fied i n i t i a l i zat ion pa rameter is not modi fiaЬle with this opt i on ОШИБКА в строке 1 : ORA - 02 0 9 6 : указанный параметр инициализации не может быть изменен подобным образом EODA@ORA12CR1> a l t e r s ys tem s e t s o rt a rea s i ze = 6 5 5 3 6 de fe rred ; Sys tem a l t e red . Система изменена . • s c ope=memo r y 1 s p f i l e 1 both указывает "область действия" этого параметра. Рассмотри м варианты установки значен ия. о s cope=memor y изменяет значение только в экземпляре (экземплярах) ; пос­ ле перезапуска базы данных это изменение будет утеряно. При следующем запуске значение будет таким , каким оно зафиксировано в файле S PFILE. о s cope = sp f i l e изменяет значе н ие только в файле S P F I L E . Изменение не вступит в силу, пока база данных не будет перезапущена и файл S P F I LE не обработается повторно. Некоторые параметры могут быть изменены только с применением этого варианта - например, параметр p r o ce s s e s должен испол ьзовать s cope=sp f i l e , т. к. изменить значение активного экземпляра невозможно. о s c ope=both означает, что изменение параметра происходит как в памяти , так и в файле S P FI LE . И зменение отразится в текущем экземпляре, а также будет действовать при следующем запуске базы данных. При использовании файла S P F I LE эта область действия считается стандартной . В случае приме­ нения файла параметров i n i t . ora стандартным и еди нственным допусти­ мым значением является s cope=memory. • Присваивани е s i d= ' системный_идентифика тор 1 * ' главным образом удобно в кластеризованной среде. Вариант s id= ' * ' используется по умолчанию. Это поз­ воляет указывать значение параметра для любого конкретного экземпляра в клас­ тере. Указывать s id= нужно только в случае применения технологии Oracle RAC. Файл ы • 1 51 Присваивание cont a i ne r= c u r r e n t 1 a l l используется в базе данных с мно­ жеством владельцев для определения области действия изменения. Если ко­ манда ALTER SYSTEM выполняется в корневой контейнерной базе данных, то за счет применения параметра a l l значение может распространяться в каж­ дую подключаемую базу дан н ых. В противном случае по умолчанию измене­ ние воздействует только на текущую контейнерную или подключаемую базу данных. Обратите внимание, что н астройки , специфичные для подключаемой базы данных, не записываются в файл S P F I L E , а сохраняются в словаре дан­ ных этой подключаемой базы данн ых , так что в случае перемещения в другой контейнер ее настройки переместятся вместе с ней. Команда обычно используется следующим образом: EODA@ORA12CR1> alter system set pga_aggregate_ta rget=5 1 2m ; System alte red . Система изменена . На заметку! П редыдущая команда - и фактически м ногие команды ALT E R SYSTEM в этой книге - может дать сбой в вашей системе. Если вы nрименяете другие nараметр ы , кото­ рые несовместимы с nриведенным nримерам ( скаже м , другие nараметры nамяти ) , может возникнуть ошибка. Это вовсе не означает, что ком анда не работает, а скорее то, что nа­ раметры, которые вы n ытаетесь исnользовать, несовмести м ы с общей установко й . Вероятно, даже еще лучше применять присваивание COMMENT=, чтобы докумен­ тировать, когда и почему было внесено конкретное изменение: EODA@ORA12CR1> a l ter sys tem s et pga_aggregate_target= 5 1 2m 2 comment = ' Changed 1 4 - aug - 2 0 1 3 , AWR recommendation ' ; System alte red . Система изменена . EODA@ORA12CR1> s elect value , update_comment 2 from v$pa rameter 3 whe re name = ' pga_aggregate_ta rget ' 4 1 VALUE UPDATE СОММЕNТ 536870912 Changed 1 4 -aug- 2 0 1 3 , AWR recommendation Отмена установки значений в файлах SPFILE Теперь возникает следующий вопрос: как отменить установлен ное значение? Другими словами, нам больше не нужен такой параметр в файле S P FILE. Каким обра­ зом решить эту задачу, если файл нельзя редактировать в текстовом редакторе? Для это­ го также используется команда ALTER SYSTEM, но на этот раз с конструкцией RES ET : Alter system reset parameter <s cope=memory l sp fi l e l both> s i d= ' s id l * ' Итак, например, если необходимо удалить параметр s o r t _area_ s i ze , чтобы дать ему возможность принимать стандартное значение, введите следующую команду: EODA@ORA12CR1> alter sys tem reset sort_a rea_s i z e s cope=sp f i l e ; System altered . Система изменена . 1 52 Глава 3 На заметку! В предшествующих выпусках, в частности , в Oracle 1 0g Release 2 и более ран­ них, конструкция S I D= не была необязательной , как сейчас. Тогда нужно было помещать конструкцию S I D= 1 * 1 в конец команды ALT E R S Y S T EM, чтобы сбросить параметр для всех экземпляров в SPFILE. Или же требовалось указать S I D= 1 не к оторый _s id 1 , чтобы сбросить его для одного экземпляра. В результате параметр s ort_a r e a_s i z e удаляется из S P F I LE, в чем можно удостовериться так, как показано ниже : EODA@ORA12CR1> connect 1 as s ysope r ; Connected . Подключено . PUBL I C @ ORA1 2CR 1 > create p fi le= 1 /tmp /p fi l e . t st 1 from spfi l e ; Fi l e c reated . Файл создан . После этого можете проверить содержимое файла /tmp /p f i l e . t s t , который бу­ дет сгенерирован на сервере базы данных. Вы увидите, что s ort_a rea_s i ze в фай­ ле параметров больше не существует. Соэдание файлов PFILE из файлов SPFILE Показанная только что команда CREATE P F I LE . . . FROM S P FILE является проти­ воположностью команды CREATE S P F I LE . Она принимает двоичный файл S P F I LE и создает из него простой текстовый файл - файл , который можно редактировать в любом текстовом редакторе, а затем применять для запуска базы данных. Эту ко­ манду можно использовать для выполнения , по меньшей мере , двух описанных н иже действий на регулярной основе . • Создание одноразовоrо файла параметров с рядом специальных настроек для запуска базы данных в целях обслуживания. Сначала вы должны запустить ко­ манду CREATE P F I LE FROM S P F I LE и отредактировать результирующий тек­ стовый файл P F I LE, изменив нужные параметры. Затем потребуется запустить базу данных с применением Р F I LЕ=<ИМЯ_ФАЙЛА>, чтобы указать файл P F I LE вместо S P F I LE. По завершении достаточно будет запустить базу данных обыч­ ным образом, и она будет использовать файл S P FI LE. . • • . Поддержание хронолоrии комментированных изменений. В прошлом мно­ гие адми н истраторы баз данных и нтенсивно снабжали свои файл ы парамет­ ров комментариям и , отражающи м и хронологию изменений. Например, если они изменяли размер кеш а буфера 20 раз, то в файле ini t . o r a параметру db_ cache s i z e могло предшествовать 20 комментариев с указанием даты и причи н ы внесения изменени й . Файл S P F I L E не поддерживает такую возмож­ ность, но аналоrичного эффекта можно добиться , если выработать у себя при­ вычку поступать следующим образом: PUBLIC@ORA 1 2 CR 1 > connect 1 as s ysdЬa Connected . Подключено . SYS@ORA1 2 CR1 > create p fi le= 1 init_l 4_aug 2 0 1 3 ora 1 2 cr l . ora 1 from spfile ; Fi l e created . Файл создан . Файл ы 1 53 SYS@ ORA1 2 CR1 > a 1 t er sys tem s et pga_aggregate_ta rget=5 1 2m 2 comment = ' Changed 1 4 - aug - 2 0 1 3 , AWR recommendat i on ' ; Sys tem altered . Система изменена . Таким способом хронология изменений будет сохраняться с течением времен и в последовательности файлов параметров. Исправление поврежд енных файлов SPFILE Последний вопрос, возни кающий в отношении файлов S P F I LE , формул ируется так: " Поскольку файлы S P F I LE являются двоичными, что произойдет, есл и один из них окажется поврежденным и запуск базы данных станет невозможным? Во всяком случае, файл i n i t . o r a бьm простым текстовым, и его всегда можно было отредак­ тировать и исправить" . В действительности файлы S P F I LE повреждаются не чаще файлов данных, журнальных файлов, управляющих файлов и т.д. Тем менее, есл и такая проблема все же возникла или в S P F I LE установлено значение, которое н е позволяет базе данных запуститься , то можно пойти двумя путя м и . Прежде всего, объем двоичных дан н ых в файле S PF I LE очен ь мал. В среде U N IX/ Linux простая команда s t r i ngs позволяет извлечь все настройки : [ ora 1 2 c r 1 @del lpe dЬs ] $ s t rings $0RACLE_HOМE /dЬs / s p f i l e $ 0RACLE_S I D . ora * . audit_fi1e_de s t= ' /home /o ra 1 2 c r 1 / app / o ra 1 2 c r 1 /admin /ora 1 2 c r 1 /adump ' * . audi t trail= ' dЬ ' * . compatiЬle= ' 1 2 . 1 . 0 . 0 . 0 ' В среде Windows достаточно открыть файл с помощью программы w r i t e . е х е (WordPad) . Этот редактор отобразит весь обычн ы й текст из файла, после чего пос­ редством операции вырезания и вставки в файл i n i t <O RAC L E_ S I D> . o r a можно создать файл P F I LE , предназначенный для запуска экземпляра. В случае "пропажи " файла S P F I LE (по любой причине - хотя мне с подобными ситуациями стал киваться не приходилось) и нформацию о файле параметров мож­ но извлечь из сигнального журнала базы данн ых (более подробно сигнальн ы й жур­ нал рассматривается далее в главе). При каждом запуске базы дан н ых в сигнальн ы й журнал записывается раздел следующего вида: Starting up : Oracle Database 1 2 с Enterprise Edition Releas e 1 2 . 1 . 0 . 1 . 0 - 64bit Production With the Partit ioning , OLAP , Advanced Ana l ytics and Real App l i cati on Testing options . ORACLE_HOME = /home /ora 1 2 c r 1 /app /ora 1 2 c r 1 /p roduct / 1 2 . 1 . 0 /dЬhome_1 Linux Sys tem name : Node name : del lpe 2 . 6 . 3 9- 4 0 0 . 1 0 9 . 1 . el 6ue k . x8 6 6 4 Re1ease : Ve rs ion : # 1 S M P T u e Jun 4 2 3 : 2 1 : 5 1 РОТ 2 0 1 3 х86 64 Machine : Using pa rameter settings in se rver - s ide spfile /home / o ra 1 2 c r 1 /app / ora 1 2 cr 1 /product / 1 2 . 1 . 0 /dЬhome_1 /dЬs / s p fileora 1 2 c r 1 . o ra Sys tem parameters with non-de fau l t values : = 300 processes = TRUE resource l imit = 4 8 0 0М sga_target 1 54 Глава 3 cont rol f i l e s = " /horne /ora 1 2 c r l /oradata/ORA1 2CR1 / control f i l e / � 01_rn f- a ;vv2prnl_ . ctl " cont rol f i l e s = " /horne/ora12cr1 /app/ora12cr1 / fast recovery-area / � ORA1 2CRl/cont ro l fi l e / o 1_rnf_8wvv2p s 2 . ct l " dЬ Ыосk s i ze 8 1 92 cornpatiЬle = " 12 . 1 . 0 . 0 . 0 " dЬ create f i l e de s t = " /horne / o ra 1 2 c r 1 /o radata " dЬ_recover y_ f i l e_de s t = " /horne/ora 12cr1 /app/ora l2crl/ fast_recovery_area " dЬ_recove ry_fi le_de s t_s i ze= 4 8 1 5М = "UNDOTBS 1 " undo_taЫespace rernote_l ogin_password f i le= "EXCLUS IVE " ' "' dЬ dornain dispatche rs " ( PROTOCOL=TC P ) ( SERVI CE=ora 1 2 c r 1XDB ) " local l i s tener " (ADDRESS= ( PROTOCOL=tcp ) ( HOST= 1 9 2 . 1 6 8 . 1 . 2 5 ) � ( PORT :;;;-1 5 2 1 ) ) " para l l el_rnin_s e rve rs = о para l l el_rnax_s e rve rs = о audi t f i l e des t = " /horne/ora12cr1 /app/ora 12cr1 /adrnin/ora 12cr1 /adurnp" audi t trai l = " DB " dЬ nате = " o ra 1 2 c r l " open_cursors = 300 _colurnn_t racking leve l = 1 pga_aggregate_ta rget = 1 6 0 0М = " /horne /ora 1 2 c r 1 1 app /ora 1 2 c r 1 " diagno s t i c_des t NOTE : rernote a srn rnode is local ( rnode Ох1 ; frorn cluster type ) St a rting background proce s s PMON Mon Sep 0 2 1 6 : 5 6 : 2 2 2 0 1 3 PMON s ta rted with pid=2 , O S id=2 1 5 7 2 На основе этого раздела легко создать файл P F I LE и затем посредством команды CREATE S P FI LE преобразовать его в новый файл S P FILE. nодключаемые базы данных П одключаемые базы дан н ых спроектированы как набор файлов, которые можно перемещать из одной корневой контей нерной базы данных в другую. То есть мы мо­ жем отсоединить подключаемую базу данных и впоследстви и снова присоединить ее либо к той же самой , либо к какой-то другой корневой контейнерной базе данных, и получить исходную подключаемую базу данн ых обратно - со всеми схемами при­ ложе н и й , пользователям и , метаданными, привилегиями, данными и даже настрой­ кам и параметров (которые не был и унаследованы от корневого контейнера) . Это достигается за счет сохранен ия настроек параметров, специфичных для подключа­ емой базы дан н ых, в табл ице словаря данных S Y S . P D B_S P F I LE $ . И менно таким способом подключаемые базы данных могут переопределять значения некоторых параметров (не каждый параметр допускает установку на уровне подключаемой базы дан н ых) в файле S P F I LE и обеспечивать их перенос по мере перемещения между корневыми контейнерными базами данн ых. Заклю чительные соображения по поводу файла параметров В этом разделе был и рассмотрен ы все основные особен ности управлен ия пара­ метрами инициализации Oracle и файлами параметров. Вы узнали , как устанавливать параметры, просматри вать их значения и обеспечивать сохранение настроек между Файл ы 1 55 перезапусками базы дан ных. М ы исследовали два типа файлов параметров базы дан­ ных: унаследован ные файлы P F I LE (простые текстовые файл ы ) и более новые фай­ лы S P FILE. Для всех существующих баз данных рекомендуется использовать файлы S P F I L E из-за легкости адми н и стрирования и ясности, которую о н и привносят. Возможность применения единствен ного источника " истины" для базы данных в со­ четании с возможностью вьщачи команды ALT E R S Y S T EM для сохране н ия значен и й параметров делает файлы S P F I L E привлекательным средством. Я начал их использо­ вать сразу же, как только они стали доступн ы , и ни разу не пожалел об этом. Трассировочные ф айлы Трассировочные файлы явля ются и сточн и ком отладочной и н формаци и . П р и возн и кнове н и и проблем сервер ге нерирует трассировочн ы й файл с огром н ы м объемом диагностической и нформаци и . Когда разработч и к запускает процедуру DBMS_MON I ТOR . S E S S I ON_T RACE_ENAB L E , сервер создает трассировочный файл с информацией, касающейся производительности. Трассировочные файлы доступны благодаря тому, что Orac\e является хорошо инструментирован н ы м программ н ы м обеспечением. П од "инструментированн ы м " я и м е ю в виду, что программ исты , на­ писавшие ядро базы данных, поместили в него очен ь много отладочного кода и ос­ тавили его там на всякий случай . Я встречал многих разработчи ков, которые считали отладочн ы й код накладными расходами - т.е. чем-то таким, от чего следует избавляться перед тем , как приложе­ ние поступит в производствен ную среду, пытаясь выжать максимум производитель­ ности из кода. П озже, конечно же, они обнаруживают, что код содержит ошибку и не функционирует настолько быстро, как должен (что конечные пользователи склонн ы расценивать как ошибку; для конечных пользователе й н изкая производительность является ошибкой) . В этот момент они страстно желают, чтобы отладочн ы й код ос­ тавался в коде приложения. Вы должны тестировать любой новый код перед его по­ мещением в производственную среду, и это не должно делаться впопыхах. СУБД Oracle, а также сервер приложе н и й , приложения Oracle и разнообразные средства, такие как Application Express (АРЕХ) , хорошо инструментирован ы . Н иже перечислены признаки этого инструментирования . • Представления V$ . Больши нство представлени й V$ содержат " отладочную" информацию. Представления V$WA I T S TAT , V$ S E S S I ON_EVENT и м ногие дру­ гие предназначены исключительно для отображения и нформации о происхо­ дящем внутри ядра базы дан ных. • Команда AUDIT. Эта команда позволяет указывать события , которые база дан­ ных должна записывать для последующего анал иза. • Диcne'rlep ресурсов (DEМS RESOURCE МANAGER). Это средство позволяет осущест­ влять микро-управление ресурсами (центральным процессором , устройствами ввода-вывода и т.п.) внутри базы данн ых. Возможность применения диспетчера ресурсов в базе данных обеспечивается тем, что база данных имеет доступ ко всем статистическим сведениям об использовании ресурсов во время выполнения . • События Oracle. События позволяют запрашивать у Oracle генераци ю необхо­ димой трассировочной или диагностической информации. _ _ 1 56 • Глава 3 DВМS_ТRАСЕ. Эта внутренняя функция механизма P L/SQL создает подробное дерево вызовов хранимых процедур, возникших исключений и ошибок. • Триггеры событий базы данных. Эти три ггеры , например, ON S ERVERE RROR, позволя ют отслеживать и регистрировать любые условия, которые можно счи­ тать " исключительными " или отклоняющимися от нормы. Например, в жур­ нал можно зап исать SQ L-зaпpoc , который выпол нялся при возн икновении ошибки типа " переполнение временной области " . • SQL_TRACE /DВМS_MONITOR. Служит дл я просмотра точ ного SQL-кoдa, собы­ тий ожидания и другой диагностической и нформаци и , связанной с произво­ дительностьюjповедением, которая генерируется в результате выполнения ва­ шего приложения. Средство SQL Trace также доступно в расш иренном виде через событие Oracle 1 0046. И нструментирование жизненно важно при проектировании и разработке прило­ жен и й , поэтому с каждым новым выпуском СУБД Oracle становится все луч ше и лучше инструментированной . На самом деле количество дополнительных инстру­ ментальных средств, появивш ихся между версиями Oracle9i Release 2 и Oracle l lg, а теперь Oracle 1 2с, феноменально велико. В версии Oracle ! Og инструментирование кода ядра бьmо поднято на совершенно новы й уровень благодаря появлению средств AWR (Automatic Workload Repository - репозиторий автоматической рабочей на­ грузки) и AS H (Active Session Н istory - хронология активных сеансов). В Oracle l lg бьmи введен ы новые средства - ADR (Automatic Diagnostic Repository - репози­ тор и й автоматической диагности ки) и S PA (SQL Performance Analyzer - анализа­ тор производительности SQL). В версии Oracle 1 2с разработчики продвинулись еще дальше, добавив журнал D D L для отслеживания всех операций DDL в базе данных (того, что не должно происходить во многих ти повых производственных базах дан­ ных изо дня в ден ь) и журн ал отладки для отслеживания исключительных условий в базе данных. В этом разделе м ы сосредоточи м внимание на и нформаци и , которую можно найти в трассировочн ых файлах различных типов. Мы рассмотрим, что они собой представляют, где хранятся и что с ними можно делать. Существуют два основных типа трассировочных файлов, и предоставляемые ими возможности значительно отличаются. • • Ожидаемые и желательные трассировочные файлы. Примерам могут служить файл ы , генерируемые в резул ьтате вкл юче н ия D B M S _MON I T O R . S E S S I ON TRACE_ ENABLE. Они содержат диагностическую и нформацию о сеансе и по­ могают в настройке приложения для оптим изации производительности и диа­ гностирования любых имеющихся узких мест. Трассировочные файлы, которые не ожидались, но были сгенерированы сервером в результате ошибок ORA-00600 "lnternal Error" (Внутренняя ошибка), ORA-03 1 13 "End of file оп communication channel" (Конец файла в канале передачи данных) или ORA-07445 "Exception Encountered" (Возникло исключение). Эти трассиро­ вочн ые файлы содержат диагностическую информацию, которая предназначе­ на главным образом для использования аналитиками службы поддержки Oracle и помогает выявить место возни кновения внутренних ош ибок в приложении. Применение этих файлов разработчиками приложений ограничено. Файл ы 1 57 Запрошенные трассировочные ф айл ы Трассировоч ные файл ы , которые ожидаются разработч икам и , чаще всего гене­ рируются в результате включен ия трассировки посредством DBMS _MON I TOR (ALTE R S E S S I ON S E T S Q L_T RAC E = T RU E в Oracle9i Release 2 и предшествующих версиях) либо использован ия расширенной трассировки через событие 1 0046, как показано ниже: EODA@ORA12CR1> a1ter s e s s ion s et events 2 ' 1 0 0 4 6 trace name context forever , leve l 1 2 ' 3 1 Sess ion al tered . Сеанс изменен . Эти трассировочные файл ы содержат диагностическую информацию и и нформа­ цию, относящуюся к производительности . Они открывают бесценные подробности внутренней работы вашего приложен ия базы данных. В нормально функционирую­ щей базе дан ных вы будете видеть такие трассировоч н ые файлы гораздо чаще , чем трассировочные файлы любого другого вида. Местоположения файлов Независимо от того, используется DBMS MON I TOR, SQL_TRACE или расширенная функция трассировки , Oracle начнет генерировать трассировочный файл в одном из следующих мест на компьютере сервера базы данных. • Есл и вы приме няете подключе н и е посредством выделен но го сервера, то трассировочный файл будет сгенерирован в каталоге , указан ном в параметре u s e r_dump_de s t . • Если в ы и с п ол ьзуете п одкл юче н ие посредством разделяе м о го сервера , то трасс ировочн ы й файл будет создан в каталоге , указан ном в п араметре background_dump_de s t . Чтобы посмотреть, куда попадут трассировочные файл ы , можно выдать коман­ ду show pa rame t e r dump_de s t в SQL* Plus, запросить представление V$ PARAМET ER, воспользоваться созданной ранее процедурой ( S COTT . GET _ РАRАМ) или запросить новое представление V$ D I AG_ I N FO . Н иже все перечисленные приемы демонстри­ руются по очереди . EODA@ORA1 2 CR1> show parameter dump_des t NАМЕ ТУРЕ VALUE background_dump_de s t s t r ing core_dump_des t string user_dump_de s t s t r ing / home /ora 1 2 cr 1 / app/ ora 1 2 c r 1 /diag/ rdbms /ora 1 2 cr 1 /ora 1 2 cr 1 / trace / home /ora 1 2 cr 1 / app/ora 1 2 c r 1 /diag/ rdbms / ora 1 2 c r 1 /ora 1 2 c r 1 / cdump / home / o ra 1 2 c r 1 / app/ ora 1 2 c r 1 /diag/ rdbms / ora 1 2 cr 1 / o ra 1 2 c r 1 / trace Эта команда отображает три местоположе н и я файлов дамп а (трассировки ) . Каталог фонового дам па используется любым " сервер н ы м " процессом (пол н ы й список фоновых процессов Oracle и выполняемых ими функций в ы найдете в гла­ ве 5). Параметр core _dump_de s t (местоположение дампа ядра) применяется для 1 58 Глава 3 выгрузки "дампа ядра" (очен ь детальная диагностическая и нформация о процес­ се) при возникнове н и и серьезной проблемы , такой как аварийный отказ процесса. Параметр u s e r_dшnp_de s t (местоположение пользовательского дампа) использует­ ся подключениями посредством выделенного и разделяемого сервера (описанными в главе 2), когда они генерируют трасси ровочн ы й файл. Чтобы продолжить исследование разнообразных методов просмотра этих место­ положен и й для дампов, давайте взглянем на доступные таблицы V$ : EODA@ORA12CR1> s e l ect name , va lue 2 from v$parameter 3 where name l i ke 1 % dump_des t % 1 ; NАМЕ VALUE background_dump_de s t /home / o ra 1 2 cr l / app / ora 1 2 cr 1 /diag/ rdЬms /ora 1 2 cr 1 /ora 1 2 cr 1 / t race /home / o ra 1 2 c r 1 / app/ora 1 2 cr 1 /diag/ rdЬms /ora 1 2 c r 1 /ora 1 2 cr 1 / trace / home / o ra 1 2 c r l / app /ora 1 2 c r 1 /diag/ rdЬms /ora 1 2 c r l / or a 1 2 cr 1 / cdump u s er_dump_de s t core_dump_de s t Конечно, для запрашивания табл и цы V$ PARAМETER можно было бы также применить пакет DBMS _uт I L I T Y с ранее созданной функцией sсотт . GET_РАRАМ: EODA@ORA12CR1> s e t s erve routput on EODA@ORA12CR1> ехес dЬms_output . put_line ( scott . get_param ( 1 USer_dump_dest 1 ) ) / home / o ra 1 2 c r 1 / app /ora 1 2 c r 1 /diag/ rdbms / ora 1 2 c r 1 /ora 1 2 c r 1 / t race PL/ SQL procedure succe s s fu l l y comp leted . Процедура PL/SQL успешно выполнена . В версии Oracle l lg было добавлено новое средство - ADR. Частью его функци­ ональности является новое представление V$ по имени V$ DIAG_ INFO. Н а заметку! V $ D I AG_I N FO - это представление, доступное в Oracle 1 1 g ( и последующих версиях), которое в старых выпусках отсутствует. Оно предлагает более легкий интерфейс для работы с трассировочной информацие й , используемый новым средством ADR . В целях улучшения читабельности в выводе следующего запроса к V$ D IAG_INFO дл и нное путевое и мя к домашнему каталогу AD R (AD R Ноте) заменено $ home $ . Это просто облегчает его восприятие в кни ге ; поступать так н е обязательно: EODA@ORA 1 2 CR 1 > with home 2 as 3 ( se l ect val ue home 4 f rom v$di ag_info 5 whe re name = 1 ADR Home 1 6 7 s e l ect name , 8 cas e when va lue <> home . home 9 then replace ( val ue , home . home , 1 $ home $ 1 ) 10 e l s e value end value 11 12 from v$di ag_i n fo , home 13 1 Файлы NАМЕ VALUE Diag EnaЬled ADR Ba se ADR Home TRUE / home / o ra 1 2 c r 1 / app/ora 1 2 c r 1 / home / o ra 1 2 c r 1 / app/ora 1 2 c r 1 /di ag/ rdЬms /ora 1 2 cr 1 / o ra 1 2 c r 1 Diag Trace Diag Alert Diag I ncident Diag Cdump Health Monitor De fault Trace File $ home $ / trace $ home $ /alert $ home $ / incident $ home $ / cdump $home $ / hm $home $ / trace/ora 1 2 c r 1 ora 2 2 3 1 9 . tr c Active ProЬlem Count Active I ncident Count о 1 59 о 11 rows sel ected . 1 1 строк выбрано . Как видите , строки содержат пути к местоположениям разных трассировочн ых файлов. В Oracle l lg модернизированы соглашения о местах, где м ногие файл ы хранятся по умолчанию, отличаясь чуть более удобной организацией; это упрощает процесс поддержки , когда вы протоколируете запрос службы в Oracle Support. Н иже описаны наиболее важные строки . • D i ag T r a c e (Трассировка диагностики ) . Место, куда попадают трассировоч­ ные файл ы - как фоновые, так и пользовательского дампа - в Oracle l l g и последующих версиях. • De fault T race F i l e (Файл трассировки по умолчанию). Имя трассировочно­ го файла вашего текущего сеанса. В ранн их выпусках выяснить это имя было непросто (далее будет показано, каким образом) . В Oracle Database l l g и пос­ ледующих версиях простой запрос к V$ D IAG_I N FO возвращает полностью оп­ ределенное имя файла. До выхода Oracle l lg и добавления информации De fault Trace F i l e вы должны были искать трассировочный файл вручную. Если применяется подключение к раз­ деляемому серверу Oracle , то используется фоновый процесс, так что расположение трассировочных файлов определяется в bac kground_durnp_de s t . В случае подклю­ чения к выделен ному серверу для взаимодействия с Oracle применяется пользова­ тельский процесс или процесс переднего плана, и трассировочные файлы попадают в каталог, указанный в параметре us e r_durnp_de s t . П араметр c o r e _dump _de s t определяет, где будет сгенерирован файл "ядра" в случае возникновения серьезной внутренней ошибки Oracle (вроде ошибки сегмен­ тации в U N I X/Linux) , или если в службе поддержки Oracle вас попросят е го сгене­ рировать для получения дополнительной отладочной и нформации. Вообще говоря, нас и нтересуют местоположен ия фонового и пользовательского дампов. Если не указано иное, то на протяжен и и этой кн и ги мы будем использовать подключен и я посредством выделенного сервера, так что все трассировочные файлы будут генери­ роваться в местоположении u s e r_durnp_de s t . 1 60 Глава 3 Соглашение об именовании Соглашение об именован и и трассировочных файлов в Oracle время от време­ ни меняется , но есл и вам известен пример имени трассировочного файла из име­ ющейся систе м ы , то выясн ить применяемый шаблон не составит особого труда. Например, на моих разнообразных серверах U N I X/Linux имена трассировоч ных файлов выглядят так, как показано в табл . 3. 1 . Таблица 3 . 1 . Примеры имен трассировочных файлов Версия базы данных И мя трассировочного файла ora 1 0 5 8 3 . trc 9i Release 1 ora 9 i r 2 ora 1 9 0 5 . trc 9i Release 2 ora l 0gr2_ora_6 7 9 3 . trc 1 Og Release 2 ora l l gr2_o ra_l 9 9 0 . trc 1 1 g Release 2 ora l 2 c r l ora 2 3 4 4 . trc 1 2с Release 1 На моих серверах и мя трассировочного файла может быть разбито на части сле­ дующим образом. • П ервая часть имени файла O RACLE _ s I о (за исключением версии Oracle9i Release l , в которой реш ил и эту часть опустить). • Следующая часть имени файла - просто ora. • Н омер в имени трассировочного файла - это идентификатор процесса выде­ ленного сервера, доступный через представление V $ P ROCES S . - Таким образом, д о выхода версии Oracle l lg, где было удобно использовать пред­ ставление V$ DIAG_ I N FO, на практике (предполагая режим выделенного сервера) для определения имени трассировочного файла требовался доступ к четырем представ­ лениям: • V$ P A R AM E T E R , п р и м е н я емое для нахожден ия трассировоч н ого файла u s e r_dump_de s t и необязательного идентификатора t race f i l e_ident i f ier, который может быть использован в имени трассировочного файла; • V$ PROCE S S , применяемое для нахожден ия идентификатора процесса; • V$ S E S S I ON , используемое для корректной идентификации информации о се­ ансе в других представлениях; • V$ I NSTANCE , применяемое для получения ORACLE_S I D. Как упом и налось ранее, для выяснения местоположения файлов можно ис­ пользовать утилиту овмs _UT I L I T Y . Кроме того, часто идентификатор ORACLE_S I D просто " известе н " , поэтому формально требуется доступ только к Представлениям V$ S ES S I ON и V$ PROCE S S , но для упроще н ия работы может понадобиться доступ ко всем четырем представлениям. Следовательно, запрос для генерации имени трассировочного файла мог бы вы­ глядеть так: Файл ы 161 EODA@ORA1 2 CR1 > column trace new va l TRACE format a l O O EODA@ ORA1 2 CR1 > s e lect c . value 1 1 1 / 1 1 1 d . ins tance_name 1 1 1 ora 1 a . spid 1 1 1 . t rc 1 t race 2 from v$process а , v $ s e s s ion Ь , v$pa ramete r с , v$ins tance d 3 whe re а . addr = Ь . paddr 4 and Ь . auds id = userenv ( 1 s e s s ionid 1 ) 5 and c . name = 1 Us er_dump_de s t 1 6 1 1 1 TRACE /home/ ora 1 2 c r l / app/ora 1 2 c r l /diag / rdЬms /ora 1 2 c r l / o ra 1 2 c r l / t race / � ora 1 2cr l_ora_2 2 3 1 9 . t rc Вы вод как раз показывает, что если файл существует, то к нему можно обратить­ ся по такому имени (при наличии разрешений на чтение каталога трассировки ) . В следующем примере генерируется трассировочный файл , демонстрируя создание файла после включения трассировки : EODA@ORA1 2 CR1 > ! l s &TRACE l s : cannot acce s s /home/o ra 1 2 cr l /app/ora 1 2 c r l /diag/ rdЬms / o ra 1 2 cr l / ora1 2 c r l / t race/ora 1 2 c r l_ora_2 2 3 1 9 . trc : No s uch f i l e o r di rectory l s : невозможен доступ к /home/ora 1 2crl /app/ora 1 2 crl /di ag/rdЬm s/ora 1 2crl / ora 1 2crl / t ra ce/ora 1 2crl_ ora_ 2231 9 . trc : Нет такого файла или ка талога EODA@ORA12CR1> ехес dЬms moni tor . se s s ion trace enaЬle PL/ SQL procedu re succe s s ful l y comple ted . Процедура PL/SQL успешно вшюлнена . EODA@ORA1 2CR1> ! l s &TRACE /home /ora 1 2 cr l / app/ora 1 2 cr l /diag/ rdbms /o ra 1 2 c r l / o ra 1 2 c r l / t race / ora1 2crl ora 2 2 3 1 9 . trc Как видите , перед включением трассировки в этом сеансе файл не существовал; однако, как только трассировка включена, мы можем его видеть. Должно быть очевидным, что в среде Windows символы 1 понадобится заменить символами \ . В случае применения верс и и Oracle9i Release l вместо добавления имени экземпляра в имя трассировочного файла понадобится просто выдать следу­ ющий запрос: se lect c . value 1 1 1 ora_ 1 1 1 a . spid 1 1 1 . trc ' Маркирование трассировочных файлов Существует способ "маркирования" трассировоч н ых файлов, позволяющий нахо­ дить их, даже когда доступ к Представлениям V$ PROCE S S и V$ S E S S I ON не разрешен. При наличии доступа по чтени ю к каталогу u s e r_durnp_de s t можно использовать параметр сеанса t race f i l e_ ident i f ie r . С его помощью к имени трассировочного файла можно добавить уни кально идентифицируемую строку, например: EODA@ORA1 2 CR1 > alter s e s s ion set trace f i l e identi f i e r = 1 Look For Ме 1 ; Session al tered . Сеанс изменен . EODA@ORA1 2CR1> ! l s /home /ora 1 2 c r l / app/ora 1 2 c r l /diag/ rdЬms / o ra 1 2 c r l / ora 1 2 cr l / trace / * Look_For_Me * 1 62 Глава 3 l s : cannot acce s s / home / ora 1 2 cr l / app/ ora 1 2 c r l /diag/rdЬms /ora 1 2 c r l / ora 1 2 cr l / trace / * Loo k_For_Me * : N o s uch file or directory l s : невозможен доступ к /home/ora 1 2crl /app/ora 1 2crl /di a g/rdЬms/ora 1 2crl / ora 1 2crl / tra ce/ *Look_For_Me * : Нет такого файла или ка талога EODA@ ORA1 2CR1 > ехес dbms monitor . se s s ion t race еnаЫе PL/ SQL procedure succe s s fu l l y completed . Процелура PL/SQL успешно выполнена . EODA@ ORA 12CR 1> ! l s / home / o ra 1 2 cr l / app /ora 1 2 c r l /diag/ rdЬms / ora 1 2 c r l /ora l 2 cr l / trace/ * Look For Ме* П редшествующая строка кода не умещается в физические границы печатной страницы, поэтому в книге она разнесена на две строки , хотя должна вводиться как одна строка. Команда l s и щет файлы в следующем каталоге: /home / o ra 1 2 cr l /app/ora 1 2 c r l /diag / rdЬms /ora 1 2 c r l /ora l 2 c r l / trace Символ * представляет собой групповой символ, указывающий команде ls на необ­ ходимость поиска любых файлов, в имени которых присутствует строка Look_ For_Ме. В этом примере предыдущая команда 1 s обнаруживает два таких файла: / home / o ra 1 2 cr l /app /ora l 2 cr l /diag/ rdЬms /ora 1 2 c r l /ora l 2 c r l / trace/ ora 1 2 c r l ora 2 2 4 8 9 Look For Me . t rc / home /ora 1 2 cr l / app/ora l 2 c r l /diag/ rdЬms /ora l 2 cr l /ora l 2 cr l / trace / ora 1 2 cr l ora 2 2 4 8 9 Look For Me . t rm Как видите , теперь трассировочному файлу назначено и мя в стандартном форма­ те <ORACLE_S I D>_ora_< PROCE S S_I D>, но с ним связана также заданная уникальная строка, что позволяет без особых затруднений найти и мя "нашего" трассировочного файла. Трассировочн ы й файл имеет расширение t r c. И меется также соответству­ ющи й файл отображения трассировки (с расширением t rm) , в котором находится структурная и н формация о трассировочном файле. Обычно вас будет интересовать только содержимое файла t r c . . . . Трассировочные ф айл ы , генерируемые в ответ на внутренние о ш ибки Этот раздел я хотел бы завершить рассмотрен ием несколько иного вида трасси­ ровочных файлов - файлов, генерируемых в результате ошибки ORA- 0 0 6 0 0 или ка­ кой -то другой внутрен ней ошибки . М ожно ли с ними что-то делать? Если ответить на такой вопрос коротко, то эти файлы предназначены не для нас с вами - их испол ьзуют сотрудники службы поддержки Oracle. Однако они могут пригодиться при запол не н и и запроса службы поддержки Oracle. Важно запомнить следующее: если вы столкнулись с внутрен н и м и ошибками , то еди нственный спо­ соб их устранен ия заключается в заполнении запроса службы поддержки . Есл и вы просто проигнорируете их, ошибки никогда не исчезнут сами по себе, разве что слу­ чайно. Напри мер, при создании следующей таблицы и выполнении запроса в Oracle ! Og Release 1 вполне можно получить сообщен ие о внутрен ней ошибке (или же не по­ лучить; эта ошибка была выявлена и устранена в последующих исправлениях этого выпуска): Файл ы 1 63 ops $ t kyte @ORA1 0G> create taЬle t ( х int prirnar y key ) ; ТаЬlе created . Та блица создана . ops $ t kyte @ORA1 0G> insert into t va lues ( 1 ) ; 1 row created . 1 строка создана . op s $ t kyte @ORA1 0G> ехес dbrns s tats . gather taЬl e_stats ( u s e r , ' Т ' ) ; PL/ SQL procedure succe s s fully cornpleted . Процедура PL/SQL успешно выполнена . ops $ t kyte @ORA1 0G> s e l ect count ( x ) over ( ) 2 frorn t ; frorn t * ERROR at l ine 2 : ORA-00600 : internal error code , argurnents : [ 1 2 4 1 0 ] , [ ] , [ ] , [ ] , [ ] , [ ] , [ ] , [ ] ОШибка в строке 2 : ORA- 00600 : код внутренней ошибки, аргументы: [ 1241 0 } , [} , [ } , [} , [} , [} , [ } , [ } Теперь представьте , что вы - адми н истратор базы данных, и этот трассировочный файл вдруг появляется в области трасси ровки . Или же вы - разработчик, и ваше приложение вызывает ошибку ORA- 0 0 6 0 0 , поэтому нужно выяснить, что про­ изошло. Этот трассировочный файл содержит огромн ы й объем информации (около 35 000 строк) , но в целом для вас и для меня он не особенно полезен. В общем слу­ чае нужно было бы просто сжать его и загрузить как часть запроса службы . В Oracle l lg и последующих версиях процесс сбора трассировочной информации и ее загрузки в службу поддержки был модифицирован (и стал значительно проще). Новый инструмент командной строки в сочетании с пользовательским интерфейсом диспетчера предприятия позволяет просматри вать трассировочную информаци ю в ADR, упаковывать ее и передавать в службу поддержки Oracle. Инструмент ADRC I (Automatic Diagnostic Repository Command I nterpreter - ко­ мандный интерпретатор репозитория автоматической диагностики) позволяет про­ сматривать " проблемы" (критические ошибки в базе данн ых) и инциденты (случаи возникновения этих критических ошибок) , а затем упаковывать их для передачи в службу поддержки. Шаг упаковки включает извлечение не только трассировочной информации , но также деталей из сигнального журнала базы дан н ых и прочей кон­ фигурационной/тестовой информации . Например, я создал в своей базе данных ус­ ловия для возни кновения критической ошибки. (Я не собираюсь сообщать какие­ либо подробности . Вы должны генерировать собствен н ые критические ошибки . ) Я узнал, что в базе данных присутствует " проблема " , т. к. инструмент ADRCI сооб­ щил следующее : [ ora 12 c r1 @dellpe - ] $ adrci ADRCI : Release 1 2 . 1 . 0 . 1 . 0 - Product i on оп Mon Sep 2 1 7 : 4 5 : 3 8 2 0 1 3 Copyright ( с ) 1 9 8 2 , 2 0 1 3 , Oracle and/or its affiliates . ADR base = " /horne /ora 1 2 c r 1 /app / o ra 1 2 cr 1 " adrci > s how proЬlern All rights reserved . 1 64 Глава 3 ADR Home = / home / o ra 1 2 c r 1 /app / o ra 1 2 c r 1 /diag/ rdbms /ora 1 2 c r 1 /ora 1 2 cr 1 : *********************************************************************** PROBLEM I D PROBLEM КЕУ LAST INCI DENT LAS T I NC T I ME ORA 7 4 4 5 [ qctcopn ] 3 62 8 1 1 2 0 1 3-0 9-02 1 7 : 52 : 1 1 . 4 3 8 000 -04 : 0 0 2 сентября 20 1 3 года я вызвал в базе данных ошибку ORA- 4 0 3 1 - серьезную про­ блему (ошибка бьmа зафиксирована и исправлена) . Теперь я могу посмотреть, что затронула эта ошибка, выдав команду s how i n c i dent: adrci > show incident ADR Home = / home / o ra 1 2 c r 1 / app/ora 1 2 c r 1 /diag / rdЬms /ora 1 2 cr 1 /ora 1 2 cr 1 : *********************************************************************** INCI DENT I D PROBLEM КЕУ CREATE T IME 3 62 4 9 3 62 5 0 3 62 8 1 ORA 7 4 4 5 [ qctcop n ] ORA 7 4 4 5 [ qctcopn ] ORA 7 4 4 5 [ qctcopn ] 2 0 1 3 -0 9- 0 2 1 7 : 4 5 : 0 6 . 7 9 1 0 0 0 - 0 4 : 0 0 2 0 1 3 - 0 9- 0 2 1 7 : 5 1 : 5 8 . 4 6 9 0 0 0 - 0 4 : 0 0 2 0 1 3 - 0 9- 0 2 1 7 : 52 : 1 1 . 4 3 8 0 0 0 - 0 4 : 0 0 Я отмечаю наличие трех инцидентов и с помощью команды s how t ra c e f i l e могу вывести и нформацию, связанную с каждым и з них: adrci> show trace f i l e -I 3 6 2 5 0 diag/ rdЬms / ora 1 2 c r 1 / o ra 1 2 c r 1 / inciden t / in cdi r_3 62 5 0 / ora 1 2 c r 1 o r a 2 2 6 8 2 i 3 6 2 5 0 . trc Это показывает местоположение трассировочного файла ДJIЯ инцидента номер 36250. Более того, при желани и я могу просмотреть массу деталей об инциденте: adrci > show i ncident -mode detail -р " incident_id= 3 62 5 0 " ADR Home = / home / ora 1 2 cr 1 / app /ora 1 2 c r 1 /di ag/ rdЬms / or a 1 2 c r 1 /ora 1 2 cr 1 : *********************************************************************** ********************************************************** INCI DENT I N FO RECORD 1 ********************************************************** I NC I DENT I D STATUS CREATE T I ME PROBLEM I D CLOSE T IME FLOOD CONTROLLED ERROR FAC I L I TY ERROR NUМBER ERROR ARG1 ERROR ARG2 ERROR ARG 3 ERROR ARG4 ERROR ARG5 ERROR ARG 6 ERROR ARG7 ERROR ARG8 ERROR ARG9 ERROR ARG 1 0 ERROR ARG 1 1 ERROR ARG 1 2 36250 ready 2 0 1 3 - 0 9- 0 2 1 7 : 5 1 : 5 8 . 4 6 9 0 0 0 - 0 4 : 0 0 1 <NULL> none ORA 7445 qctcopn S I GS EGV ADDR : O x 1 8 РС : ОхВ8 5 9 5 1 2 Addre s s not mapped t o obj ect <NULL> <NULL> <NULL> <NULL> <NULL> <NULL> <NULL> Файл ы 1 65 S IGNALLING COMPONENT S I GNALLING SUBCOMPONENT SUS PECT COMPONENT SUS PECT SUBCOMPONENT ECID IMPACTS PROBLEM КЕУ FIRST INCI DENT FIRSTINC T I ME LAST INCI DENT LASTINC T IME IMPACT 1 IMPACT2 I МРАСТЗ IMPACT 4 КЕУ NАМЕ КЕУ VALUE <NULL> <NULL> <NULL> <NULL> <NULL> О ORA 7 4 4 5 [ qctcopn ] 3624 9 2 0 1 3 - 0 9- 0 2 1 7 : 4 5 : 0 6 . 7 9 1 0 0 0 - 0 4 : 0 0 3 62 8 1 2 0 1 3 - 0 9- 0 2 1 7 : 52 : 1 1 . 4 3 8 0 0 0 - 0 4 : 0 0 О О О О Cl ient Proc ! d oracle @del lpe ( TNS V1 -V3 ) . 2 2 68 2 1 4 0 2 3 9 5 0 2 6 62 1 1 2 КЕУ NАМЕ SID 41 6 . 23 КЕУ VALUE КЕУ NАМЕ Proc i d КЕУ VALUE 31 . 41 PQ КЕУ NАМЕ ( 0 , 13781587 17 ) КЕУ VALUE 1 OWNER I D INCI DENT_FILE /home / o ra 1 2 c r 1 /app/ora 1 2 c r 1 /diag/ rdbms / ora 1 2 c r 1 /ora 1 2 c r 1 / t race /ora 1 2 c r 1_ora_2 2 6 8 2 . t r c OWNER I D 1 INCI DENT_FI LE /home /ora 1 2 c r 1 / app / o ra 1 2 c r 1 /diag / rdЬms / ora 1 2 c r 1 /ora 1 2 c r 1 / inciden t / i ncdi r 3 62 5 0 /o ra 1 2 c r 1 ora 2 2 6 8 2 i 3 62 5 0 . tr c - - - - И , наконец, я могу создать " пакет", включающий сведен ия об инциденте , кото­ рый будет полезен для службы поддержки . П акет будет содержать все , что необхо­ димо аналитикам службы поддержки для начала работы над проблемо й . Настоя щий раздел не претендует на то, чтобы быть исчерп ы вающим обзором или введением в утилиту ADRC I , которая пол ностью документирована в руководс­ тве Oracle Database Utilities (Утилиты базы дан ных Oracle). Вместо этого я просто хо­ тел напомнить о существовани и этого инструмента - и нструмента, облегчающего использование трассировочных файлов. До появления утилиты ADRC I в верс и и Oracle l lg могл и л и вы делать с неза­ планированными трассировочн ы м и файлами что-то помимо отправки их в службу поддержки? Да, в них присутствует информация , которая может помочь ответить на вопросы о том , какая произошла ошибка и где именно. Трассировоч н ы й файл мо­ жет также помочь при возникновении ряда других проблем . Предыдущи й пример продемонстрировал , что ADRC I предлагает удобный спо­ соб анализа трассировочных файлов в Oracle 1 2с (здесь бьша показана лишь малая часть доступных команд) . В Oracle 1 Og и предшествующих версиях вы могл и делать то же самое, хотя с большей долей ручного труда. Н апример, даже беглый взгляд на начало трассировочного файла предоставляет некоторую полезную и нформацию: /home /ora 1 0gr1 /admin/ora 1 0 g r 1 / udump / o ra 1 0 g r 1_ora_2 5 7 8 . trc Oracle Database 1 0 g Enterpr i s e Edition Re lease 1 0 . 1 . 0 . 4 . 0 - P roduction 1 66 Глава 3 With the Pa rtition i ng , OLAP and Data Mining opt ions ORACLE НОМЕ = /home / o ra 1 0 g r 1 L inux System name : del lpe Node name : 2 . 6 . 9 - 1 1 . ELsmp Re 1ea s e : # 1 SMP Fri Мау 2 0 1 8 : 2 6 : 2 7 E DT 2 0 0 5 Ve rS lOП : i686 Machine : I n s tance name : o ra 1 0 g r 1 Redo thread mounted Ьу t h i s ins tance : 1 Oracle p roce s s numЬe r : 1 6 Unix proce s s pid : 2 5 7 8 , image : orac l e@de l 1pe ( TNS V1 - V3 ) И нформацию о базе данных важно иметь при заполнении запроса службы под­ держки на сайте h t t p : 11 supp o r t . o r a c l e . с от или при выяснении, является ли то, с чем вы столкнулись, известной проблемой. Вдобавок вы можете просмотреть экземпляр Oracle, в котором произошла ошибка. Довольно часто параллельна вы­ полняются несколько экземпляров, так что изоляция проблемы в конкретном эк­ земпляре весьма полезна. А вот другой раздел трассировочного файла, о котором следует знать: * * * 2 0 1 0-0 1-2 0 1 4 : 32 : 4 0 . 00 7 * * * ACT I ON NАМЕ : ( ) 2 0 1 0 - 0 1 - 2 0 1 4 : 3 2 : 3 9 . 9 8 8 * * * MODULE NАМЕ : ( SQL * Plus ) 2 0 1 0 - 0 1 - 2 0 1 4 : 3 2 : 3 9 . 9 8 8 * * * SERV I CE NАМЕ : ( SY S $ US ERS ) 2 0 1 0 - 0 1 - 2 0 1 4 : 3 2 : 3 9 . 9 8 8 Эта часть трассировочного файла присутствует только в Oracle ! Og и последу­ ющих версиях; в Oracle9i и предшествующих версиях ее нет. Она показывает до­ ступную и нформацию о сеансе в столбцах ACT I ON (действие) и MODULE (модуль) представления V$ S E S S I ON . Здесь можно выяснить, какой сеанс SQL* Plus при вел к возни кнове н и ю ошибки (вы и ваши разработчики можете и должны установить информацию ACT ION и MODULE; некоторые среды , такие как Oracle Fonns и АРЕХ, делают это автоматически) . Кроме того, здесь есть строка S ERV I CE N АМ Е (имя службы ) . Это имя реальной службы , которая применялась для подключения к базе данн ых ( S Y S $ U S E RS в рас­ сматр иваемом случае) ; легко заметить, что подключение осуществлялось не через службу TN S . Если бы мы вошли в базу данных, используя u s e r / pa s s @ o r a l O g . l o c a l doma i n , то могл и бы видеть такую строку: * * * SERV I CE NАМЕ : ( ORA 1 0 G ) 2 0 1 0 - 0 1 - 2 0 1 4 : 3 2 : 3 9 . 9 8 8 Здесь o ra l O g - имя службы (не строка подключения TN S ; точнее, оно пред­ ставляет собой имя конечной службы , зарегистрированной в проелушивающем про­ цессе TNS , к которому произведено подключен ие) . Эта и нформация полезна также при отележивани и процессаjмодуля, на которы й повлияла возникшая ошибка. В заключен и е, прежде чем переходить к действительной ошибке , можно выяс­ нить идентификатор сеанса ( 1 9 в этом примере), порядковый номер сеанса (27995 в этом примере) и связанную с ним информацию даты/времени ( все выпуски) : * * * S E S S I ON I D : ( 1 9 . 2 7 9 9 5 ) 2 0 1 0 - 0 1 - 2 0 1 4 : 3 2 : 3 9 . 9 8 8 Теперь м ы готовы к анализу самой ошибки : ksedmp : inte rnal o r fata1 e r ro r ksedmp : внутренняя или неисправимая ОIIIИбка Файлы 1 67 ORA- 0 0 60 0 : interna l error code , argument s : [ 1 2 4 10 ] , [ ] , [ ] , [ ] , [ ) , [ ] , [ ] , [ ] ORA - 0 0 60 0 : код внутренней опмбки, аргументы: [ 1 24 1 0 ] , [ ] , [ ] , [ ] , [ ] , [ ] , [ ] , [ ] Current SQL staternent f o r t h i s s e s s ion : Текущий SQL -oпepa тop для этого сеанса : select count ( x ) ove r ( ) frorn t - -- -- Cal l Stack Trace - - - - - - - - - �а ссировка стека вызовов ksedrnp+ 52 4 ks fdrnp . 1 6 0 + 1 4 kgeriv+ 1 3 9 kgesi v+ 7 8 ks es i c 0 + 5 9 _qe rixAl locate+ 4 1 5 5 _qknRwsAl locateTree+ 2 8 1 _qknRwsAl locateTree+ 2 5 2 _qknRwsAl locateT ree+ 2 5 2 _qknRwsAl locateTree+ 2 5 2 _qknDoRwsAl locate+ 9 Здесь мы видим пару важных фрагментов и нформации . П ервый и з н их - SQL­ oпepaтop , которы й выполнялся в момент возникнове н ия внутренней ошибки , что оче нь полезно для отслеживания п р иложен ия или п р иложе н и й , подвергш ихся влиянию ошибки . Кроме того, поскольку мы располагаем и нформацией об SQL­ oпepaтope , мы можем начать поиск возможных способов обхода ошибки - опро­ бовать разные способы кодирования SQ L-зaпpoca, чтобы выяснить возможность быстрого обхода проблемы на время , пока ведутся работы по устранению внутрен­ ней ошибки . Более того, можно вырезать и вставить подозрительный SQ L-oпepaтop в среду интерфейса SQL* P ius и посмотреть, удастся ли получить воспроизводимый тестовый сценарий для службы поддержки Oracle (естественно, это наиболее пред­ почтительный подход) . Вторым важным фрагментом и нформации является код ошибки (обычно 600, 3 1 1 3 или 7445) и другие аргументы, связанн ые с кодом ошибки . Эти сведен ия в со­ четании с и нформацией трассировки стека, которая показывает набор и порядок вызова внутренних подпрограмм Oracle, могут помочь в нахожден и и суrnествующей программной ошибки ( и способов ее обхода, заплат и т. п . ) . Например, вот как мо­ жет выглядеть строка поиска: ora - 0 0 6 0 0 1 2 4 1 0 k s e s i c O qe rixAl locate qknRwsAl locateTree С помощью расширенного поиска ( поиска в базе дан ных программных ошибок с применением всех слов) на сайте М у Oracle Support (М оя поддержка Oracle) мы немедленно находим ошибку 38006 1 4, "ORA-600 [ 1 24 1 0] ON S I M PLE QU ERY WITH ANALYТI C FU NCTION " (O RA-600 [ 1 24 1 0] на простом запросе с анал итической функцией ) . Есл и вы перейдете на сайт h t t p : 1 / s up p o r t . o r a c l e . с от и поище­ те приведенный текст, то обнаружите сведен ия об этой ошибке, выясните, что она была исправлена в следующем выпуске , и узнаете , что для нее имеются заплаты вся эта информация доступ на. Я многократно убеждался в том, что возни кающая в моей системе ошибка уже случалась ранее, и для нее есть исправления или способы обхода. 1 68 Глава 3 Заклю чительны е соображения по поводу трассировочных ф айлов Итак, вы теперь знаете два типа основных трассировочн ых файлов, места их хра­ нения и способы их нахождения . Будем надеяться , что вам придется использовать трассировочн ые файлы главным образом для настройки и повы шения производи­ тельности приложений , а не для заполнения запросов в службу поддержки . В за­ ключение хочу отметить, что сотрудники службы поддержки Oracle имеют доступ ко многи м недокументированным "событиям " , которые очень полезны для извлечения огромного объема диагностической информации при возникновении любой ошиб­ ки в базе данн ых. Например, если ошибка O RA- 0 1 5 5 5 Snaps hot Т о о O l d (слиш­ ком старый снимок) возникла в ситуации , в которой , по вашему мнению, это было совершенно невозможно, то сотрудники службы поддержки помогут выполнить на­ стройку таких диагностических событий для отслеживания точной причины ошибки путем создания трассировочного файла при каждом ее возникновении. С и г нальны й файл С и гнальный файл (также известн ый как сигнальный журнал (alert log) ) - это своего рода ежедневник базы данных. Он представляет собой простой текстовый файл , заполняемый с момента "рожден ия " (создания) базы дан н ых и до ее пос­ леднего дня (когда она будет удалена) . В этом файле вы найдете зап исан ные в хронологическом порядке исторические сведения о базе дан н ых - переключения журнальных файлов, возможные внутренние ошибки , время создания табличных пространств, их отключения и повторного подключения и т. п . Этот файл чрезвы­ чайно полезен для просмотра хронологии базы данн ых. Я совершенно убежден, что чем больше и н формации содержит этот файл , тем лучше, поэтому позволяю ему становиться достаточно большими, прежде чем его архивировать. Я не стану описывать абсол ютно все , что попадает в сигнальный журнал - эта тема достаточно обш ирна. Однако я рекомендую просмотреть его у себя и оценить обилие содержащейся в нем и нформации . В этом разделе мы рассмотрим конкрет­ н ы й пример извлече н ия информаци и из сигнального журнала - в дан ном случае для создания отчета о работе базы данных. В прошлом я применял файл сигнального журнал а для веб-сайта h t t р : 1 1 a s kt om . o r a c l e . сот и для генераци и отчета о работоспособности своей базы дан­ н ых. Вместо того чтобы вручную проходить по файлу и выяснять, что происходи­ ло (в частности , время запуска и остановки базы данных) , я решил воспользоваться преимуществами , предлагаемыми СУБД и языком SQL, для автоматизации таких работ. Результатом стала методика создан ия динамического отчета о работоспособ­ ности непосредственно из сигнального журнала. Команда EXTERNAL TABLE (которая подробно рассматривается в главах 10 и 1 5) позволяет запрашивать сигнальный журнал и просматривать сохраненную в нем ин­ формацию. Я обнаружил, что при каждом запуске базы данных в сигнальный жур­ нал вносилась пара записей: Thu Мау б 1 4 : 2 4 : 4 2 2 0 0 4 Starting ORACLE ins tance ( no rmal ) То есть всегда и меется зап ись метки времени в постоя нном формате с фикси­ рованной шириной и сообщение S t a r ing ORAC LE i n s t ance (Запуск экземпляра Файлы 1 69 ORACLE) . Кроме того, я обратил вни мание, что этим записям должно было пред­ шествовать сообщение ALT E R DATABA S E C L O S E (в случае чистого завершения ) , сообщение о б отмене остановки или вообще ничего - сообщения отсутствовал и , свидетельствуя об аварийном отказе системы . Н о любое сообщен и е должно было сопровождаться связанной с ним меткой време ни . Таким образом, до тех пор, пока не возник аварий н ый отказ системы, в сигнальный журнал должна была записы­ ваться какая-то значащая метка времени (в случае отказа системы метка времени должна была фиксироваться незадолго до аварии, т.к. запись в журнал производится довольно часто). Я заметил, что мог бы легко сгенерировать отчет о работоспособности , если бы: • собрал все записи вроде Staring ORACLE i n s t ance % ; • собрал все записи , которые соответствуют формату даты (фактически , пред­ ставляющие значен ия даты) ; • связал с каждой записью S t a r i ng ORACLE i n s tance две предшествующие ей записи (которые были бы записями с датой) . В при ведеи ном н иже коде создается внешняя таблица, позволяющая запраши­ вать сигнальный журнал. (Обратите внимание, что строка /bac kground/dump /de s t должна быть заменена реальным каталогом фонового дампа, а в операторе CREATE TABLE необходимо указать свое и мя сигнального журнала.) EODA@ORA12CR1> create o r replace 2 directory data_di r 3 as 4 ' /home / ora 1 2 c r 1 /app /ora 1 2 c r 1 /diag/ rdЬms /ora 1 2 c r 1 / o ra 1 2 cr 1 / t race / ' 5 1 Di rectory created . Ка талог создан . EODA@ ORA12CR1 > CREATE ТАВLЕ ale rt_l og 2 ( 3 text_l ine varcha r2 ( 4 0 0 0 ) 4 5 ORGAN I ZAT I ON EXTERNAL 6 ( 7 ТУРЕ ORACLE LOADER 8 DE FAULT DI RECTORY data di r 9 ACCESS PARAМETERS 10 ( 11 reco rds de l imited Ь у newline fields 12 13 LOCAT I ON 14 ( 15 16 ' a le rt_ora 1 2 cr 1 . l og ' 17 18 1 9 re j ect l imi t unl imi ted 20 1 ТаЬlе created . Таблица создана . 1 70 Глава 3 Теперь эту и нформацию можно запросить в любое время: EODA@ ORA 1 2 C R 1 > s e le ct to_cha r ( l a s t_time , 1 dd-mon- yyyy hh2 4 : mi 1 ) shutdown , 2 to_char ( s ta rt_time , 1 dd-mon-yyyy hh2 4 : mi 1 ) startup , 3 round ( ( s tart_time - l a s t_time ) * 2 4 * 60 , 2 ) mins_down , 4 round ( ( la s t_time - l ag ( s tart_time ) ove r ( o rder Ьу r ) ) , 2 ) days_up , 5 case when ( lead ( r ) over ( orde r Ьу r ) i s null ) 6 then round ( ( s ysdate - s ta rt_time ) , 2 ) 7 end days_s t i l l_up from ( 8 9 se lect r , to_date ( last_time , 1 Dy Mon D D HH2 4 : MI : S S УУУУ 1 ) l a s t_time , 10 to_date ( s tart_time , 1 Dy Mon DD HH2 4 : MI : SS УУУУ 1 ) s ta rt time 11 from ( 12 1 3 s e l ect r , 14 text l i n e , 15 lag ( text_l ine , 1 ) ove r ( o rder Ьу r ) sta rt_time , 16 lag ( text_l ine , 2 ) ove r ( o rder Ьу r ) l as t t ime from ( 17 1 8 s e l ect rownum r , text_l i ne 19 from a l e rt_log 2 0 where text l ine l i ke 1 - - - - - - 2 0 21 o r text l ine l i ke 1 Starting ORACLE instance % 1 ) 22 ) 23 2 4 whe re text l ine l i ke 1 S ta rting ORACLE ins tance % 1 25 26 1 S HUTDOWN STARTUP 2 8 - j un-2 0 1 3 1 7 : 02 2 9- j un-2 0 1 3 0 6 : 0 0 02-j ul-2 0 1 3 1 4 : 5 9 02-j ul-20 1 3 1 5 : 0 0 02-j ul-20 1 3 1 5 : 1 0 02-j ul-20 1 3 1 7 : 0 1 1 8 - j ul - 2 0 1 3 0 2 : 0 0 0 5- aug- 2 0 1 3 0 9 : 0 0 1 4 - aug-2 0 1 3 0 9 : 0 9 3 1 -aug- 2 0 1 3 1 4 : 0 8 0 2 - sep-2 0 1 3 1 4 : 3 2 0 2 - sep- 2 0 1 3 1 5 : 1 3 0 2 - sep-2 0 1 3 1 5 : 1 5 0 2 - sep- 2 0 1 3 1 6 : 5 3 0 2 - sep-2 0 1 3 1 6 : 5 6 2 8 - j un-2 0 1 3 1 6 : 0 4 2 8 - j un-2 0 1 3 1 7 : 0 2 0 1 -j u l - 2 0 1 3 0 9 : 4 2 0 2 - j u l -2 0 1 3 1 4 : 5 9 02-j ul-2 0 1 3 1 5 : 0 0 0 2 - j ul-2 0 1 3 1 5 : 1 0 02-j ul-2 0 1 3 1 7 : 02 1 8 - j ul - 2 0 1 3 1 1 : 3 1 0 6 -aug-2 0 1 3 0 9 : 0 6 1 4 -aug-2 0 1 3 0 9 : 5 8 0 2 - sep-2 0 1 3 1 0 : 5 1 0 2 - sep- 2 0 1 3 1 4 : 5 1 0 2 - s ep-2 0 1 3 1 5 : 1 3 0 2 - s ep-2 0 1 3 1 5 : 1 5 0 2 - sep-2 0 1 3 1 6 : 5 4 0 2 - sep-2 0 1 3 1 6 : 5 6 MINS DOWN DAYS UP . 03 3102 . 53 . 03 . 03 . 03 1 . 55 571 . 37 1 4 4 5 . 62 4 9 . 42 2683 . 15 18 . 93 . 03 . 05 . 03 . 03 . 04 . 54 1 . 22 DAYS-ST I LL-UP о . 01 . 08 1 5 . 37 17 . 9 8 17 . 17 . 15 . 02 о . 07 о . 07 1 6 rows s e lected . 1 б строк: выбрано . Я не стану здесь останавл иваться на нюансах SQ L-зaпpoca, а отмечу лишь, что сам ы й внутренний запрос (строки 1 8-2 1 ) собирает строки , содержащие " Starting " и дату ( вспомните, что использование подчерки вания (_) в конструкци и L I KE обеспе­ ч ивает сопоставление в точности с одни м символом - не больше и не меньше). Файлы 1 71 Запрос также нумерует строки с применением rownum. Н а следующем уровне запроса используется встроенная анал итическая функция LAG ( ) дЛя ухода на одну и на две строки дЛЯ каждой строки и сдвига соответствующих данных вверх, что­ бы третья строка запроса имела дан н ые строк l , 2 и 3. Строка 4 содержит данные строк 2 , 3 и 4 и т.д. В итоге м ы сохраняем только строки , которые был и подобны Starting ORACLE inst ance % и теперь имеют две предшествующих метки времен и , ассоциирован ные с н и м и . С этого места вычисление времени простоя базы данн ых не соста вляет труда: достаточно вычесть одно значен ие даты из другого. Вычисление времени работы экземпляра не намного сложнее: достаточно уйти на предьщущую строку, получить ее время запуска и вычесть это значение из значения времени ос­ тановки, относящегося к этой строке. Моя база данных Oracle l 2c начала свое существование 28 и юня 20 1 3 года и оста­ навливалась много раз (к моменту получения этого вывода она функционировала на протяжении 0,07 дня без перерыва) . Если вас интересует другой пример извлечения полезной информаци и из си г­ нального журнала, пройдите по ссьтке h t t p : 1 / t i n yu r l . c om / y 8 w k h j t . На этой стран ице при ведена демонстрация вычисления среднего време н и , необходимого для архивирования заданного оперативного журнального файла. Когда вы понима­ ете , что находится в сигнальном журнале, генерация подобных запросов становится простой . В дополнение к применению внешней таблицы для опроса сигнальных журналов в Oracle l 2c вы можете легко просматри вать их с помощью инструмента AD RCI . Он позволяет осуществлять поиск, редактирование (пересмотр) и мониторинг ( интер­ активное отображение новых зап исей по мере их появления в журнале) . К тому же сигнальный журнал в Oracle l lg и последующих выпусках доступен в двух верси ­ ях - в старой , которая только что использовалась, и в верси и XML: EODA@ORA1 2CR1 > column val ue new val V EODA@ ORA12CR1 > select val ue f rom v$diag info where nате = ' Diag Al e r t ' ; VALUE /home /ora l 2 cr l / app /ora l 2 c r l /diag / rdЬms /ora l 2 c r l /ora l 2 c r l / a l e rt EODA@ORA12CR1> ! l s &V/log . xrnl /home /ora l 2 c r l /app /ora l 2 c r l /diag / rdЬms /o ra l 2 cr l / o ra l 2 c r l / a l e r t / log . xrnl EODA@ORA1 2CR1 > ! head &V/log . xrnl <msg time= ' 2 0 1 3 - 0 6- 2 8 T l 6 : 0 4 : 2 5 . 37 8 - 0 4 : 0 0 ' org_id= ' oracle ' comp_id= ' rdЬms ' ms g_id= ' dЬkrlChe c kSuppressAl ert : 3 3 2 : 7 0 0 3 6 1 1 ' type= ' NOT I FI CAT I ON ' group= ' s tartup ' level= ' l б ' hos t id= ' localhos t . localdomain ' host addr= ' : : 1 ' pid= ' 3 2 62 8 ' ve rsion= ' l ' > <txt>Adj usting the de fault va lue o f parameter para l l el_max_s e rvers </txt> < /msg> <ms g time= ' 2 0 1 3 - 0 6-2 8 T l 6 : 0 4 : 2 5 . 37 8 - 0 4 : 0 0 ' org id= ' oracle ' comp id= ' rdЬms ' ms g_id= ' db krlCheckSuppre s sAlert : 3 32 : 2 0 0 0 7 7 8 7 7 2 ' type= ' NOT I FI CAT I ON ' group= ' s tartup ' level= ' l б ' host id= ' localhos t . localdomain ' host addr= ' : : l ' 1 72 Глава 3 Располагая утилитами либо и нструментами для генераци и отчетов из XM L (на­ пример, таким и как база данных Oracle , применяющая XDB - XM L DB), вы также можете запраши вать и строить отчеты в этом формате. Естествен но, диспетчер предприятия также отображает важную информацию из сигнального журнала. Ф айлы дан ных Файлы данн ых наряду с журнальными файлами повторения действий представ­ ляют собой наиболее важны й набор файлов в базе данных. Именно в этих файлах в конечном итоге будут храниться данные. Каждая база дан н ых имеет, по мен ьшей мере , оди н связанн ы й с нею файл данн ых , и обычно таких файлов будет значи­ тельно больше. Только самая простая "тестовая " база дан н ых будет содержать лишь оди н файл дан ных. Н а самом деле, как вы видели в главе 2 , даже простейшая ко­ манда CREAT E DATABAS E по умолчани ю создает базу данных с тремя файлами дан­ н ых, которые перечислен ы н иже: NАМЕ / home /ora 1 2 c r l /app / o ra 1 2 c r l /product / 1 2 . 1 . 0 /dЬhome_l / dЬs /dbs lora 1 2 c . dЬ f / home /ora 1 2 cr l /app / o ra 1 2 c r l /product / 1 2 . 1 . 0 /dЬhome_ l / dЬs /dbx lora 1 2 c . dЬ f / home /ora 1 2 cr l /app / o ra 1 2 c r l /product / 1 2 . 1 . 0 /dbhome_l /dЬs /dЬu lora 1 2 c . dЬ f Один файл данных предназначен для табличного пространства SYSTEM (которое вмещает настоящий словарь данных Oracle) , оди н для табличного пространства SYSAUX (где хранятся другие несловарные объекты в Oracle 1 0g и последующих вер­ с иях) и еще оди н - для табличного пространства U S E R (понятие табличного про­ странства будет раскрыто в разделе "Табличные пространства" далее в главе). Любая реальная база данных будет иметь, по крайней мере, эти три файла дан ных. П осле краткого обзора типов файловой системы мы обсудим организацию этих файлов в базе данных Oracle и орган изацию данных внутри них. Для пон иман ия этого вы должны знать, что собой представляют табличные пространства, сегмен­ ты , экстенты и блоки . Все они являются единицами распределения, которые Oracle использует для хранения объектов в базе дан ных, и вскоре они будут описаны более подробно. - Краткий обзор механизмов файловой системы Существуют четыре механизма файловой системы (в версии Oracle 1 2с их только три ) , с применением которых хранятся ваш и дан ные в среде Oracle . Под вашими данн ы м и понимается словарь данн ых, данные журнала, данные отката, таблицы, и ндексы, LОВ-объекты и т.д. - данные, о которых вам придется лично заботиться в конце дня . Н иже приведено краткое описание этих типов файлов. • " Готовые" файловые системы операционной системы (ОС). Это файлы, появ­ ляющиеся в файловой системе подобно документам текстовых процессоров. Их можно видеть в окне проводника Windows или в среде U N IX/Linux как ре­ зультат запуска команды l s . Для перемещения этих файлов с места на место можно использовать простые утилиты ОС, такие как хсору в Windows или ер в U N IX/Linux. Готовые файловые системы ОС исторически являются наиболее Файлы 1 73 популярным методом хранения дан ных в Oracle, но я вижу, что с появлен ием AS M (речь об этом пойдет ниже) ситуация меняется. Готовые файловые систе­ мы обычно буферизуются , т.е . ОС будет кеш ировать и нформацию при чте н и и и в ряде случаев п р и записи на диск. • Чистые (raw) разделы. Это не файлы - это диски без файловой системы. Их нельзя просматривать с помощью команды ls или проводни ка Windows. Он и представляют собой всего лишь большие области диска без какой-либо файло­ вой системы внутри. Для Oracle весь чистый раздел выглядит как оди ноч н ы й крупн ы й файл . Этим он отличается о т готовой файловой систе м ы , которая может содержать многие десятки или даже сотни файлов данных. В настоящее время чистые разделы применяются л и ш ь в н ебол ьшом проценте разверну­ тых баз данных Oracle из-за присущих им накладных расходов по адм и н ист­ рированию. Ч истые разделы не являются устройствами с буферизацией - все операции ввода-вы вода выполняются напрямую без какой-л ибо буферизаци и данных с участием ОС (что применительно к базе дан н ых в целом считается положительным качеством) . Н а заметку! В версии Oracle 1 1 g ч истые разделы были объявлены устарев ш и м и и в Oracle 1 2с они больше не поддерживаются . При наличии существующей базы данн ых, в которой используются чистые разделы , вам понадобится извлечь данные с помощью помпы дан­ ных или прибегнуть к услугам другого инструм ента репл и каци и , такого как Goldeп Gate, чтобы переместить свои данные в новую базу дан ных, в которой применяется одна из поддерживаемых файловых систем. В качестве альтернативы в существующую базу дан­ ных можно добавить новые пространства имен с поддерживаемой файловой систе мой и переместить в них нужные данные из чистых разделов . Такой подход работает, только если табличное пространство SYS TEM не является чистым разделом . • Автоматическое управление памятью (Automatic Storage Management - ASM). Это новая функциональная возможность Oracle I Og Release 1 (в обеих редак­ циях Standard и Enterprise). В выпусках, предшествующих Oracle I lg Release 2, ASM представляет собой файловую систему, предназначенную для использова­ ния исключительно базой данн ых. Проще всего думать о ней как о файловой системе базы данных. В этой файловой системе вы не будете хранить, скажем, текстовый файл со списком покупок, а только и нформацию, связанную с ба­ зой данных: таблицы, и ндексы, резервные копи и , управляющие файлы, файлы параметров, журнальные файл ы , архивы и т.д. Н о даже в AS M существует эк­ вивалент файла данн ых; кон це птуально данные по-прежнему хранятся в фай­ лах, но файловой системой является AS M . Система ASM рассчитана на работу либо на отдельном ком пьютере, л ибо в кластеризованной среде . Н ач и н ая с Oracle l lg Release 2, AS M предоставляет не только файловую систему для базы дан н ых, но также дополнительно кластеризованную файловую систему, опи­ санную н иже . • Кластеризованная файловая система. Эта файловая система предназначе­ на специально для (кластеризованной) среды RAC и предлагает то, что вы ­ глядит подобно готовой файловой системе, которая совместно используется многими узлам и (компьютерами) в кластеризованной среде . Таким образом, 1 74 Гл ава 3 хотя и можно было бы смонтировать устройство N FS или создать общи й ре­ сурс Samba (метод совместного использования дисков в среде WindowsjUN IX/ Linux, похожий н а N FS ) для готовой файловой систем ы с целью доступа из множества узлов кластера, это породило бы оди ночную точку отказа. Если узел , который владеет файловой системой и обеспечивает совместную работу с ней, откажет, то файловая система станет недоступной. В версиях Oracle, пред­ шествующих l lg Release 2, в этой области предлагалась кластерная файловая система Oracle (Oracle Cluster File System - OCFS), которая в настоящее время доступна только для Windows и U N IX/Linux. Другие поставщики предлагают сертифицированные кластеризованные файловые системы, также работающие с Oracle . В версии O racle l l g Release 2 предоставляется еще оди н вариант в форме кластерной файловой систем ы для автоматического управления памя­ тью Oracle (Oracle Automatic Storage Management Cluster File System - AC FS). Кластеризованная файловая система привносит комфорт готовой файловой системы в кластеризованную среду. И нтересно отметить, что база данн ых может включать файлы из любой или всех описанных выше файловых систем - вовсе не обязательно выбирать какую-то одну. Вполне может существовать база данных, внутри которой часть данных хранится в традиционных готовых файловых системах, часть - в чистых разделах, часть - в ASM и часть - в кластеризован ной файловой системе. Такой подход облегчает пе­ реход с одной технологии на другую или дает представление о возможностях нового ти па файловой системы без переноса туда всей базы дан ных. А теперь, поскольку подробное обсуждение файловых систем и всех их характеристик выходит за рамки настоящей книги , мы возвращаемся к типам файлов Oracle. Независимо от того, где хранится файл - в готовой файловой системе, в чистом разделе, в системе AS M или в кластеризованной файловой системе , - описанные н иже кон цепции всегда будут применимы к нему. Иерархия хранения в базе данных Oracle База дан ных состоит из одного или более табличных пространств (taЬlespace) . Табличное пространство - это логически й контейнер хранения в Oracle , который находится н а верхушке иерархии хранения и образован из одного или нескол ьких файлов данных. Файлы могут быть готовыми файлами файловой системы, чистыми разделами , файлами базы дан ных, управляемой посредством AS M , или файлами в кластеризованной файловой системе. Табличное пространство содержит сегменты , описанн ые в следующем разделе. Сегменты Сегменты (segment) представляют собой основную организационную структуру внутри табличного пространства. Сегменты - это просто объекты базы данных, ко­ торые потребляют хранилище, т.е . объекты наподобие таблиц, и ндексов, сегментов отката и т.д. При создании секционированной таблицы мы создаем не оди н сегмент для всей таблицы, а по сегменту на секцию. При создании индекса обычно создает­ ся сегмент и ндекса и т.д. Каждый объект, занимающий место в хранилище, в итоге сохраняется в оди ночном сегменте. Существуют сегменты отката, временные сег­ менты , сегменты кластеров, сегменты индексов и прочие. Файл ы 1 75 На заметку! Утверждение о том , что каждый объект, занимающий место в хранил и ще, в ито­ ге сохраняется в оди ночном сегменте , может сби вать с толку. Вы встретите м ногоч ис­ ленные операторы CREAT E , которые создают многосегментные объекты . Путаница воз­ ни кает вследствие того факта, что отдельный оператор C REATE может, в конечном счете , создавать объекты , состоящие из нуля, одного или большего ч исла сегментов! Например, оператор CREATE TABLE т ( х i nt p r ima r y key , у c l ob ) создаст четыре сегмента: один для таблицы т, оди н для и ндекса, который будет создан для поддержки первичного кл юча, и два для объекта C LOB (один сегмент для и ндекса LOB и оди н для самих дан ­ ных LOB ) . С другой сторон ы , оператор CREAT E TABLE т ( х i n t , у date ) c l u s t e r М У_ CLUSTER создаст ноль сегментов ( в этом случае сегментом я вляется класте р ) . М ы допол нительно исследуем эту концепцию в главе 1 0. Экстенты Се гменты состоят из одного или более экстентов (exte nt) . Экстент - это ло­ гически непрерывное распределение пространства в файле. ( В общем случае сам и файлы не зан имают непрерывное место на диске , иначе нам н икогда не пришлось бы пользоваться инструментом дефрагментации дисков. Кроме того, в случае при­ менения таких дисковых технологи й , как RAI D ( Redundant Array of I n dependent Disks - избыточ ный масси в независимых дисков) , отдельны й файл может распро­ страняться на несколько физических дисков. ) П о традиции каждый сегмент нач ина­ ется, по крайней мере , с одного экстента. В версии Oracle l lg Release 2 была введена концепция "отложен ного" (deferred) сегмента - сегмента, которы й не распределяет экстент немедленно, так что в этой и последующих версиях СУБД сегмент может отложить выделение своего начального экстента до момента вставки в него дан н ых. Когда объект вырастает до размеров, выходящих за пределы начального экстента, он запраш ивает распределение следующего экстента. Этот второй экстент не обяза­ тел ьно будет расположен на диске по соседству с первым - он может даже не по­ пасть в тот же файл, где находится первый экстент. Второй экстент может распола­ гаться очень далеко от первого, но пространство внутри экстента всегда считается логически непрерывным в файле. Размеры экстентов варьируются от одного блока данных Oracle (рассматривается следующим) до 2 Гбайт. Блоки Экстенты, в свою очередь, состоят из блоков (Ьlock) . Блок представляет собой на­ имен ьшую еди ницу распределения пространства в Oracle. И менно в блоках хранятся строки данных, зап иси индексов или временные результаты сортировки . Блок - это то, что Oracle обычно считывает с диска или записывает на диск. Как правило, бло­ ки в Oracle и меют оди н из четырех общих размеров: 2 Кбайт, 4 Кбайт, 8 Кбайт или 1 6 Кбайт (хотя в некоторых случаях допускается также размер 32 Кбайт; ограниче­ ния на максимальный размер блоков накладываются операционной системой) . Н а заметку! Есть оди н малоизвестный факт: стандартны й размер блока для базы данных н е обязательно должен быть степенью двой ки . Степени двойки - всего л и ш ь общепринятое соглашение. На самом деле можно создать базу данн ых с размером блока 5 Кбайт, 7 Кбайт или n Кбайт, где n - любое значение из диапазона 2-32 Кбайт. Однако я не рекомендую поступать так в реальных базах данных - придерживайтесь обычных размеров блоков. Использование нестандартных размеров блоков может легко превратиться в nроблему nри поддержке - если только лично вы п р и меняете размер блока 5 Кбайт, то можете столк­ нуться со сложностям и , которые другие пользователи просто н икогда не увидят. 1 76 Глава 3 Взаимосвязь между сегментами , экстентами и блоками демонстри руется на рис. 3 . 1 . 1 С егмент 1 \J ' 2 Э кстент 1 Мбайт М байт t\ т 1 1 Э кстент ' ' ' 1 Мбайт 1 1 1 1 ' .. ' .. ' .. .. .. .. .. .. .. 8 Кбайт 8 Кбайт ВJ<бай � Кбайт \ 8 Кбайт 8 Кбайт 8 Kб3ijJ"[8 Кбайт Бло ки \ 8 Кбайт 8 Кбайт 8 Кбайт!В.t<байт данных 8 Кбайт 8 Кбайт 8 Кбайт 8 Кб� Рис. 3 . 1 . Сегменты , экстенты и блоки Сегмент образован из одного или более экстентов, а экстент - это непрерывная область блока. Н ач иная с версии Oracle9i Release 1 , база дан ных может содержать блоки до шести разных размеров. На заметку! Подцержка нескольких размеров блоков была в ведена для того, чтобы nере­ носи мые табличные пространства можно было использовать в большем ч исле ситуаци й . Возможность переноса табличного пространства позволяет администратору базы данных перемещать или коп и ровать уже сформатированные файлы данных из одной базы данных и п рисоединять их к другой - нап ример, чтобы немедленно скоnировать все таблицы и и ндексы из базы данных OLTP ( O n l i ne Transaction Processing - оnеративная обработка транзакций ) в базу данных DW ( Data Warehouse - и нформационное хранилище ) . Однако во м ногих случаях в базе данных O LTP могут nрименяться блоки небольшого размера ( 2 Кбайт и л и 4 Кбайт) , тогда как в базе данных DW будут исnользоваться блоки знач ительно большего размера (8 Кбайт или 1 6 Кбайт). Без поддержки нескольких размеров блоков в одной базе данных nеренос такой и нформаци и оказался бы невозможн ы м . Табличные n ространства с нескольким и размерами блоков должны nрименяться для содействия nе­ реносу табличных nространств ; обычно они не используются для чего-то другого. Для базы дан ных будет определен стандартный размер блока, представля ющий собой размер, который указан в файле и нициализации , задействован ном при вы­ полнении команды CREAT E DATABAS E . Табличное пространство SYSTEM всегда бу­ дет использовать стандартны й размер блока, но вы можете создать другие таблич­ ные пространства с нестандартны м и размерами блоков 2 Кбайт, 4 Кбайт, 8 Кбайт, 1 6 Кбайт и 32 Кбайт (в зависимости от операционной системы). Общее количество размеров блоков равно шести , есл и и только если во время создания базы данных был указан нестандартны й размер блока (не степень двойки ) . Следовательно, фак­ тически база данных будет иметь максимум пять размеров блоков: один стандарт­ ный и четыре нестандартных размера. Каждое табличное п ространство будет обладать согласован ным размером бло­ ка, т.е . все блоки в этом табличном пространстве будут иметь один и тот же размер. В м ногосегментном объекте, таком как таблица со столбцом LO B, каждый сегмент в табличном пространстве может и меть отличающийся размер блока, но любой отде- Файл ы 1 77 льно взяты й сегмент (который содержится в табличном nространстве) будет состо­ ять из блоков в точности одинаковых размеров. Больш инство блоков, независимо от их размеров, имеют оди н и тот же общий формат, которы й выглядит подобн о показанному на рис. 3 . 2 . Р и с . 3 . 2 . Структура блока Исключениями из этого формата я вляются блоки сегментов LO B и блоки гиб­ ридных сжатых столбцов в хран ил и ще Exadata, например, но подавляющее боль­ шинство блоков в базе данных будут и меть формат, сходный с nредставленным на рис. 3 .2. Заголовок блока содержит информацию о типе блока (блок таблицы, блок индекса и т.д . ) , и нформаци ю об активных и nрошедших транзакциях (эту инфор­ мацию имеют только блоки , управляемые транзакциями - скажем , во временном блоке сортировки она отсутствует) и адрес (местоположение) блока на диске . Следующие два компонента блока встречаются в н аиболее расnространенных типах блоков базы данных - блокам традиционных (heap-organized) таблиц. Ти п ы таблиц баз данных подробно рассматриваются в главе 1 0 , а пока достаточно знать, что к этому типу относится большинство таблиц. Сnисок указателей таблиц, если присутствует, содержит информацию о табли цах, хранящих строки в этом блоке (в одном блоке могут храниться данные из более чем одной таблицы). Список указателей строк содержит информацию, которая описыва­ ет строки , находящиеся в блоке . Он представляет собой массив указателей на места, где расположен ы строки в части данных блока. Эти три компонента блока вместе называются дополнительной памятью блока, являющейся nространством блока, ко­ торое не доступно для размещения данн ых, но используется Oracle для управления самим блоком. Оставшиеся два фрагмента блока просты : в блоке может присутствовать свобод­ ное пространство, и обычно в нем будет находиться область, где в текущи й момент хранятся данные. Теперь, когда вы в общих чертах ознакомились с сегментами , которые состоят из экстентов, в свою очередь состоящих из блоков, давайте подробнее рассмотрим таб­ личные пространства и то, каким образом файлы вписываются в общую картину. Табличные пространства Как отмечалось ранее, табличное пространство представляет собой контейнер оно хранит сегменты . Каждый сегмент nринадлежит только одному табличному про­ странству. Табличное nространство может содержать внутри себя множество сегмен­ тов. Все экстенты отдельного сегмента будут находиться в табличном nространстве, которое связано с этим сегментом . Сегменты никогда не пересекают границы таб- 1 78 Глава 3 личных n ространств. Само табл ичное nространство связано с одн им ил и большим числом файлов данных. Экстент для любого заданного сегмента в табличном nро­ странстве будет nолностью содержаться внутри одного файла данных. Тем не менее, сегмент может и меть экстенты из множества разных файлов данных. Графически табличное nространство может выглядеть так, как показано на рис. 3 . 3 . Табличное п ространство USER_DATA jdo 1 juser_data0 1 .dbl ,....- � - """ T2 I T2 I T2 1 1 1 1 1 Т 1 Т 1 Т 1 Т 1 T1 I T1 I Т1 11 J 11 J 11 J 11 / do1 juser data02.dbl i'-- Ри с . 3 . 3 . Табличное п ространство , содержащее два файла данных, три сегмента и четыре экстента На рис. 3 . 3 изображено табличное nространство USER_ DATA. Оно состоит из двух файлов данных - u s e r_da t a O l . с!Ь f и u s e r_da t a 0 2 . с!Ь f . Для него выделено три сегмента: T l , Т 2 и I 1 (вероятно, две таблицы и и ндекс ) . В таблич ном пространс­ тве расnределены четыре экстента, каждый из которых представлен как логически неnрерывный н абор блоков базы данных. Сегмент т 1 содержит два экстента - по одному в каждом файле. Как показано, сегменты Т 2 и I 1 имеют по одному экстен­ ту. Если этому табличному nространству понадобится доnолнительное место, можно л ибо измен ить размеры уже расnределенных для него файлов данных, либо доба­ вить к нему третий файл данных. Табличное nространство - логически й контей нер для хранения данных в Oracle . Как разработчи ки , м ы будем создавать в табличных nространствах сегменты . Нам н икогда не придется опускаться до уровня файлов - мы не указываем, что хотим, чтобы наши экстенты бъш и распределены в конкретном файле (делать это можно, но обычно так не поступают) . Взамен мы создаем в табличных пространствах объек­ ты, а Oracle заботится обо всем остальном . Если когда-либо в будущем администра­ тор базы дан ных решит переместитъ файлы на диске для обеспечения более равно­ мерного распределения оnераци й ввода-вывода, это нас вполне устроит. Оно никак не скажется на обработке данн ых. Резюме по иерархии хранения В качестве резюме по иерархи и хранения в Oracle можно при вести следующие утверждения . 1 . База данных состоит и з одного или большего ч исла табличных nространств. 2. Табличное пространство образовано одним или несколькими файлами дан ных. Эти файлы могут быть готовыми файлами в файловой системе, чистыми раз­ делами , файлами базы данных, управляемой AS M , ил и файлами в кластеризо­ ванной файловой системе. Табличное пространство содержит сегменты . 3 . Сегмент ( TAB L E , I N DEX и т.д.) формируется одним или большим количеством экстентов. Сегмент существует в табличном nространстве , но его данные могут располагаться во многих файлах данных внутри этого таблич ного пространства. Файл ы 1 79 4. Экстент - логически непрерывный набор блоков на диске. Экстент находит­ ся в одном табличном пространстве и, более того, всегда в единственном фай ­ ле внутри этого табличного пространства. 5. Блок - это наимен ьшая еди н и ца распределения пространства в базе данных. Блок я вляется наимен ьшим элементом ввода-вы вода, испол ьзуе м ы м базой данных при взаимодействии с файлами данн ых. Табличные пространства , управляемые словарем и управляемые локально Прежде чем двигаться дальше, давайте рассмотрим еще одну тему, связан ную с табличными пространствами: управле ние экстентами в табличном пространстве . До выхода верси и Oracle 8 . 1 . 5 существовал только один метод управления выделе­ нием экстентов внутри табл ичного пространства: табличное пространство, управ­ ляемое словарем данных (dictionary- managed taЬiespace). То есть управлен и е п амя­ тью внутри табличного пространства производилось в табли цах словаря данн ых, во многом подобно управлени ю дан н ы м и бухгалтерского учета, возможно, с участием табли ц DEВ I T (дебет) и CRE D I T (кредит) . На стороне дебета представлены все экс­ тенты, вьщеленные объектам. На стороне кредита имеются все свободные экстенты, доступ ные для использования . Когда объект нуждается в е ще одном экстенте , он должен запросить его у системы. Затем Oracle обратится к своим табли цам словаря данных, выпол н ит ряд запросов, найдет свободное пространство (или н ет) , после чего обновит строку в одной из табли ц (или удалит ее) и вставит строку в другую таблицу. СУБД Oracle управляет пространством хранения оче н ь похоже на то, как мы поступаем в своих приложен иях: изменяя и перемещая данные. Этот SQ L-зaпpoc, выполняемый от нашего имени в фоновом режиме для по­ лучен ия допол н ител ьного пространства, называют рекурс и в н ы м SQ L-запросом . Наш SQL-oпepaтop I N S E RT вызывает выполнение е ще одного рекурси вного S Q L­ oпepaтopa для получения дополнительного места. Ч астое выполнение этого рекур­ сивного SQL-зaпpoca может обходиться достаточно дорого с точки зрен ия ресурсов. Такие обновления словаря данных должны быть сериализированы ; они не могут де­ латься одновремен но. Это то, чего следует избегать. В ранних версиях Oracle с упомянутой проблемой управления пространством накладные расходы в виде рекурсивного SQL-зaпpoca - мы сталкивались наиболее часто при работе с време н н ы м и табличными пространствами (это было до появ­ ления "подлинных" времен н ых табличных пространств, создаваемых посредством команды CREAT E T EMPORARY TABLES PACE ) . П ространство должно было регулярно распределяться (приходилось удалять данные из одной табл и ц ы словаря и встав­ лять их в другую) и освобождаться (только что перемещенные строки приходилось помещать обратно туда, где они располагал ись первоначально) . Как п равило, эти операции должн ы были выполняться последовательно, что вело к резкому сниже ­ н и ю степени параллелизма и увеличению времени ожидания. В верси и Oracle 7 . 3 (давным-давно, еще в 1 996 году) была введен а кон цеп ция подл и н ного временно­ го табличного пространства - нового типа табличного пространства, вьщеленного специал ьно для хране н ия временн ых дан ных и призванного смя гчить описанную проблему. 1 80 Глава 3 До поя вления этого типа табличного пространства временные данн ые управля­ лись в тех же самых табличных пространствах, что и постоя нные данные и тракто­ вались во многом так же, как постоянные данные. Во временном табличном пространстве нельзя было создавать собственные пос­ тоя н н ые объекты . По существу это было единствен н ы м отличием; пространство хранения по-прежнему управлялось посредством таблиц словаря данных. Тем не ме­ нее, как тол ько экстент распределялея во времен ном табличном пространстве, сис­ тема должна была удерживать его (т.е. не возвращать пространство обратно). Когда в следующий раз кто-то запраши вал выделение части времен ного табличного про­ странства для любых целей , СУБД Oracle должна была искать уже выделенный эк­ стент в своем внутреннем списке распределенных экстентов. При обнаружении та­ кого экстента она должна была просто использовать его повторно или же выделить его стары м способом. В результате после запуска базы данных и ее работы в течение определенного периода време н н ы й сегмент выглядел бы полным, хотя в действи­ тельности он бьm бы всего лишь "распределенным". Свободные экстенты имелись в налич и и ; они просто управлялись по-другому. Когда кто-то нуждался во временном пространстве , СУБД Oracle должна бьmа искать это пространство в структуре дан­ ных, расположенной в памяти , а не выполнять затратный в плане ресурсов рекур­ сивный SQL-зaпpoc. В Oracle 8 . 1 . 5 и последующих версиях бьm совершен следующий шаг в направ­ лен и и сокращен ия накладных расходов, связанных с управлением пространством . Бьmа введена кон цепция лакальна управляемых табличных пространств как проти ­ воположность табличным пространствам, управляемым словарем . Локальное управ­ ление пространством фактически позволило делать для всех табличных пространств то, что в Oracle 7 . 3 делалось для времен н ых табличных пространств: оно устранило необходимость применеимя словаря данных для управления памятью в табличном пространстве . В лакальна управляемых табличных пространствах для управления экстентами используется битовая карта (Ьitmap) , хранящаяся в каждом файле данных. Для по­ лучения экстента системе достаточно лишь установить в 1 бит в битавой карте. Для освобождения пространства система устанавли вает бит в О. П о сравнению с приме­ нением табличных пространств, управляемых словарем, это происходит невероятно быстро. Больше не нужно сериализировать длительно выполняющиеся операци и на уровне базы дан ных для запросов памяти по всем табличным пространствам. Вместо этого последовательность выполнения обеспечивается на уровне табличного про­ странства, что гарантирует очен ь быструю работу. Лакальна управляемые табличные пространства обладают и другими замечательными характеристиками , таким и как принудительное использование унифицированного размера экстента, но это уже от­ носится к ком петенции адми н истратора базы данных. Забегая наперед, следует отметить, что единственным методом управлен ия про­ странством хране н ия , которы й вы должн ы применять, является лакальна управ­ ляемое табл ич ное пространство. На самом деле в Oracle9i и последующих версиях при создании базы дан н ых с использованием утилиты D BCA ( Database Configuration Assistant - помощник по конфи гурированию сервера баз данных) табличное nро­ странство S YS T EM будет создано как лакальна управляемое , а если это так, то все остальные табличные пространства в базе данных также будут управляться локально, Файл ы 181 и унаследованный метод управления посредством словаря работать н е будет. Это не означает, что табличные пространства, управляемые словарем , не поддерживаются в базе данных, в которой табл ичное п ространство SYSTEM управляется локально - их просто невозможно создать: EODA@ORA12CR1 > create taЬl espace dmt 2 data f i l e ' / tmp /dmt . dЬ f ' s i ze 2m 3 extent management dict iona r y ; create taЬlespace dmt * ERROR at l i ne 1 : ORA- 1 2 9 1 3 : Cannot create dictionary managed taЬlespace ОПМБКА в строке 1 : ORA- 1 2 9 1 3 : невозможно создать табличное пространство , управляемое словарем EODA@ORA1 2 CR1> ! oe r r ora 1 2 9 1 3 1 2 9 1 3 , 0 0 0 0 0 , " Cannot create dictionary managed taЬle space " 1 1 * Cause : At temp to create dictionary managed taЬlespace in database which has system taЬle space as local ly managed 11 11 *Action : Create а loca l l y managed taЬlespace . 1291 3 , 0 0 0 0 0 , "Невозможно создать та бличное пространство, управляемое словарем" / 1 *Причина : попытка создания табличного пространства , управляемого словарем, в базе данных с лакальна управляемьм табличньм пространством SYSTEM 11 / 1 *Действие : создайте лакаль на управляемое табличное пространство . Обратите внимание, что o e r r - это утилита, доступная только в U N IX/Linux; на других платформах за описанием полученной ошибки необходимо обращаться в руководство Orac/e Database Error Messages (Сообщен ия об ошибках базы данн ых Oracle). На заметку! Вас может заинтересовать, по какой причине я утверждаю : "Это не означает, что табл ичные пространства, управляемые словаре м , не подцерживаются в базе данных, в которой табличное пространство S Y S TEM управляется лакальна - их просто невозможно создать" . Если их нельзя создать, то почему нам может пенадобиться их подцержи вать? Ответ кроется в средстве переносимых табличных п ространств. Вы можете переносить табл ич ное пространство, управляемое словарем , в базу данных с табличным п ространс­ твом SYS TEM, которое управляется локально. Вы можете подключ ить это таблич ное про­ странство и и меть в своей базе данн ых таблич ное пространство, управляемое с помощью словаря , но вы не можете создать его с нуля в этой базе данных. Невозможность создания табличных пространств, управляемых словарем, я вля­ ется положительн ым побоч ным эффектом, т. к. запрещает пользоваться унаследо­ ванным механизмом хранения, которы й был менее эффективным и опасно пред­ расположенным к фрагментации пространства. Локально управляемые табличные пространства, вдобавок к более высокой эффективности в плане выделения и ос­ вобождения пространства, также п редотвращают фрагментаци ю табличного про­ странства. Мы рассмотрим их детально в главе 1 0. 1 82 Глава 3 Вр еме н ные ф айлы Време н ные файлы данных (или просто временные файл ы) в Oracle представля­ ют собой специальный ти п файла дан ных. Они применяются Д)]Я хранения проме­ жуточ ных результатов масштабных операций сортировки и хеширования , а также Д)]Я хранения данных глобальной времен ной табли цы или результирующего н або­ ра, когда объем а ОЗУ для этого оказы вается недостаточно. В Oracle 1 2с и после­ дующих версиях времен н ые табличные п ространства также могут хранить дан ные UNDO, сгенерированные операциями, которые вы полня ются в глобальных времен­ ных табл и цах. В ранн их выпус ках такие дан н ые направлялись в таблич ное про­ странство U N D O , поэтому приводили к генераци и данных REDO; теперь это боль­ ше не происходит. Во временные файлы н икогда не попадут постоянные объекты дан ных, такие как табл и ца или и нде кс , а тол ько содержимое временных таблиц вместе с их и ндексами . Таки м образом , вы н и когда не будете создавать во вре­ мен ном файле табл и цы своего приложения, но можете хранить в нем дан ные при использовании временных табли ц . Временные файлы в Oracle трактуются специальным образом . Обыч но каждое изменение, вносимое в объект, будет записываться в журналы повторения. П озже эти журнал ы транзакций можно воспроизводить для " повторения транзакции", на­ пример, во время восстановления после сбоя . Временные файлы из этого процесса исключен ы . В частности, для транзакций во времен н ых табли цах (расположенных во временных файлах) дан ные REDO н икогда не генерируются , хотя они могут иметь сгенерированные дан н ые UNDO. Следовательно, могут существовать сгенерирован­ ные данные REDO, работающие с временными табл и цам и , т. к. данные UNDO всегда защищены данными REDO, как будет показано в главе 9. Данные UNDO, сгенериро­ ванные Д)]Я глобальных времен н ых таблиц, предназначен ы для поддержки отката работы , выполненной в текущем сеансе , л ибо из-за ошибочной обработки дан ных, л ибо вследствие какого-то общего отказа транзакции . У администратора базы дан­ ных н икогда не возникает потребность в резервном коп ировании временного файла данных; фактически такая попытка была бы напрасной тратой времени, поскольку восстановление временного файла дан н ых совершенно невозможно. На заметку! В Oracle 1 2с и последующих версиях данные UNDO, сгенерированные для гло­ бальных временных таблиц, могут быть сохранены во временном табличном пространстве. По умолчанию данные UNDO будут генерироваться в постоянном табличном пространстве UNDO, как это было в n редыдущих выпусках. Чтобы разрешить сохранение данных UNDO, сгенер и рованных для глобальных временных таблиц, во временном файле , можно ус­ тановить в T RU E настрой ку i n i t . o r a уровня системы или устанавливаемый параметр ТЕМР_ UNDO_ ENABLED уровня сеанса. В таком случае для этих операций данные RE DO ге­ нерироваться не будут. Мы возврати мся к этой теме в главе 9 . Рекомендуется сконфигурировать базу данных на применение локально управ­ ляемых временных табл и ч н ых пространств. Необходимо гарантировать использо­ ван и е адми н истратором базы дан ных команды CREAT E T E M PORARY TAB L E S PAC E . Совершенно нежелательно просто замен ить постоянное табличное пространство временным, т.к. при этом невозможно получить все преимущества, связанные с вре­ менными файлам и . Файл ы 1 83 Одна из особенностей подлинных временных файлов заключается в том , что если операционная система разрешает это, то временные файлы будут создаваться разре­ женными - т.е. в действительности они не будут потреблять дисковое пространство до тех пор, пока в этом не возникнет необходимость. В этом легко убедиться с по­ мощью следующего примера (в Oracle Linux) : EODA@ORA12CR1> ! df -h / tmp S i ze Used Avai l U s e % Mounted on Fi lesys tem /dev/mappe r /Vo lGroup - lv_root 50G 6 . 5G 4 1 G 1 4 % / EODA@ORA12CR 1 > create temporary t aЫespace temp_huge 2 temp f i l e ' / tmp / temp_huge . dЬ f ' s i ze 2 g ; TaЬlespace created . Та бличное пространство создано . EODA@ORA12CR1> ! df -h / tmp S i ze Used Avai l U s e % Mounted on Filesys tem /dev/mapper /VolGroup- lv_root 50G б . 5G 4 1 G 1 4 % 1 EODA@ORA12CR1> ! l s - 1 / tmp / temp_huge . dЬ f - rw- rw- - - - . 1 ora 1 2 c r 1 ora 1 2 c r 1 2 1 4 7 4 9 1 8 4 0 S e p 3 1 3 : 2 8 / tmp / temp_huge . dЬ f Н а заметку! Команда U N IX/Lin ux под названием d f показы вает свободное пространство на диске (от "disk free " ) . В ее выводе видно, что перед добавлением в базу данных времен­ ного файла размером 2 Гбайт в файловой системе, содержащей / t emp , было свободно 41 Гбайт. После добавления временного файла объем свободного дискового п ространс­ тва файловой системы по-прежнему остался равны м 41 Гбайт. Как видите, для этого файла не поиадабилось м ного места. Если м ы взглянем на вывод l s , то увидим нормальны й файл размером 2 Гбайт, но фактически в теку­ щий момент он потребляет всего несколько килобайт дискового пространства. Так что на самом деле мы могли бы создать сотни таких временных файлов по 2 Гбайт, несмотря на то, что на диске свободно примерно 4 1 Гбайт. Звучит неплохо - бес­ платное хранилище для всех! Однако проблема в том , что как только мы приступи м к использованию этих временных файлов, и о н и начнут увеличиваться в размерах, то очень скоро мы получи м сообщен ие об ошибке типа " свободного места больше нет" . Поскольку пространство выделяется или физически назначается файлу опера­ ционной системой по мере необходимости , есть реальный шанс нехватки свободно­ го места (особенно если после создан ия времен н ых файлов кто-то другой заполнит файловую систему своими данными). Способ решения такой проблемы варьируется в зависимости от операционной системы. В среде U N IX/Linux для этого можно выдать команду dd, запол н и в файл данными, что вынудит ОС физически назначить файлу дисковое пространство, или применить команду ер, чтобы создать неразреженный файл, например: EODA@ORA12CR1> ! ер - - spars e=neve r /tmp / temp_huge . dЬ f / tmp / temp_huge_not_sparse . dЬ f EODA@ORA12CR1> ! df -h / tmp S i ze Used Avai l U s e % Mounted on Fi lesys tem /dev/mappe r /VolGroup-lv_root 50G 8 . 5G 39G 1 9 % 1 1 84 Глава 3 EODA@ORA12CR1> drop taЬlespace temp_huge including contents and data files ; TaЬlespace dropped . Та бличное пространство удалено . EODA@ORA 1 2 CR 1 > create temporary taЬlespace temp_huge 2 temp f i l e ' /tmp /temp_huge_not_spar s e . dЬ f ' reus e ; TaЬlespace created . П осле копирования разреженного файла размером 2 Гбайт в 1tmp 1t emp_huge _ not_ s pa r s e . d.Ь f и создания с помощью опции REUSE временного табличного про­ странства, использующего этот временн ы й файл , мы гарантируем, что временному файлу выделено все нужное ему пространство файловой системы, а база дан ных действительно и меет 2 Гбайт времен ного пространства для работы с ним. На заметку! Согласно моему оnыту, файловая система NTFS в Windows не создает разре­ женные файл ы , и это nрименимо к разновидностям U N IX/Linux. В качестве nоложительной сторон ы , если вы должны создать временное табличное nространство размером 1 5 Гбайт в системе U N IX/Linux и расnолагаете nоддержкой временных файлов , то обнаружите , что это nроисходит очень быстро ( мгновенно); просто удостоверьтесь в наличии 1 5 Гбайт сво­ бодного n ространства и держите их в уме . У правля ю щ ие ф айлы Управляющие файл ы - это довольно небольш ие файл ы (в предел ьных случаях они могут вырастать до 64 Мбайт) , которые содержат каталог других файлов, необ­ ходимых Oracle. Файл параметров сообщает экземпляру, где находятся управляющие файл ы , а управляющие файлы указывают экземпляру местоположения файлов базы данных и оперативных журналов повторен ия транзакций. Управляющие файлы также сообщают Oracle другие сведения , такие как инфор­ мация об имеющихся контрольных точках, имя базы данных (которое должно соот­ ветствовать указанному в параметре dЬ_name внутри файла параметров), метка вре­ мени создания базы данных, хронология архивного журнала повторения транзакций (в некоторых случаях это может при водить к получению управляющего файла боль­ шого размера) , информация RМAN и т.д. Управл я ю щ и е файлы должны мул ьти плексиро ваться л ибо оборудован ием ( RAI D) , либо самой базой данных Oracle, когда поддержка RAI D или зеркального отображен ия недоступна. Для каждого управля ющего файла должно существовать более одной коп и и , которые во избежание их утери в случае отказа диска должны храниться на разных дисках. Утеря управляющего файла не является фатальной она лишь значительно затрудняет процесс восстановления. Скорее всего, разработчи ку н и когда не придется иметь дело с управля ющими файлами. Для адми нистратора базы данных они являются важной частью базы дан­ ных, но для разработчи ка приложений они не представляют особого и нтереса. Ф айлы жу рналов повторе н ия тра н з акций Файлы журналов повторен ия транзакций критически важны для базы дан ных Oracle. Они представляют собой журналы транзакци й для базы данных. В основном Файл ы 1 85 эти файлы используются только при восстановлен и и , но могут также применяться в перечислен ных ниже ситуациях: • восстановление экземпляра после аварийного отказа системы; • восстановление носителей и нформации после восстановления файла дан н ых из резервной копи и ; • обслуживание резервной базы данных; • подключение к Streams, или процессам извлечения и нформации из журналов повторения транзакций Golden Gate для совместного использования инфор­ мации (это всего лишь необычное название репл и каци и ) ; • предоставление администраторам возможности инспектирования транзакци й хронологической базы данных посредством утилиты Oracle LogMiner. Главным предназначением этих файлов я вляется их применение в случае отка­ за экзем пляра или носителя либо в качестве метода поддержан ия резервной базы данных для обхода отказа. Если на компьютере базы данных откл юч илось элект­ ропитание, в результате чего произошел сбой в работе экземпляра, то Oracle будет использовать оперативные журналы повторения для восстановления системы в со­ стоянии, которое непосредственно предшествовало моменту исчезновения п итания. Если диск, содержащий файлы данных, серьезно пострадал , то для восстановления резервной копи и этого диска на соответствующий момент времени вдобавок к опе­ рати вным журналам Oracle будет применять архивные журнал ы повторения. Кроме того, если вы случайно удалили табли цу или какую-то важную информацию и за­ фиксировали операцию, то можете взять резервную копи ю и запросить у Oracle вос­ становление дан ных на момент прямо перед эти м происшествием с использованием оперативных и архивных журналов повторения . Практически каЖдая операция, выполняемая в Oracle, генерирует какой-то объем данных, которые записываются в журнальные файлы повторен ия транзакц и й . П р и вставке строки в таблицу конечный результат этой вставки записывается в журналы повторений. При удалении строки факт ее удаления также фиксируется . Результаты удаления табл и цы аналогичным образом зап исы ваются в журнал ы повторен и й . Дан ные и з удаленной таблицы не фиксируются , но рекурсивный SQL-зaпpoc, вы­ полняемый Oracle для удале н ия табл и ц ы , генерирует и н формаци ю повторен и я . Например, Oracle удалит строку из таблицы S Y S . O B J $ (и других внутренних объек­ тов словаря) ; это приведет к генерировани ю данных повторения транзакци и , и если различные режимы дополнительной протоколирован ия включены, то действитель­ ный оператор DROP TABLE будет записан в поток журнала повторения транзакц и й . Некоторые операции могут выпол няться в режиме генерации минимально необ­ ходимого объема данных повторен ия . Например, я могу создать индекс с атрибутом NOLOGG ING. Это означает, что сведен ия о первоначальном создани и данных индек­ са не будут зап исан ы в журн ал , но любые рекурсивные SQ L-запросы , выполняе­ мые Oracle от моего имени, протоколироваться будут. Например, вставка в табли цу SYS . OBJ$ строки, свидетельствующей о существовании индекса, будет зафиксиро­ вана в журнале , как и все последующие изменения и ндекса, вызванные выполне­ нием SQL-операторов вставки , обновления и удаления . Н о факт первоначального записывания структуры индекса на диск в журнале не фиксируется. 1 86 Глава 3 Я упоминал о двух тип ах файлов журналов повторен ия - оперативных и архи­ вных. М ы подробно рассмотри м каждый из н их в последующих разделах. В главе 9 мы еще раз взглянем на журналы повторения в сочетании с сегментами отката, что­ бы выяснить, какое воздействие они оказывают на разработчиков. А пока мы прос­ то сосредоточи м внимание на их сущности и назначен и и . О перативный журнал повторения транзакций Каждая база данных Oracle имеет, по крайней мере, две rруппы файлов опера­ тивных журналов повторения . Каждая группа журналов повторения состоит из од­ ного или нескольких элементов (управление журналами повторения осуществляется на уровне групп элементов) . Отдельные элементы этих групп журнальных файлов являются точными зеркальными образами друг друга. Файлы оперативного журнала повторения фиксированы по размеру и используются циклически . СУБД Oracle бу­ дет вы полнять запись в группу 1 журнальных файлов, а когда дойдет до кон ца этого н абора файлов, перейдет к группе 2 и пере п ишет все содержимое этих файлов от начала до конца. Заполнив группу 2 журнальных файлов, она снова вернется к груп­ пе 1 (при налич и и только двух групп журнальных файлов; естественно, при наличии трех груп п журнальных файлов программа перейдет к группе 3). Этот процесс пока­ зан на рис. 3 .4. Рис. 3 . 4 . Запись в группы журнальных файлов Действие по переходу от одной групп ы журнальных файлов к другой назы вают перек.лючением журнальных файлов. Важно отметить, что в неудач но сконфиrуриро­ ванной базе данных переключен ие журнальных файлов может вызывать временную " паузу " . П оскольку журналы повторения служат для восстановления транзакций в случае отказа, мы должны быть уверен ы в том , что не нуждаемся в содержимом журнального файла повторения до того, как появится возможность его использо­ вания . Если такой уверенности нет, Oracle будет на мгновение приостанавли вать операции в базе данн ых и удостоверяться в том , что данные в кеше, "защищаемые" этим журналом nовторения, надежно записаны на диск (создана контрольная точ­ ка) . П осле этого обработка будет возобновлена и файл журнала повторения будет использован повторно. Мы тол ько что затронул и одну и з основных кон цепций баз дан ных: создание контрольной точки . Чтобы nонять, как nрименяются операти вные журналы пов­ торен и я , необходимо знать кое-что о контрольных точках, о работе кеша буфера базы дан ных, а также о том , что делает процесс под названием Database Block Writer (процесс записи блока базы данных), или oвwn. Кеш буфера базы данных и процесс DBWn подробно раскрываются nозже , но мы забежим немного вперед и кратко рас­ смотрим их сейчас. Файл ы 1 87 Кеш буфера базы данных - это место временного хранения блоков базы данных. Он представляет собой структуру в области SGA. По мере чтения блоки сохраняют­ ся в этом кеше в надежде, что позже не придется повторять процесс их физического считывания. Кеш буфера - самое первое устройство, на которое следует обратить внимание при настрой ке производительности . Оно существует еди нствен н о ради того, чтобы очень медлен н ы й процесс физического ввода-вывода выглядел как вы­ полняющийся намного быстрее, чем есть на самом деле . При модификации блока путем обновления в нем строки изменения производятся в памяти - в блоках кеша буфера. При этом объем и нформаци и , достаточн ы й для повторен ия данного изме­ нения , сохраняется в буфере журнала повторен ия транзакций - еще одной струк­ туре данных области SGA. При фиксации изменен и й , делающей их постоя н н ы м и , Oracle н е проходит по всем измененным блокам в SGA с целью их записи на диск, а только записывает содержимое буфера журнала повторен ия в оперативные журналы повторен ия . До тех пор, пока модифицированн ы й блок находится в кеше буфера, а не на диске , мы нуждаемся в содержимом оператив ного журнала н а случай отказа базы данных. Если немедле н но после фиксации изменени й отключить электропита­ ние, кеш буфера базы данн ых будет очище н . Когда такое произойдет, единстве н н ым свидетельством выполненного измене­ ния является запись в файле журнала повторения . П осле перезапуска базы дан н ых Oracle действительно воспроизведет транзакцию, модифицируя блок снова, как м ы это делал и , и зафиксирует изменение . Таким образом , пока измене н н ы й блок хра­ нится в кеше и не записан на диск, мы не можем повторно использовать (перезапи ­ сывать) файл журнала изменен и й . И менно здесь в и гру вступает процесс DBWn. Этот фоновый процесс Oracle отве­ чает за освобождение места в кеше буфера, когда он заполняется , и, что еще важнее, за создание контрольных точек. Создание контрольной точки - это запись " гряз­ ных" (измененн ых) блоков из кеша буфера на диск. Это делается Oracle автомати­ чески в фоновом режиме. Запись контрольной точки может быть вызвана м ногим и причинам и , наиболее распространен ной и з которых я вляется переключение жур­ нальн ых файлов. После заполнения журнального файла 1 и переключен ия на журнальный файл 2 база данных Oracle и н и циирует создан ие контрольной точки . В этот момент процесс DBWn начинает записывать на диск все " грязные" блоки, защищенные группой жур­ нальных файлов 1 . До тех пор, пока DBWn не сбросит на диск все эти блоки, защи­ щенные упомянутым журнальным файлом, Oracle не может применять его повторно (перезаписывать) . П ри попытке воспользоваться журнальным файлом до заверше­ ния создания контрольной точки процессом DBWn в сигнальном журнале базы дан ­ ных появится сообщение, подобное показан ному н иже: Thread 1 cannot allocate new l og , sequence 6 6 Checkpoint not complete Current log# 2 s eq# 6 5 mem# 0 : /home /ora l 2 c r l /app/ora 1 2 c r l / oradat a / orcl / redo 0 1 . log Поток 1 не может разместить новый журнал , последова тельность 66 Создание контрольной точки не завершено Номер текущего журнала 2 последова тельности 65 обла сти памяти 0 : /home/ora l2crl /app/ora l 2crl /orada ta /orcl /redo 0 l . l og 1 88 Глава 3 Итак, когда появилось такое сообщение, обработка в базе данных была приоста­ новлена на время , пока процесс DBWn торопливо создавал контрольную точку. В этот момент Oracle предоставляет процессу DBWn всю доступную вычислительную мощь, чтобы он мог как можно быстрее завершить свою работу. Это сообщение никогда не должно появляться в хорошо настроенном экземпляре базы дан ных. Если вы видите его, то знайте , что вы ввели искусственные и нежела­ тельные ожидания при работе конечных пользователей. Этого всегда можно избежать. Цель (причем администратора базы данных, а не обязательно разработчика) заключа­ ется в обеспечени и достаточного количества журнальных файлов, чтобы не приходи­ лось пытаться повторно использовать один из них до завершения создания контроль­ ной точки (инициированного переключением журнальных файлов). Частое появление такого сообщен ия свидетельствует о том , что администратор базы данных не выделил приложению достаточное число оперативных журналов повторен ия транзакций, или о том , что процесс DBWn нуждается в настройке для более эффективной работы . Разные приложения будут генерировать разное количество журналов повторения . Система поддержки принятия решен и й ( Decision Support System - DSS) или систе­ ма и нформационного хранилища ( DW) по своей природе ежедневно будет генериро­ вать значительно меньше данных для оперативных журналов nовторения, чем сис­ тема O LTP. Система, которая выполняет множество ман ипуля ций с изображениями в больших двоичных объектах ( В inary Large Objects - B LOB) базы дан н ых, может генерировать радикально больше данных повторения, чем простая система обработ­ ки заказов . Система обработки заказов, имеющая сто пол ьзователей , скорее всего, будет генерировать десятую часть объема данных повторен ия , которые генерировала бы система с тысячей пользователей . Таким образом, не существует какого-то " пра­ вильного" размера для журналов повторен ия , хотя вы должн ы стремиться обеспе­ ч ить и м такой размер, которы й достаточен для конкретной рабочей нагрузки . П р и установке размеров и количества операти вных журналов повторения вы должн ы принимать во внимание множество факторов. М ногие факторы выходят за рамки тематики этой кни ги , но некоторые из н их перечислены н иже, чтобы вы мог­ ли получить общее представление. • Пиковые рабочие нагрузки. Желательно, чтобы системе не nриходилось дожи­ даться завершения создания контрольных точек и чтобы в ней не возн икали узкие места во время пиковых нагрузок. В ы должны определять размер журна­ лов повторения в расчете не на среднюю часовую пропускную способность, а на пиковую нагрузку. Если на протяжении дня генерируется 24 Гбайт журналь­ ных данных, но 1 0 Гбайт из них попадают в период с 9:00 до 1 1 :00, то размеры журнальных файлов должны быть достаточ но большими, чтобы выдерживать эту двухчасовую п и ковую нагрузку. Установка их размеров, исходя из средней величины l Гбайт в час, вероятно, окажется недостаточной . • Наличие множества пользователей, изменяющих одни и те же блоки. Это также может требовать nрименения больших журнал ьных файлов. П осле того, как каждый из них модифи цирует те же самые блоки , желател ьно обеспечить мак­ симально возможное количество их обновлений перед записью на диск. Каждое переключен ие журнальных файлов будет инициировать создание контрольной точ ки , поэтому неплохо сделать так, чтобы переключение nроисходило как можно реже. Тем не менее, это может повл иять на время восстановления. Файл ы • 1 89 Среднее время восстановления . Если вы должны обеспечить минимальное время восстановления , то можете склониться в сторону использования меньших по размеру журнальных файлов даже с учетом предьщущего обстоятельства. При восстановлении обработка одного или двух небольших журнальных файлов пот­ ребует меньшего времени, чем обработка одного гигантского файла. Возможно, это приведет к общему замедлению повседневной работы системы (из-за созда­ ния дополнительных контрольных точек) , но время , уходящее на восстановле­ ние, сократится . Впрочем, существуют также и другие параметры базы данных , которые можно применять дл я сокращения времени восстановления в качестве альтернативы использованию небольших журнал ьных файлов. Архивный журнал повторения транзакций База дан н ы х O racle м ожет фун к ц и о н и ровать в одном и з двух режи мов: ARCH I VELOG и NOARC H I VELOG. Отличие между ними связано с тем , что происходит с файлом журнала, когда Oracle собирается использовать его повторно. При этом необходимо ответить на важны й вопрос : " Сохран и м ли мы копи ю этого журнала повторения ил и пусть Oracle просто перезапишет его, утрати в навсегда? " Если вы не сохран ите этот файл , то восстановление данных на текущи й момент времен и из резервной копии окажется невозможным. Предположим , что резервное коп ирование выполняется раз в неделю по суббо­ там . В полдень пятницы, после того как за неделю были сгенерированы сотн и жур­ нальных файлов, жестки й диск отказы вает. Если база данных не работает в режиме ARCHIVELOG, то у вас есть только две возможности. • Удалить табличное пространство или пространства, ассоци ирован ные с отка­ завшим диском. Любое табличное пространство, которое и меет файл на этом диске, должно быть удалено вместе со всем его содержимым. Если отказ диска затронул табличное пространство SYSTEM (словарь данн ых Oracle) или какое­ то другое табличное пространство, связанное с системой , например, UNDO, то сделать это не получится. В таком случае придется воспользоваться следующей возможностью. • Восстановить данные, сохраненные в предыдущую субботу, и потерять резуль­ таты работы, выполненной за неделю. Н и один из вариантов не выглядит привлекательным. Оба они предполагают уте­ рю данных. С другой стороны, если бы база данных работала в режиме ARCH I VELOG, то достаточно было бы найти другой диск и восстановить на него испорченные фай­ лы из субботней резервной коп и и . Затем нужно было бы применить архивные жур ­ нальные файлы и, в кон це концов, оперативные журнал ы повторен ия (в сущности , воспроизводя в ускорен ном режиме выполненные за неделю транзакции ) . При этом ничего не теряется . Данные восстанавливаются на момент отказа диска. Люди часто говорят мне, что не нуждаются в режиме ARC H I VELOG для их произ­ водственных систем. Я еще ни разу не встретил того, кто был бы корректен при та­ ком заявлении. Я уверен в том , что система не может считаться производствен ной, если она не функционирует в режиме ARCH I VELOG. База данных, которая не рабо­ тает в режиме ARC H I VE LOG, однажды потеряет данные. Это неизбежно; вы потеря­ ете данные (не возможно, а обязательно), есл и ваша база данных не выполняется в режиме ARCНIVELOG. 1 90 Глава 3 Обычно в качестве оправдания можно услышать: " М ы используем RAI D-5, по­ этому полностью защищены " . Мне приходилось сталкиваться с ситуациями, ког­ да из-за производствен н ых дефектов все диски в масси ве RAI D останавли вались, причем почти одновременно. В некоторых случаях аппаратный контроллер при­ водил к поврежде н и ю файлов данных, в результате чего устройства RAI D надежно защищали уже поврежденные данные. Кроме того, система RAI D не защи щает от ошибок операторов - одной из наиболее распространенных причин потери данн ых. Применение RAID не означает, что данные находятся в безопасности ; данн ые могут быть доступнее, они могут быть более защищены, но данные, хранящиеся только на устройстве RAI D , когда-нибудь будут утерян ы - это лишь вопрос времени. Очень часто можно услышать: " Если бы у нас были резервные копии базы дан­ ных на момент, предшествовавш и й аппаратному сбою или ошибке оператора, то мы смогли бы восстановить данн ые " . П о этому поводу можно лишь сказать, что отказ от использования режима ARC H I VELOG в системе, содержащей сколько-нибудь цен­ ные данн ы е , нельзя ничем оправдать. Стремление к высокой производительности оправданием не я вляется ; правильно сконфигурированная архивация увеличи вает накладные расходы лишь незначительно либо вовсе не влияет на них. Указанное об­ стоятельство и тот факт, что быстрая система, которая теряет данные, совершенно бесполезна, обусловливает необходимость применения архивации даже в том случае, есл и это приведет к стопроцентному росту накладных расходов. Функциональное средство можно отнести к накладным расходам , если от него можно отказаться без утери чего-либо важного; накладные расходы подобн ы сахарной глазури на пирож­ ном . Сохранение дан ных и обеспечение невозможности их потери не является на­ кладными расходами - наоборот, это первоочередная задача администратора базы данных! В режиме NOARCH I VE LOG могут находиться только тестовые системы или воз­ можно системы для разработки приложений. Большинство систем разработки долж­ ны функционировать в режиме ARC Н I VELOG по двум причинам. • Это способ обработки данных в производствен ной среде ; вы хотите , чтобы система разработки действовала и реагировала так, как будет себя вести реаль­ ная рабочая система. • Во многих случаях разработчи ки извлекают свой код из словаря дан ных, моди­ фицируют его и комп илируют обратно в базу. База разработки хранит текущую версию кода. Если база разработки подвергается отказу диска после обеда, что произойдет со всем кодом, который вы комп ил ировали и повторно комп или­ ровали все утро? Он будет утерян . Н е позволяйте н и кому отговаривать вас от использования режима ARCHI VELOG. На разработку приложен и я было потрачено много времен и , поэтому вы должн ы стремиться к тому, чтобы пользователи ему доверял и . П отеря их данных никоим об­ разом не способствует повышению доверия к системе. На заметку! В некоторых случаях работа крупного и нформационного хранилища в режиме NOARCH I VE LOG может оказаться оnравданной , если в нем п родумано применяются таб­ личные п ространства READ ONLY и если л юбое табличное пространство READ W R I T E , пострадавшее о т сбоя , должно быть полностью перестроено путем повторной загрузки данных. Файлы 1 91 Ф айлы пароп ей Файл паролей - это необязател ьн ый файл , которы й позволяет удаленному ад ­ министратору или пользователю SYS DBA получать доступ к базе данн ых. Когда вы пытаетесь запустить Oracle , не существует какой -то доступной базы данных, к которой можно было бы обратиться для проверки подлинности паролей . При запуске Oracle в локальной системе (т.е. не по сети, а с ком пьютера, на котором будет располагаться экземпляр базы данн ых) для выполнения действий по аутенти­ фикаци и Oracle будет использовать средства ОС. При устан овке Oracle необходимо указать группу ОС для адм и н истраторов. Обычно по умолчани ю в системе U N IX/Linux этой группой будет DBA, а в системе Windows - O RA_DBA. Тем не менее, это может быть любое имя груп n ы , допусти­ мое на текущей nлатформе. Такая группа обладает "особым " статусом в том смысле, что любой входя щий в нее пользователь может подключаться к базе данных " как SYS DBA" , не указывая имя пользователя или пароль. Например, в своей установлен­ ной коп ии Oracle 1 2с Release 1 я задал группу o r a 1 2 c r l . Л юбой пользователь, вхо­ дящий в эту группу, может подключаться без указан ия имени пользователя/пароля : [ t kyte@dellpe - ] $ groups t kyte ora 1 2 c r 1 ora 1 1gr2 ora 1 0gr2 [ t kyte @de1 lpe - ] $ sqlplus 1 as sysdЬa SQL* Plus : Re lease 1 2 . 1 . 0 . 1 . 0 Production on Tue Sep 3 1 4 : 1 5 : 3 1 2 0 1 3 Copyright ( с ) 1 9 8 2 , 2 0 1 3 , Oracle . Al l r i ghts res e rved . Connected to : Oracle Database 1 2 с Enterprise Edition Release 1 2 . 1 . 0 . 1 . 0 - 6 4bit Production With the Part i t i oning , OLAP , Advanced Analytics and Real App l i cation Testing options SYS@ ORA1 2CR1 > show user USER i s " SYS " Как видите, все работает. Я подключился и теперь могу запускать базу дан ных, останавливать ее или выпол нять любые действия по адми н истрированию. Однако предположим, что эти операц и и необходимо выполнять с другого комп ьютера че­ рез сеть. В этом случае я пробую подключиться с применением строки соединения TNS. Однако попытка оказывается неудачной : [ t kyte @del lpe - ] $ sqlplus / @ or a 1 2 c r 1 a s s ys dЬa SQL* Plus : Re lease 1 2 . 1 . 0 . 1 . 0 P roduct ion on Tue Sep 3 1 4 : 1 6 : 2 2 2 0 1 3 Copyright ( с ) 1 9 8 2 , 2 0 1 3 , Oracl e . Al l r i ghts rese rved . ERROR : ORA- 0 1 0 1 7 : inva l id use rname /pa s s word ; logon denied ОПМБКА : ORA- 0 1 01 7 : недопустимое имя пользова теля/пароль ; вход запрещен Аутентификация со стороны ОС пользователя S Y S D BA через сеть не будет ра­ ботать даже при установке в T RUE значе н ия очен ь нежелательного (с точки зрен ия безопасности) параметра REMOT E_ os _AUTHENT. Таким образом, аутентификация со стороны ОС не работает и , как обсуждалось ранее, когда вы пытаетесь запустить эк- 1 92 Глава 3 земпляр Д1IЯ монтирования и открытия базы данн ых, то по определению пока еще нет какой-либо базы дан н ых , где бы можно было найти сведения по аутентифика­ ц и и . Это оди н из примеров пресловутой проблемы с выяснением, что первично курица или яйцо. Н а выручку приходит файл паролей . В этом файле хранится список имен поль­ зователей и паролей , которым разрешена удаленная аутентификация через сеть как S Y S DBA. Для их аутентификации СУБД Oracle должна использовать этот файл, а не обычный список паролей, хранящи йся в базе данных. Итак, давайте исправим ситуацию. Для начала проверьте, что параметр REMOTE LOG I N_PAS SWORDF I LE установлен в свое стандартное значен ие EXCLUS IVE, которое предусматривает использование предоставленного файла паролей только одной ба­ зой данных: EODA@ORA12CR1> s how pa rameter remote_login_pas swordfile NАМЕ ТУРЕ VALUE remote_login_pas sword f i l e s t r ing EXCLUS I VE На заметку! Другими допустим ы м и значениями для этого параметра явля ются NONE, ука­ зывающее на отсутствие файла паролей ( нет удаленных подключений SYS DBA ) и S HARE D ( оди н файл паролей может быть задействован более , чем одной базой данных). Затем с помощью утилиты командной строки (в U N IX/Linux и Windows) под на­ зван ием orapwd необходимо создать и заполнить файл паролей : [ ora l 2 c r l @del lpe - ] $ orapwd Us age : orapwd f i l e=< fname> ent r ie s =<u s er s > force=<y/n> a sm=<y/n> dЬun i quename=<dЬname> format=<legacy/ 1 2 > sysbackup=<y/n> sysdg=<y/n> sy skm=<y/n> delete=<y/n> input_f i l e=<input - fname> Использование : orapwd fi l е=<имя_файла> еп tri еs=<пользова тели> force=<y/n> a sm=<y/n> dЬuп iqиепате=<имя_базы_данных> forma t =<lega cy/1 2> sysba ck up=<y/n> sysdg=<y/n> syskm=<y!n> del e te=<y/n> iпрu t_fi l е=<имя_входного_ файла> Usage : orapwd des cribe f i le=< fname> Использование : orapwd describe fi l е=<имя_файла > whe re There mus t Ье no space s around the equal - to ( = ) character . где Пробелы в озле знака равенства (=) не разрешены. Команда, которую мы будем применять при входе с учетной записью олерацион ­ ной системы , владеющей проrраммным обеспечением Oracle , выглядит следующим образом : [ ora l 2 c r l @del lpe dЬs ] $ orapwd f i le=orapw$0RACLE_S I D pas s word=bar entr ies=2 0 В моем случае создается файл паролей по имени o r apwo r a l 2 c r l (идентифи­ катором ORACLE S I D у меня является o ra l 2 c r l ) . Это соответствует соглашению Файл ы 1 93 об именован и и данного файла, используемому на больши нстве платформ U N I X/ Linux (детал и , связанные с именованием этого файла для кон кретной платформ ы можно найти в руководстве по установке и адми н и стрировани ю ОС). Файл раз­ мещен в каталоге $ 0 RAC L E_HOM E / db s . В системе Windows этот файл и меет имя PW % 0RACLE_S I D% . ora и находится в каталоге % 0RACLE_HOME % \ dat aba s e . П режде чем запускать команду для создания данного файла, необходимо перейти в правил ь­ ный каталог или переместить файл в этот каталог впоследстви и . В настоя щее время в файле присутствует тол ько оди н пол ьзователь S Y S , не­ смотря на то, что база дан ных содержит и другие учетные записи SYS DBA (они пока еще не зап исаны в файл паролей ) . Однако, располагая этой информацией , можно выполнить первое подключение к базе данных через сеть в качестве пользователя SYS DBA: [ t kyte@de l lpe - ] $ sqlplus sys/bar@ ora 1 2 c r 1 as sysdba SQL* Plus : Re lease 1 2 . 1 . 0 . 1 . 0 Production on Tue Sep 3 1 4 : 2 1 : 0 8 2 0 1 3 Copyr ight ( с ) 1 9 8 2 , 2 0 1 3 , Oracle . Al l rights r e s erved . Connected to : Oracle Database 1 2 с Enterpri s e Edition Release 12 . 1 . 0 . 1 . 0 - 64bit P roduction With the Part i tioning , OLAP, Advanced Analytics and Real Appl i cation Testing options SYS@ORA1 2CR1> На заметку! Есл и на этом шаге вы столкнетесь с ошибкой ORA- 1 2505 "TN S : I istener does not currently know of SID given in connect Descriptor" (ORA- 1 2505 " Прослуши вающему nроцессу TNS в настоящий момент не известен идентифи катор S I D , п редоставленный в дескри п ­ торе соединения " ) , значит, проелуш и вающий nроцесс базы данных не сконфигурирован со статической регистрационной записью для этого сервера. Адм инистратору базы дан­ ных не разрешено удаленно подкл ючаться как S Y S DBA, когда э кзем пляр базы не запу­ щен . Именно так обстоят дела в большинстве установок Oracle9i и последующих верси й . Необходи мо настроить статическую регистрацию сервера в конфигурационном файле l i s t e n e r . o r a . Пои щите на странице поиска в документации OTN (Oracle Technology Network) для своей версии СУБД подробную и нформацию о конфигурации этой статичес­ кой службы , указав в качестве искомой строку "Configuring Static Service l nformation". М ы прошли аутентификацию и , следовательно, вошли в систему. Теперь мы можем успешно выполнять удаленный запуск, останов и администрирован ие базы дан ных с применением учетной записи S Y S DBA. В системе присутствует еще оди н пользователь, OPS$TKYTE, которому были выданы права SYS DBA, н о о н пока не мо­ жет удаленно подключаться к базе данных: [ t kyte @de llpe - ] $ sqlplus ' op s $ t kyte / foobar ' @ ora 1 2 c r 1 a s sysdba SQL* Plus : Re lease 1 2 . 1 . 0 . 1 . 0 Production on Tue S ep 3 1 4 : 2 2 : 2 1 2 0 1 3 Copyr ight ( с ) 1 9 8 2 , 2 0 1 3 , Oracle . Al l rights reserved . ERROR : ORA- 0 1 0 1 7 : i nvalid use rname /pas sword; logon denied ОПМБКА : ORA-01 01 7 : недопустимое имя пользова теля/пароль ; вход запрещен 1 94 Глава 3 П ричина неудачи подключен ия в том, что пользователь ORS $TKYTE еще не зане­ сен в файл паролей. Чтобы записать его в файл паролей , необходимо "заново вы­ дать" этой учетной записи привилегию SYS DBA: [ t kyte @ de l lpe - ] $ s qlplus 1 as sysdЬa SQL * P l u s : Re lease 1 2 . 1 . 0 . 1 . 0 Production on Tue Sep 3 1 4 : 2 3 : 1 1 2 0 1 3 Copyr ight ( с ) 1 9 8 2 , 2 0 1 3 , Oracl e . Al l r ights rese rved . Connected to : Oracle Databas e 1 2 с Enterprise Edition Re lease 1 2 . 1 . 0 . 1 . 0 - 64bit Product�on With the Partit ioning , OLAP , Advanced Ana1ytics and Rea1 Appl i cation T e s ting opt ions SYS@ORA1 2CR1> grant s ys dЬa to ops $ t kyte ; Grant s ucceeded . Выдано успешно . SYS @ORA1 2 CR 1 > e x it Dis connected from O r ac l e Databas e 1 2 с Enterpr i s e Edition Release 1 2 . 1 . 0 . 1 . 0 - 64bit Production With the Partit ioning , OLAP , Advanced Ana lytics and Real Appl i cation T e s t i ng opt ions [ t kyte @ de l lpe - ] $ s qlp1us ' op s $ t kyte / foobar ' @ ora 1 2 c r 1 as sysdba SQL * P l u s : Release 1 2 . 1 . 0 . 1 . 0 Production on Tue Sep 3 1 4 : 2 3 : 2 5 2 0 1 3 Copyr ight ( с ) 1 9 8 2 , 2 0 1 3 , Oracl e . Al 1 r ight s reserved . Connected to : Oracle Databas e 1 2 с Enterprise Edi tion Re lease 1 2 . 1 . 0 . 1 . 0 - 64bit Product ion With the P a r t i tioning , OLAP , Advanced Ana lyt i c s and Rea l App l i cation T e s t i ng opt ions SYS @ ORA12CR1> Этот запрос создал запись в файле паролей, и теперь Oracle будет поддерживать параль в синхронизированном состоя н и и . Если пользователь O P S $ T KYTE изменит свой п ароль, стары й параль п ерестанет действовать для удаленных подключений SYS DBA, а НОВЫЙ вступит в силу. Аналогичный процесс повторяется для любого пользователя , который имел при­ вилегию SYS DBA, но не бьш записан в файл паролей . Ф айл отслежи ва н ия изменений Файл отслеживания изменений - это необязательный файл , предназначенный для использования с O racle l Og Enterprise Edition и последующими версиям и . Его еди нственное назначение заключается в отележивани и блоков, которые были изме­ нены с момента последнего и н крементнаго резервного копирования. Это позволяет утилите RМAN ( Recovery M anager - диспетчер восстановления) выполнять резерв­ ное копирование только тех блоков базы дан н ых, которые действительно были из­ менены, без необходимости в считы вани и всей базы данных. Файл ы 1 95 В версиях, предшествующих Orac1e 1 Og, при и н крементнам резервном коп иро­ ван ии для выявления блоков, которые был и изменены с момента последне го и н ­ крементного копирован ия, приходилось считы вать весь н абор файлов базы дан ­ ных. Таким образом , если в базу данных объемом 1 Тбайт было добавлено всего 500 Мбайт новых данных (например, производилась загрузка информационного храни­ лища), то для нахождения этих 500 М байт новой и нформации с целью резервного копирования пришлось бы прочитать 1 Тбайт данн ых. В итоге процесс инкремент­ наго резервного копирования сохранял значительно меньш и й объем данных, но ему по-прежнему требовалось считывать всю базу данных. В Orac1e 1 Og Enterprise Edition и последующих версиях такая проблема больше не возни кает. В процессе работы базы данн ых и по мере того, как блоки модифициру­ ются, Orac1e дополнительно поддерживает файл, который указывает утилите RMAN , какие блоки были изменены. Создается этот файл отележиваимя изменени й доволь­ но просто с помощью команды ALTER DATABASE : SYS@ORA12CR1> a l t e r da tabase enaЬle Ьlock change tracking u s i ng f i l e 2 ' /home /ora 1 2 c r l /oradata/ORA1 2CR1 / changed_Ьlocks . bct ' ; Database al tered . База данных изменена . Внимание! В этой книге я время от времени повторяю: не забывайте , что команды , которые устанавли вают параметры , модифицируют базу данных или вносят существенные изме­ нения, не должны в ыдаваться необдуманно и , безусловно, их следует протестировать, прежде чем вы полнять в " реальной" системе. П редыдущая ком анда в действительнос­ ти заставит базу данных делать больший объем работ и при ведет к росту потребления ресурсов . Чтобы отключить и удалить файл отслежи вания измененных блоков, нужно снова воспользоваться командой ALTER DATAВAS E: SYS @ORA1 2 CR1> a l t e r databas e d i s aЬle Ьl o c k change tracking ; Databa se al tered . База данных изменена . Обратите вниман и е , что эта команда удалит файл отслеживан ия измененных блоков. Она не просто отключает функци ю отслеживания - она также удаляет сам файл . На заметку! В определенных операционных системах, таких как Wiпdows, вы можете обна­ ружить, что после запуска приведеиного примера - создание файла отслежи вания из­ мененных блоков и затем отключение функци и отслеживания - файл по-прежнему су­ ществует. Это проблема, специфичная для ОС: во м ногих операционных системах она не проявляется. Она возникает, тол ько если файл отслеживания измененных блоков созда­ ется и откл ючается в одном сеансе . Сеанс, создавший файл отслеживания измененных блоков, оставляет его открыты м , а в ряде ОС не разрешено удалять файл , который открыт предыдущи м процессом ( например, процессом сеанса, создавшего файл ) . В этом нет ни­ чего страшного - nросто позже понадобится удалить файл самостоятельно. Фун кция отслеживания измененных блоков м ожет быть включен а в режиме ARCНI VELOG или NOARCHIVELOG. Но помните, что база данных, работающая в режи- 1 96 Гл ава 3 ме NOARCH I VELOG, в котором ежедневно генерируемый журнал повторения не сохра­ няется, не и меет возможности восстановить все изменения в случае отказа носителя (диска либо устройства)! Однажды такая база данных неизбежно утратит данные. Мы рассмотрим эти два режима работы базы данных более подробно в главе 9. Р етроспекти вн ые журналы Ретроспекти вные журнал ы (flashback log) были введены в Oracle 1 Og для подде­ ржки команды FLASHBACK DATABAS E нового средства этого выпуска базы данных в редакции Enterprise Edition . Ретроспективные журналы содержат "предшествую­ щие образы " модифицированных блоков базы данн ых, которые можно применять для восстановлен ия базы данных в состоян и и на определенный момент времени в прошлом . - Команда FLASНВACK DATAВASE Команда FLAS HBACK DATABASE была добавлена для ускорения достаточно мед­ лен ного процесса восстановления базы данн ых на определенный момент времени. Ее можно использовать вместо полного восстановления базы дан н ых и наката с применением архивных журналов, и она предназначена главным образом для по­ вышения скорости восстановления после " катастрофы " . Например, давайте пос­ мотрим, что адми н истратор базы данных может сделать для восстановления после случайного удаления схемы не той базы данн ых (удалять нужно было версию в тес­ товой среде) . Администратор сразу же заметил свою ошибку и немедленно остано­ вил СУБД. Но что делать дальше? До появления возможности FLAS HBACK DATABAS E адми н истратору, скорее всего, пришлось бы выполнить следующие действия. 1 . Остановить базу данн ых. 2 . Восстановить последнюю пол ную резервную копию базы данных с магнит­ ной ленты (как п равило) , что в общем случае представляет собой длительный процесс. Обычно это и н и циируется в RMAN посредством команды RES TORE DATABAS E UNT I L <момент_времени> . 3 . Восстановить все архивные журналы повторен и й , сгенерированные с момента резервного копи рован ия . 4. Используя архивные журналы повторения (и возможно информацию из опе­ ративных журналов повторения), произвести накат (последовательное вы пол­ нение всех ранее выполненных транзакций) базы данных до момента, непос­ редственно предшествующего ошибочному применению команды DROP USER. Ш аги 3 и 4 в этом списке обычно и н и ци ируются в RMAN через команду RECOVER DATABAS E UNT I L <момент_времени> . 5 . Открыть базу данных с опцией RESETLOGS . Это был весьма непростой процесс с многочисленными шагами, который в це­ лом занимал длительное время (в течен ие которого, естествен но, никто не мог полу­ чать доступ к базе данных) . П ричин для подобного восстановления базы данных на определенн ы й момент времени множество: некорректно сработавший сценарий мо­ дерн изации ; неудавши йся процесс модернизации ; невнимател ьная выдача команды Файл ы 1 97 кем-то с достаточными пол номочиям и (пожалуй, самы й часто встречающийся слу­ чай) ; создание каким-то процессом проблем с целостностью дан н ых в круп ной базе данн ых (опять-таки, случайное событие ; возможно, процесс был запущен два раза вместо одного или содержал в себе ошибку). Какой бы ни была причина, конечным результатом станет дл ительный простой. Ниже описаны шаги , которые адми н истратору базы дан н ых понадобится выпол­ нить в Oracle 1 Og Enterprise Edition и последующих версиях для восстановления базы данных при наличии сконфигурированной возможности ретроспективы. 1 . Остановить базу данн ых. 2. Выполнить начал ьное монтирование базы дан н ых и выдать команду ретрос­ пекти вного восстановления, используя номер SCN (внутренние часы Oracle), точ ку восстановления (указатель на SCN ) либо метку времени (показание обычных часов) с точностью до пары секунд. 3. Открыть базу данных с указанием опции RE S ETLOG S . Для применения этой функциональности база дан н ых должна работать в режи­ ме ARCНIVELOG и быть сконфигурирован ной для включения команды FLAS HBACK DATABAS E . Иначе говоря , возможность ретроспективы должна быть настроена до того, как в ней возникнет потребность. Ее нел ьзя вкл ючить после того, как база данных окажется поврежденной , поэтому решение о ее использовании следует при­ нимать заранее . Облас т ь для быст рого восс т ановления Область для быстрого восстановления ( Fast Recovery Area) - новая концепция в Oracle 1 Og и последующих версиях. Начиная с Oracle 1 Og, впервые за многие годы (свыше 25 лет) концепция резервных копи й в Oracle изменилась. В прошлом в ос­ нове резервного коп ирования и восстановления лежала кон це пция применения устройств с последовательным доступом , таких как накоп ители на магнитных лен­ тах. Устройства произвольнаго доступа (диски) всегда считались сли ш ком дорогос­ тоящими, чтобы тратить их на обычные резервные коп и и . В итоге использовались сравнительно дешевые ленточн ые устройства большой емкости . Однако в наши дни можно приобрести терабайты дискового хранили ща по очен ь низкой цене. Например, м о й с ы н Ал а н стал первым ребен ком в квартале, облада­ ющи м сетевым устройством хранения (network attached storage - NAS) объемом 1 Тбайт. Оно обошлось мне в $ 1 25 . Я вспоминаю первый жесткий диск, установ­ ленный на моем переональном компьютере : он и мел колоссальный на тот момент объем 40 Мбайт. Н а самом деле мне пришлось его еще и разбить н а два логических диска, поскольку ОС, с которой я и мел дело тогда ( M S-DOS), была не в состоян и и распознавать диски емкостью больше 32 М байт. За последние 25 лет или около того ситуация коренным образом изменилась. Область Fast Recovery Area в Oracle - это местоположение, где СУБД будет уп­ равлять множеством файлов, связанных с резервным коп ированием и восстановле­ нием баз данных. В этой области (области, которая является частью набора дисков и предназначена для этой цели - например, каталог) можно найти : • фрагменты резервных копи й RMAN (пол н ых и/или инкрементных резервных копий); 1 98 Глава 3 • коп и и образов RMAN (побайтовые коп и и файлов дан ных и управляющих файлов) ; • оперативные журналы повторения; • архивные журналы повторения; • мультипле ксированные управляющие файл ы ; • ретроспективные журналы . Новая область Fast Recovery Area применяется Oracle мя управления перечислен­ ными файлами , поэтому серверу известно, что присутствует на диске, а что отсутс­ твует (и находится , возможно, где-то на магнитной ленте). Используя эту информа­ цию, Oracle может выполнять такие операции, как восстановление поврежденных файлов дан н ых с диска на диск или ретроспективный откат (операция " перемотки в начало") базы данных дJ1Я отмен ы операции , которая не должна была выполняться . Например, команду FLAS HBACK DATAВASE можно было бы применить мя возвраще­ н ия базы данных в состояние, в котором она пребывала пять минут назад (не делая полное восстановление базы данных и ее восстановление на определенный момент време н и ) , что п озволяет отмен ить, к примеру, случайное удаление учетной записи пользователя . Область Fast Recovery Area - нечто большее, чем логическая концепция . Это об­ ласть, содержащая тип ы файлов, которые были рассмотрены в главе . Ее использо­ ван ие не я вляется обязательн ы м , но если вы намерены применять некоторые рас­ ширенные возможности вроде FLAS HBACK DATABAS E , то должны использовать эту область дJ1Я хранения информации . Ф айлы DMP ( файл ы э кспорта / и мп орта ) Утилиты Export (Экспорт) и I mport ( И м порт) - уважаемые инструменты из­ влечения и загрузки дан ных Oracle , которые входили в состав множества версий . Задача утилиты Export заключается в создан и и независимого от платформы файла D M P, который содержит все обязательные метаданные (в форме операторов CREATE и ALT E R) и дополн ительно сами дан ные дJ1Я воссоздания таблиц, схем и даже целых баз данных. Еди нственное назначение утилиты l mport состоит в чтении этих файлов DM P, выполнении операторов D D L и загрузке любых найденных данных. На заметку! В версии Oracle Database 1 1 g Release 2 утилита Export была официально объ­ явлена устаревшей. Она поставляется только для применения с унаследованными струк­ турами баз дан н ых. Новые типы данных, новые структуры , новые функциональные воз­ м ожности баз данных этот и н струмент не поддерживает. Я настоятел ьно рекомендую пол ьзоваться Data Pump - пришедши м на замену инструментом экспорта/импорта , ко­ торый несколько лет тому назад появился в Oracle 1 0g. Файлы D M P спроектированы так, чтобы обеспечивать обратную совместимость, т.е . более новые версии могут успешно ч итать и обрабатывать файлы D M P из пред­ шествующих вы пус ков. Я сл ышал о л юдях, которые экспортировали базу данных верси и 5 и благополуч но и м портировали ее в Oracle l Og (просто ради проверки ) . Таким образом , процесс l mport может считывать старые версии файлов D M P и об- Файл ы 1 99 рабатывать содержащиеся в них дан н ы е . Однако обратное , скорее всего, окажет­ ся невозможн ым: процесс l mport, входящий в состав Orac1e9i Re1ease 1 , не может, да и не должен , считывать файл D M P, которы й создан версией Orac1e9i Re1ease 2 или Orac1e 1 Og Re1ease 1 . Например, я экспортировал простую таблицу из Oracle l lg Release 2. Когда я попробовал воспользоваться эти м и файлами D M P в O racle9i Release l , то быстро обнаружил , что процесс l mport этой версии даже не пытается обрабатывать файл D M P версии Oracle l lg Release 2: $ imp use rid= / full=y Import : Release 1 0 . 2 . 0 . 4 . 0 - Product ion on Wed Jan 20 1 8 : 2 1 : 0 3 2 0 1 0 Copy right ( с ) 1 9 8 2 , 2 0 0 7 , Oracle . Al l rights re s e rved . Connected to : Oracle Databas e 1 0g Enterp r i s e Edit ion Re l e a s e 1 0 . 2 . 0 . 4 . 0 Production With the Part itioning, OLAP , Data Mining and Real Appl icat ion Test ing opt ions IMP - 0 0 0 1 0 : not а va l i d export f i l e , heade r failed ve r i f i cation IMP - 0 0 0 0 0 : Import terminated unsucce s s fu l l y IMP- 0001 О : недопустимый экспортный файл , заголовок не прошел верификацию IMP- 00000 : процесс Import завершен неуда чно . Даже в случае, если бы инструмент l mport мог распознать файл , высоки шан­ сы на то, что D D L-кoд, сгенерированный и нструме нтом Export из версии Oracle I lg Release 2 , не сможет быть распознан в более ранних версиях Oracle. Например, предположим , что вы экспортируете из любой выпуска Oracle верси и 9i Release 2 или выше. В экспортном файле вы обнаружите , что к каждому оператору CREAT E TABLE добавлена опция COMPRE S S или NOCOMPRE S S . Средство базового сжатия таб­ лиц появилось в версии Oracle9i Release 2. Если попробовать прочитать этот экспор­ тный файл в любой версии базы, предшествовавшей 9i Release 2 , то выяснится , что содержащи йся в нем D D L-кoд не выпол ня ется , причем в 1 00% случаев . Н и оди н оператор CREATE TABLE н е будет работать, поскольку ключевые слова NOCOMPRE S S 1 COM PRESS в старых выпусках не распознаются . Файлы D M P явля ются н езависимыми от платформ ы , поэтому их можно безо­ пасно экспортировать из любой платформ ы , перенести на другую платформу и за­ тем импортировать (при условии , что установленная версия Oracle разрешает это). Однако при переносе файлов с помощью FТР в среде Windows возникает проблема, обусловленная тем , что по умолчанию Windows посчитает файл D M P текстовым и будет стремиться преобразовать символы перевода строки (маркеры конца строки в U N IX/Linux) в пары символов возврата каретки/перевода строки , полностью разру­ ш ая файл D M P. При передаче файла D M P по FТР в среде Windows необходимо вы­ бирать двоичный режим. Если окажется , что процесс импорта не работает, необхо­ димо удостовериться , что размеры исходного и целевого файлов совпадают. Я даже не могу вспомн ить, сколько раз эта проблема стопорила процесс переноса файлов. Файлы D M P являются двоичн ы м и , т.е . их н ельзя редактировать для внесен ия изменени й . Из них можно извлечь большой объем и нформации ( D D L- команды CREAT E и многое другое) , но их нельзя редактировать в текстовом (ил и в любом дру­ гом) редакторе . В своей книге Expert One-on-One Orac/e я посвятил немало страниц описанию утил ит l mport и Export и файлов DMP. П опулярность этих утилит снижа­ ется в связи с появлением предлагающих большие возможности утилит Data Pump. 200 Глава 3 Ф айл ы Data Pump Data Pump (помпа данн ых) - это файловый формат, который используется , по меньшей мере , двумя инструментами в Oracle. Внешние таблицы могут загружать и выгружать данные в этом формате, а новые программные средства импорта/экспор­ та I M P D P и EX P D P используют его во м ногом подобно тому, как утилиты I mport и Export работают с файловым форматом D M P. Н а заметку! Формат Data Pump ориентирован н а применение исключительно в Oracle 1 Og Release 1 и последующих версиях - в вы пуске Oracle9i он не существовал и не может там использоваться . Значительная часть проблем , связанных с описанными ранее файлами D M P, со временем станут актуальными и для файлов Data Pump. Эти файл ы представляют собой межплатформен ные (переносимые) двоичные файлы, которые содержат мета­ данные (хранящиеся не в операторах C REAT E /ALT E R , а в ХМ L-коде) и возможно данные. Для нас, как конечных пользователей инструментов, важно то, что в ка­ честве структуры представления метаданных при меняется XM L. Утилиты I M P D P и E X P D P обладают рядом сложных возможностей фил ьтрации и преобразования, ко­ торых н икогда ранее не было в старых утилитах l mport/Export. Ч астично это обус­ ловлено использованием языка XM L и тем , что оператор создан ия таблицы хранит­ ся не в форме CREAT E TAB L E , а в виде документа разметки . Это позволяет легко реал изовать запрос типа " замен ить все ссылки на табличное пространство FOO ссылками на табли чное пространство BAR " . Когда метаданные хранились в файле D M P в виде операторов C REAT E /ALT E R , для решен ия этой задачи утилите l mport приходилось подробно анализировать каждый SQ L-oпepaтop перед его выполнени­ ем (т. е . заниматься несвойствен ной ей задачей ) . Тем не менее , утилите I M P D P для этого достаточно применить простую ХМ L-трансформацию - если строка FOO от­ носится к табличному пространству, то она должна быть заключена в дескрипторы < TABLES PACE> FOO< /TABL E S PACE > (ил и представлена как-то иначе) . Использование XM L позволило утилитам EX P D P и I M P D P оставить старые ути­ л иты l mport и Export дале ко позади с точки зре н ия предлагаемых возможностей. В главе 15 мы подробно проанализируем основные особенности этих инструментов. А пока давайте посмотрим, как применять формат Data Pump для быстрого извле­ чения определенных данных из базы дан н ых А и их перемещения в базу данных В. Здесь мы будем использовать " внешнюю таблицу в обратном направлени и " . Внешние табл и цы , впервые появившиеся в Oracle9i Release l , предоставили воз­ можность считывать плоские файлы ( простые текстовые файлы) так, как если бы они был и табли цами базы данных. Это позволяет полностью задействовать для их обработки возможности , предлагаемые языком SQL. Они допускали только чтение и был и п редназначены для загрузки данных из внешнего мира в Oracle . Внешние таблицы в Oracle l Og Release l и последующих версиях поддержи вают и другое на­ правление: их можно применять для извлечения данн ых из базы данных в формате Data Pump с целью облегчения переноса дан ных на другой компьютер ил и на дру­ гую платформу. П еред началом упражнения понадобится создать объект D I RECTORY, который указывает Oracle место выгрузки данных: Файлы 201 EODA@ORA12CR1> create or rep1ace directory tmp a s ' / tmp ' ; Directory created . Ка талог создан . EODA@ORA12CR1> create t а Ы е a ll_obj ects_unload 2 organi zation external 3 ( type oracle_datapump 4 de fault di rectory ТМР 5 location ( ' al l obj ects . dat ' б 7 as 8 select * from al l_ob j ects 9 1 ТаЫе created . И это буквально все, что необходимо: в каталоге /tmp мы и меем файл по имени a l l ob j e c t s . dat , в котором находится содержимое запроса s e l e ct * f r om a l l obj ect s . Теперь можно заглянуть в него: EODA@ORA12CR1 > ! s trings / tmp/al lobj ects . dat " EODA" . "U " х 8 6 6 4 / Li nux 2 . 4 . хх AL3 2UTF8 12 . 0 0 . 0 0 . 0 0 . 0 0 001 : 001 : 000001 : 000001 i<?xml ve rs ion= " 1 . 0 " ? > <ROWSET> <ROW> <STRМTAВLE Т> 1 head Это только заголовок, или верхняя часть, файла. Теперь с помощью двоичного режима передачи FfP (аналогично файлам D M P) этот файл можно переместить на любую другую платформу, где установлена версия Oracle 1 2с, после чего вьщать опе­ ратор CREAT E D I RECTORY (чтобы сообщить базе данн ых, где расположен файл) и оператор CREATE TABLE следующего вида: create table t ( OWNER OBJECT NАМЕ SUBOBJECT NАМЕ OBJECT I D DATA OBJECT I D OBJECT ТУРЕ CREATED LAST DDL Т I МЕ Т I МЕSТАМР STATUS TEMPORARY GENERATED SECONDARY VARCНAR2 ( 3 О ) , VARCНAR2 ( 3 О ) , VARCНAR2 ( 3 0 ) , NUМBER , NUMBER, VARCНAR2 ( 1 9 ) , DAT E , DAT E , VARCНAR2 ( 1 9 ) , VARCНAR2 ( 7 ) , VARCНAR2 ( 1 ) , VARCHAR2 ( 1 ) , VARCНAR2 ( 1 ) organi zation external ( type oracle_datapump de fault directory ТМР location ( ' al l obj ects . dat ' ); 202 Глава 3 Теперь все готово для чтения выгружен н ых данн ых, используя SQL-кoд непос­ редствен но. В этом и заключается основное преимущества файлового формата Data Pump: он позволяет немедленно перемешать данные из одной системы в другую посредством сети " на своих двоих" по мере необходимости . Вспомните об этом, когда в следующий раз потребуется захватить подм ножество дан ных домой на вы­ ходные дни для проведен ия тестирования . Даже есл и кодировка баз данных отличается (в рассмотрен ном примере это было не так) , теперь благодаря файловому формату Data Pump имеется возможность рас­ познавания разных символьных наборов, а также их обработки . Преобразование с и м вольн ых наборов может вы полняться на лету, когда это нужно, обеспечи вая " корректность" представления данных для каждой базы дан ных. М ы вернемся к рассмотрен и ю файлового формата Data Pump в главе 1 5, но на­ стоящий раздел должен был содействовать в общем пониман и и содержимого фай­ лов этого формата. Плос кие ф айл ы Плоские файлы существуют с момента зарождения электронной обработки дан ­ н ых. М ы встречаемся с ними буквально на каждом шагу. Например, описанный ра­ нее сигнальн ы й журнал является плоским файлом . Я считаю довольно точным следующее определение плоского файла. Электронная запись, лишенная всех специфичных для приложен ия (программ ы) форматов . Это позволяет перемещать элементы данных в другие приложения с целью манипулирования ими . Такой режим отбрасывания форматов элект ­ ронных данных предотвращает потерю данных из -за устаревания оборудова­ ния и патентованного программнаго обеспечения . Плоски й файл представляет собой просто файл , в котором каждая "строка" яв­ ляется " записью" и содержит определенный текст, как правило, разделенный сим­ волами запятой или вертикальной черты . Плоские файлы легко читаются в Orac1e л ибо с помощью унаследованной утилиты загрузки данных SQLLDR, либо с приме­ нением внешних таблиц. Все эти вопросы будут подробно обсуждаться в главе 1 5 (вне ш н ие таблицы также рассматри ваются в главе 1 0) . Тем не менее, создавать плоские файлы в Orac1e не настолько легко . По ряду причин не существует какого-то простого инструмента командной строки для эк­ спорта информации в плоский файл . И нструменты вроде АРЕХ, SQL Deve1oper и Enterprise Manager упрощают этот процесс, но официальные средства командной строки , которые можно было бы легко использовать в сценариях или как-то по-дру­ гому для выполнения этой операции , отсутствуют. Одна из прич и н , по которой я реш ил упомянуть плоские файлы в этой главе , связана со стремлением предложить набор инструментов, способных создавать про­ стые плоские файль1 . За долгие годы практи ки я разработал три метода решения этой задачи , каждый и з которых соответствует своей ситуаци и . Для выполнения работы первая утилита применяет комбинацию PL/SQ L и пакета UTL_FILE с ди­ намическим SQL. При небольш их объемах дан н ых (сотни или тысячи строк) она Файл ы 203 обеспечивает достаточ ную гибкость и скорость. Однако эта утилита должна созда­ вать свои файлы на комп ьютере сервера базы данных, что временами нежелательно. Для таких ситуаций я написал утилиту SQL* Pius, которая создает плоские файлы на компьютере, где фун кционирует SQL* Pius. П оскольку SQL* Pius может подключать­ ся к серверу Oracle в любой точ ке сети, это предоставляет возможность выгружать в плоский файл любые дан н ые из любой базы данных в сети . Наконец, в случаях, когда требуется максимальная скорость, н ичего друтого кроме написания програм­ мы на языке С не остается (по моему мнению). Таким образом , я разработал на Pro*C утилиту командной строки для выгрузки дан ных в плоские файль1 . Все три утилиты свободно доступны по адресу h t t p : 1 / t k y t e . Ы o g s p o t . c om / 2 0 0 9 / 1 0 / httpas kt omo r a c l e c omt kyt e f l a t . html , и там же будут появляться любые новые инструменты, созданные для выгрузки в плоские файль1 . Р ез ю ме В этой главе мы исследовали важные типы файлов, используемые базой данных Oracle - от небольших файлов параметров (без которых даже не удастся приступ ить к работе) до крайне важных журналов повторения и файлов дан н ых. Мы рассмот­ рели структуры хранения дан н ых Orac\e , нач и н ая с табличных пространств и сег­ ментов и заканчивая экстентами и блоками базы данных, представляющим и собой наименьшую единицу хранения . Мы кратко объяснили работу контрольных точек и даже забежали немного наперед, указав действия , которые выполняют физические процессы или потоки Oracle. Мы также раскрыли многие допол нительные файло­ вые типы, такие как файлы паролей , файлы отслеживания изменени й , файлы Data Pump и т.д. Теперь вы готовы приступить к исследовани ю структур памяти Oracle в следующей главе. ГЛ А В А 4 Структур ы п амят и В этой главе мы рассмотрим три основные структуры памяти Oracle. • Тhобальная область системы (System Global Area - SGA). Это большой сов­ местно используемый сегмент памяти, к которому в тот или и ной момент вре­ мени будут обращаться практически все процессы Oracle . • Тhобальная область процесса (или проrраммы) (Process (Prorgam) Global Area ­ PGA). Это закрытая область отдельного процесса или потока; из других п ро­ цессов или потоков она не доступна. • Глобальная область пользователя (User Global Area - UGA). Эта область па­ мяти связана с конкретным сеансом . Она располагается л ибо в области SGA (если подключение к базе данных выполнено посредством разделяемого сер­ вера) , либо в области PGA (если подключение к базе данных осуществлено че­ рез выделенный сервер). На заметку! В ранних версиях Oracle разделяемый сервер назы вался многопоточным сер­ вером (Multi- Threaded Server - MTS) . В этой книге мы будем всегда использовать тер м и н "разделяемый сервер" . При обсуждении управления памятью в Oracle нам предстоит исследовать пять режимов. • Автоматическое управление памятью (automatic memory management - АММ ) , применяемое к областям SGA и PGA, доступно тол ько в Oracle l l g и после­ дующих версиях. Администратор базы дан н ых устанавливает всего лишь оди н параметр MEMORY_TARGET , чтобы позвол ить базе дан н ых определить, каким образом назначать размеры всем областям памяти . • Автоматическое управление разделяемой памятью (automatic shared memory management - AS M M ) , используемое в отношении к SGA. Адми н истратор базы дан ных устанавливает целевой размер для области SGA (через S GA_TARGET ) . • Ручное управление разделяемой памятью, применяемое к SGA. Администратор базы данных вручную устанавли вает размеры и ндивидуальных областей памя­ ти SGA (посредством DB_CACHE_S I ZE , SНARED_POOL_S I Z E и т.д.). • Автоматическое управление памятью PGA, используемое в отношении к PGA. Администратор базы дан ных устанавливает целевой размер для области PGA (через PGA_AGGREGATE_TARGET ) . 206 • Глава 4 Ручное управление памятью PGA, применяемое к PGA. Администратор базы дан ных вручную устан авли вает размеры и нди видуальных областе й памяти PGA (посредством S ORT_AREA_S I Z E , HAS H_AREA_S I Z E и т.д. ) . В Oracle на­ стоятельно рекомендуют не пользоваться эти м методом, но мы обсудим его, чтобы предоставить фундамент для пони мания других кон цепций управления памятью. Какой метод управления памятью из перечисленных выше должен применяться? В идеальной среде все испол ьзовали бы автоматическое управление памятью, не так ли? Достаточно установить оди н параметр (MEMORY_TARGET ) и все готово. Однако реал ьн ы й мир оказывается не настолько черно-белым. Временами существуют та­ кие аспекты среды , когда вы лучше знаете, как должны выглядеть целевые размеры областей памяти , поэтому применяете оди н из менее автоматизированных методов управления памятью. Цель настоящей главы заключается в том , чтобы помочь вам освоить все аспекты памяти Oracle и прин имать обоснованные решения относитель­ но того, каким образом включать управление памятью. - На заметку! Некоторые конфигураци и операционных систем несовместимы с автоматичес­ ким уп равлением памятью ( например, Linux H ugePages ) . За подробными сведениями по этому поводу обращайтесь к справочному руководству администратора баз данных Oracle для операционных систем , основанных на Linux и U N IX. Мы займемся исследованием всех упомянутых методов после того, как обсудим управление памятью PGA и U GA, сначала руч ное, а затем автоматическое . П осле этого мы перейдем к области SGA, снова рассмотрев методы ручного и автомати­ ческого управления памятью. Закончим мы тем , что взглянем на то, каким образом управлять памятью SGA и PGA, используя еди нственный параметр. Глобальная область п роцесса и глобальная область пол ьзователя Область PGA - это фрагмент п амяти , специфичный для процесса. Другими сло­ вам и , это п амять, связан ная с отдельным процессом или потоком операционной системы . Такая память не является доступной любому другому процессу или потоку в системе. Обыч но она выделяется посредством вызовов функции С под названием ma l l o c ( ) или memmap ( ) а ее объем увеличиваться (и уменьшаться ) во время вы­ пол нения . Область PGA н икогда не выделяется в области SGA базы данных Oracle ; она всегда распределяется процессом или потоком только лакальна Р в PGA оз­ начает process (процесс) или program (программа) , и это не разделяемая область. Область UGA, по сути , представляет состоян ие процесса. Сеанс должен всегда иметь доступ к этой памяти. Расположение U GA зависит от способа подключения к базе данных Oracle. Если подключение было выполнено через разделяемый сервер, область UGA должна храниться в структуре памяти , к которой имеет доступ каждый процесс разделяемого сервера - областью подобного рода будет SGA. Таким обра­ зом , сеансом может пользоваться л юбой из разделяемых серверов, поскольку любой из н их может сч итывать и записывать данные сеанса. С другой сторон ы , в случае применения подключен ия посредством выделенного сервера потребность в универ, - Структуры nамяти 207 сальном доступе к состоя н и ю сеанса отпадает, и область UGA становится практи­ чески синонимом PGA; фактически она будет содержаться внутри области PGA вы­ деленного сервера. Если вы просмотрите статистическую информацию о системе, то заметите , что в режиме выделенного сервера область UGA хранится в области PGA выделенного сервера (размер PGA будет больше или равен размеру области UGA; размер PGA будет включать также и размер UGA) . Итак, область PGA содержит память процесса и может включать область U GA. Остальные области памяти PGA в основном служат дЛЯ выполнения сортировки внутри памяти , слия ния битовых и ндексов и хеширования . Можно без опаски ут­ верждать, что наряду с UGA эти процессы вносят наибольш и й вклад в формирова­ ние области PGA. Начиная с версии Oracle9i Release 1 , существуют два способа управления этой отличной от UGA памятью в области PGA. l . Ручное управление п амятью PGA, при котором вы указы ваете Oracle, какой объ­ ем памяти можно задействовать дЛЯ выполнения сортировки и хеширован ия в любой момент, когда это необходимо в конкретном процессе. 2. Автоматическое управление памятью PGA , при котором вы указы ваете базе данных Oracle, какой объем памяти она должна пытаться испол ьзовать на уровне всей системы. Начиная с версии Oracle l lg Release 1 , автоматическое управление памятью PGA может быть реализовано с применением одного из двух приемов. 1 . Установка параметра и н ициал изации PGA_AGGREGAT E _ TARGET и сообщение Oracle объема памяти PGA, который следует попытаться использовать на уров­ не экзем пляра. 2. Установка параметра ини циализации MEMORY TARGET и уведомление Oracle об объеме общей памяти , которую экземпляр базы данных должен применять дЛЯ SGA и PGA; размер PGA будет выведен из этого параметра самим экземпляром. _ Способы выделения и использован ия памяти в каждом из этих случаев заметно отличаются , так что давайте обсудим их по очереди . На заметку! Следует отметить, что в среде Oracle9i при использован и и подключения пос­ редством разделяемого сервера можно при менять только руч ное управление памятью PGA. Такое ограничение было устранено в Oracle 1 0g Release 1 (и последующих версиях) . Начиная с этого выпуска, с подключениями через разделяемый сервер можно использо­ вать либо автоматическое, либо руч ное управление памятью PGA. Если вы работаете с Oracle 1 0g Release 1 (и последующим и версиями), то должны применять автоматическое управление памятью PGA. Режимы управле ния памятью PGA контролируются п араметром и н ициал и за­ ции базы дан ных WORКAREA_S I Z E POL I C Y и могут изменяться на уровне сеанса. В Oracle9i Release 2 и последующих версиях этот параметр и н ициал изации по умол­ чанию получает значение AUTO, что устанавливает автоматическое управление памя­ тью PGA, когда это возможно. В Oracle9i Release 1 его стандартным значением было МANUAL (вручную) . В последующих разделах мы поочередно рассмотрим каждый из этих подходов. 208 Глава 4 Ручное управление памятью PGA П ри ручном управлен и и памятью PGA наибольшее влия ние на размер области PGA без учета объема памяти , выделенного сеансом для табли ц P L/SQ L и других переменных, будут оказывать следующие параметры. • • SORT_AREA_S I ZE. Общий объем памяти, которы й будет использоваться для сор­ тировки информации перед ее сбросом на диск (с применением дискового про­ странства во временном табл ичном пространстве, назначен ном пользователю) . S ORT_AREA_RETA I N E D_S I Z E . Объем памяти , которы й будет использоваться для хранения отсортированных данных после завершения сортировки . То есть, если значением параметра S ORT _AREA_s I Z E является 5 1 2 Кбайт, а параметра S ORT _AREA_RETA I N E D_ S I Z E 256 Кбайт, то процесс сервера задействует до 5 1 2 Кбайт памяти для сортировки данн ых во время начальной обработки за­ проса. По завершении сортировки область сортировки будет "сокращена" до 256 Кбайт, а любые данные сортировки , которые не уместились в этот объем, будут записаны во временное табличное пространство. - • HASH_AREA_S I Z E . Объем памяти , который процесс сервера может применять для хранения хеш -табл и ц . Эти структуры испол ьзуются во время хе ш-со­ еди нени й , обычно при соединении крупных наборов данных друг с другом. Меньший из двух н аборов будет хеш ироваться в памяти , а все дан ные, не уместившиеся в хеш -область памяти, будут сохранены во временных таблич­ н ых пространствах по ключу соединения . Описан ные п араметры управля ют объемом памяти , которы й Огас1е будет ис­ пользовать для выполнения сортировки или хеширования дан ных в памяти перед применением времен ного табличного пространства на диске , и размером той час­ ти этого сегмента памяти , которая будет сохранена после завершен ия сортировки . В общем случае память с объемом, вычисленным как SORT_AREA_S I ZE-SORT_AREA_ RETA I N E D_S I Z E , выделится из области PGA, а память с объемом , заданным пара­ метром SORT _AREA_RETAINED_S I Z E , будет находиться в области UGA. Сведения о текущем использовании памяти PGA и UGA можно получать и отслеживать разме­ ры этих областей , запрашивая специальные V$ -представления Orac1e, которые также называются динамическими представлениями производительности. Н апример, давайте проведем небольшой тест, при котором один сеанс будет сортировать бол ьшой объем данн ых, а из второго сеанса мы будем отслеживать ин­ формацию об использовани и памяти UGA/PGA в первом сеансе. Чтобы решить эту задачу предсказуемым образом , м ы создадим копию таблицы ALL_OBJECT S , содер­ жащей около 72 000 строк безо всяких и ндексов (таким образом, мы знаем, что в случае применен ия конструкци и ORDER ВУ в этой таблице будет происходить сор­ тировка): EODA@ORA12CR1> create taЬle t a s se lect * from a l l_obj ect s ; ТаЬlе created . Та блица создана . EODA@ORA12CR1> ехес dЬms_s tats . gathe r_taЬle_stats ( use r , ' Т ' ) ; PL/SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно завершена . Стру ктуры n амяти 209 Чтобы предотвратить л юбые побоч ные эффекты н ачального полного разбора запросов, мы запустим приведенный н иже сценар и й , но пока проигнорируем его вывод. М ы выполним его еще раз в новом сеансе, чтобы посмотреть на результаты использования памяти в управляемой среде . М ы будем применять размеры области сортировки 64 Кбайт, 1 Мбайт и 1 Гбайт по очереди , поэтому сохраним этот сце­ нарий как run_que r y . s q l ( в сценар и и предполагается , что именем пол ьзователя и паролем являются e oda / f o o , так что измените их в соответствие с имеющейся средой): connect eoda / foo set se rve routput off set echo on co1umn s id new va1 S I D se1ect s id from v$mystat where rownum = 1 ; a1ter sess ion set wor karea_s i ze_po 1 i cy=manua1 ; a1 ter s e s s ion set sort_a rea_s i ze = & 1 ; prompt run @ re set_stat & S I D and @watch stat i n anothe r s e s s ion here ! pause set termout off se1ect * from t orde r Ьу 1, 2, 3, 4 ; set termout on prompt run @watch_stat in anothe r s e s s ion here ! pause А теперь запустим готовый сценарий: @ run_query 6 5 5 3 6 @ run_query 1 0 4 8 5 7 6 @run_query 1 0 7 37 4 1 8 2 0 Пока что н е обращайте вн имания н а вывод; м ы просто "разогреваем" разделяе­ мый пул и делаем все "однородны м " . Н а заметку! При обработке SQL-зaпpoca в базе данных сначала должен быть п роизведен его разбор. Различают разборы двух типов. Первый - это полный разбор (hard parse) , вы­ полняемый при первом разборе запроса экзем пляром базы данных и включающий в себя генерацию плана запроса и оптимизацию. Второй тип - частичный разбор (soft parse) , в ходе которого могут быть пропущены многие действия, обязательные во время полного разбора, поскольку при этом могут быть задействованы результаты работы , проделан­ ной в течение полного разбора. Мы осуществляем полный разбор приведенных запросов, чтобы в следующем разделе не пришлось оценивать объем работы , которая выполнена данной операцией. Прежде чем продолжить, я рекомендую выйти из сеанса SQL* Pius и снова войти , чтобы получить согласованную среду, или среду, в которой никакая работа пока еще не делалась. Теперь нам нужна возможность измерения показателей памяти сеанса, выполняющего круп н ые запросы ORDER ВУ из второго отдельного сеанса. Если м ы будем использовать тот же самый сеанс, то запрос, предназначен н ы й дл я просмотра объема памяти, задействованной под сортировку, сам может повл иять на и нтересу­ ющие нас показатели . Для замера памяти из второго сеанса применяется небольшой разработанн ы й мною сценарий SQ L* Pius. В действительности это пара сценариев: 210 Глава 4 вы узнаете, когда запускать их, из run_que r y . s q l . Сценарий, выполняющий сброс небольшой таблицы и установку переменной SQL* Plus в идентификатор S I D, кото­ рый требуется отслеживать, называется r e s et_stat . s q l : drop taЬl e s e s s_s tat s ; create taЬle s e s s stats ( nате va rchar2 ( 6 4 ) , va lue numЬer , di f f numЬer ) ; va riaЬ l e s i d numЬer ехес : s id : = & 1 Н а заметку! П еред испол ьзованием этого сценария ( ил и любого сценария , если уж на то пошло) удостоверьтесь в наличии понимания того, что он делает. Сценарий удаляет и вос­ создает табли цу по имени S E S S_STAT S . Если в вашей схеме уже и меется такая таблица, вам п ридется выбрать для нее другое имя! Второй сценар и й называется wat ch_ s t a t . sql, и в этом учебном примере в нем используется SQL-oпepaтop MERGE, так что можно изначально вставить статистичес­ кие значения для сеанса, а потом возвратиться и обновить их - без необходимости в отдельном сценар и и INS ERT / U P DATE: merge into s e s s stats us i ng ( s e l ect a . name , b . value from v$statnaтe а, v $ s e s stat Ь where a . s t a t i s t i c # = b . s t a t i s t i c # and b . sid = : sid and ( a . name like 1 %ga % 1 or а . nаше like 1 %direct temp% 1 ) curr stats on ( s e s s_stat s . name = curr_s tat s . name ) when matched then update set di f f = curr_s tats . val ue - s e s s stats . val u e , val ue = c u r r s tats . value when not matched then insert ( nате , va l ue , di f f ) values ( cur r_stats . name , curr_stats . value , null ) 1 s e lect name , case when nате l i ke 1 % ga % 1 then round ( val ue / 1 0 2 4 , 0 ) e l s e va lue end kЬytes_wr ites , case when nате l i ke 1 % ga % 1 then round ( di f f / 1 0 2 4 , 0 ) e l s e va lue end di f f_kЬytes_writes from s e s s stats order Ьу name ; Структуры памяти 21 1 Я акцентирую внимание на формул ировке " в этом учебном примере " , т. к. стро­ ки, выделенные полужирным, являются именами и нтересующих нас статистических показателей, которые изменяются от примера к примеру. В этом конкретном слу­ чае нас интересует все, содержащее в имени ga (pga и uga ) , л ибо все, включающее d i r e c t t ernp , что в Oracle ! Og и последующих версиях покажет прямые чтения и записи во временное пространство (количество операций ввода-вывода при чте н ии и записи ) . Н а заметку! В Oracle9i nрямой ввод-вывод в о временное табличное пространство подобн ы м образом не помечался, поэтому должна nрименяться конструкция WHERE, включающая в себя and ( а . nате l i ke ' % ga % ' or а . nате l i ke ' % phys i c a l % d i r e c t % ' ) . Когда этот сценари й w а t c h s t а t s q 1 в ы п ол н я ется в командной строке SQL* Plus, мы видим список статистических показателей, касающихся памяти PGA и UGA для данного сеанса, а также ввода-вывода во временную область. Если те­ перь запустить в сеансе сценарий @ run_ que r y 6 5 5 3 6 , появится вывод, подобн ы й следующему: . EODA@ORA12CR1> @ run_query 6 5 5 3 6 Connected . Подклю чено . EODA@ORA1 2 CR1 > set s erve routput o f f EODA@ ORA1 2CR1 > set echo o n EODA@ORA12CR1> co1umn s i d n ew va l S I D EODA@ORA12CR1> select s i d froт v$тys tat wher e rownum = 1 ; SID 23 EODA@ORA1 2 CR1 > a1ter s e s s ion s e t workarea s i ze_pol i cy=manual ; Session alte red . Сеанс изменен . EODA@ORA1 2 CR1 > alter s e s s ion set sort_area_s i z e = & 1 ; old 1 : al ter s e s s i on set sort area si z e = & 1 new 1 : al ter s e s s ion set sort a rea s i z e = 6 5 5 3 6 Session altered . Сеанс изменен . EODA@ORA12CR1> proтpt run @reset stat & S I D and @watch stat in another sess ion here ! run @ reset stat 2 3 and @watch s ta t in another s e s s ion here ! EODA@ORA12CR1> pause Здесь мы можем видеть идентификатор S I D этого нового сеанса (23 ) . Вдобавок мы устанавли ваем ручной режим управления памятью PGA и значение SORT _AREA_ S I ZE в 6 5 5 3 6 (64 Кбайт) . Далее сценарий предлагает запустить два других сценария в другом сеансе, что мы и сделаем : EODA@ ORA1 2CR1 > @ reset s tat 2 3 ТаЬlе dropped . Та блица удалена . 21 2 Глава 4 ТаЬlе created . Та блица создана . PL/ SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно завершена . EODA@ ORA12CR1> @watch stat б rows me rged . б строк объединено . NАМЕ phys ical reads direct temporary taЫespace physical writes direct temporary taЬlespace s e s s ion pga memory s e s s ion p ga memory max s e s s i on uga memor y s e s s i on uga memory max KBYTES WRITES DIFF- КВУТЕS -WRITES о о о о 87б 87б 334 334 о о о о б rows s e lected . б строк выбрано . На заметку! Сценарий watch _s t a t . s q l должен запускаться в том же сеансе, что и reset _ s t a t . s q l ; сценарий r e s e t _ s t a t . sql устанавливает переменную привязки : s i d, необ­ ходимую для оператора MERGE . В качестве альтернативы можно выполнить е х е с : sid : <s id>, где < s id> - идентификатор SID, полученный при тестировани и . = Таким образом , как видите , д о начала работы м ы располагаем около 3 3 4 Кбайт данных в области U GA и 876 Кбайт данных в области PGA. Первый возникающий вопрос: сколько памяти мы задействуем из областей PGA и UGA? Другим и слова­ м и , мы используем 3 34 + 876 Кбайт памяти или какой-то другой объем? Это слож­ н ы й вопрос, на который невозможно ответить, не зная, был ли наблюдаемый се­ анс с S I D 23 подключен к базе данн ых посредством выделенного или разделяемого сервера. Но, даже располагая этой и нформацией , ответить на поставленный вопрос может быть нелегко. В режиме выделенного сервера область UGA полностью содер­ жится внутри области PGA, и в этом случае наш процесс ил и поток потреблял бы 876 Кбайт памяти . В режиме разделяемого сервера область U GA выделяется из области SGA, а область PGA распределена в памяти операционной систем ы , которая является за­ крытой для процесса разделяемого сервера. Итак, в режиме разделяемого сервера в момент получения последне й строки приведеи ного запроса процесс разделяемого сервера может эксплуатироваться кем-то еще. Эта область PGA больше не является " нашей " , поэтому формал ьно мы используем 3 34 Кбайт памяти (за исключением момента действительного запуска запроса, когда м ы применяем 1 2 1 0 Кбайт памя­ ти из объединенных областей PGA и U GA) . В этом случае я использую выделен­ н ы й сервер (иначе было бы невозможно точно выполн ить тест) и конеч н ы й объем 876 Кбайт памяти из объединенных областей PGA и UGA. Давайте теперь запус­ тим первый крупн ы й запрос в сеансе с идентификатором 23, в котором применя­ ется ручное управление памятью PGA в режиме выделенного сервера. М ы просто должны возвратиться в сеанс, где был запушен сценари й run _que r y . s q l и нажать < Ente r>, чтобы начать выполнение запроса. Структуры nамят и 213 Н а заметку! Поскольку м ы н е устанавли вали параметр SORT _AREA_ RETA I N E D s r Z E , его _ отображаемое значение будет равно нулю, но действительно используемое значение бу­ дет совпадать со значением SORT_AREA_S I Z E . EODA@ORA12CR1> s e t te rrnout o f f EODA@ORA12CR1> prompt run @watch_s tat in anothe r s e s s 1on here ! run @watch stat in anothe r s e s s ion here ! EODA@ORA12CR1> pause Точка, где вы видите s e t t e rmout o f f это место, где запускается круп н ы й запрос; здесь мы указываем SQL* Pius о необходимости выполнить запрос, ничего не выводя на экран (вывод свыше 70 000 строк займет немало времени). Если мы снова запустим сценари й watch_ s t a t . s q l во втором сеансе, то увидим примерно такой вывод: - EODA@ORA12CR1> @watch stat 6 rows me rged . б строк объединено . NАМЕ phys ica1 reads direct temporary taЬlespace phys ica1 writes di rect temporary taЫespace sess ion pga memory sess ion pga memory max sess ion uga memo ry sess ion uga memo ry max 6 rows selected . б строк выбрано . KBYTES WRITES DIFF КВУТЕS WRITES 3000 3000 1196 12 60 654 718 3000 3000 320 384 320 384 Обратите внимание, что н а этот раз значения s e s s i o n ххх memo r y и s e s s i o n ххх memo ry max не совпадают. Значение s e s s i on ххх memo r y представляет объем памяти , применяемый в текущий момент време н и . Значение s e s s i on х х х memo ry m a x отражает максимальный объем памяти , ис­ пользованный в ходе сеанса при обработке запроса. На заметку! В этих примерах не стоит ожидать, что вы получите в точности такие же цифр ы , как приведенные в ы ш е . На объем задействованной памяти влияют м ногие аспекты , такие как версия Oracle, операционная система, ее функциональные средства и возможности , объем данных, помещенных в табли цу т , и т.д. Вам следует ожидать вариаций в объемах памяти , однако общая картина должна быть аналогичной . Как видите , объем используемой памяти возрос - мы вы пол н или определен­ ную сортировку данных. Объем памяти UGA увеличился с 334 Кбайт до 7 1 8 Кбайт (максимальная величина) во время обработки запроса. Чтобы выполнить запрос и сортировку, СУБД Oracle выделила область сортировки для нашего сеанса. Кроме того, объем памяти PGA увеличился с 876 Кбайт до 1 1 96 Кбайт. Вдобавок можно заметить, что было сделано 3000 операций записи и чтения в и из временного про­ странства (т.к. сортируемые данные не уместились в 64 Кбайт - значение параметра SORT_AREA_S I Z E ) . 214 Глава 4 К моменту завершения запроса и исчерпания результирующего набора объем PGA также несколько уме ньш ился (следует отметить, что в Oracle8i и предшеству­ ющих версиях объем PGA вообще не уменьшился б ы ; эта особенность появилась в Oracle9i и сохранилась в последующих версиях) . Давайте повтори м эту же операцию, но изменим размер SORT _AREA_ s I Z E , уве­ личив его до l М байт. Мы выйдем из наблюдаемого сеанса, снова войдем в него и выпол н и м указания по увеличению SORT_AREA_S I Z E до l М байт. П омните , что в другом сеансе , из которого осуществляется мониторинг, понадобится снова запус­ тить сценар и й r e s e t _ s t a t . s q l . Поскольку начальные значения остаются посто­ янными (вывод после первого запуска w a t ch_s t a t . s q l должен быть таким же в новом сеансе) , я их не повторяю, а привожу только конечный результат: NАМЕ phys ical reads di rect temporary taЫespace physical writes di rect temporary taЬlespace se s s ion pga memory s e s s ion pga memo ry max s e s s ion uga memo ry s e s s ion uga memory max 6 rows s e lected . б строк выбрано . KBYTES WRI TES DI FF КВУТЕS WRITES - - 1043 1043 320 1856 384 1422 1043 1043 1196 2732 718 1756 Как видите , н а этот раз в о время обработки запроса объем памяти UGA зна­ чител ьно возрос. Он временно увеличился почти до 1 700 Кбайт (немного больше l М байт - значен ия параметра S ORT _AREA_ s I Z E ) , но при этом количество физи­ ческих операций ввода-вывода, которые пришлось выполнить для сортировки дан­ ных, существенно уменьшилось (в случае работы с памятью большего объема обмен данными с диском происходит реже ) . Мы можем также избежать многопроходной сортировки - ситуации , когда количество небольших наборов отсортированных данных, которые требуется объединить вместе, настолько велико, что СУБД Oracle вынуждена записывать данные во временное пространство более одного раза. Теперь давайте перейдем к пределу и используем для SORT_AREA_ S I Z E значение 1 Гбайт: NАМЕ physical reads di rect temporary taЬlespace physical writes di rect temporary taЬlespace s e s s ion pga memo ry s e s s ion pga memo ry max s e s s ion uga memory s e s s ion uga memo ry max 6 rows s e l ected . б строк выбрано . KBYTES WRI TES DI FF КВУТЕS WRITES - - о о о о 1 132 1 1 372 654 10631 256 1 0 4 96 320 10296 Легко заметить, что хотя м ы разреш ил и S O RT_AREA_S I Z E прин имать величи­ ны вплоть до l Гбайт памяти , в действительности было использовано только около l O Мбайт. Это говорит о том , что параметр S ORT_AREA_S I Z E определяет верхнюю грани цу, а не стандартное значение, и представляет собой только размер выделенной памяти. Кроме того, мы снова выполнили только одну сортировку, но на этот раз она происходила полностью в памяти; никакое временное пространство на диске не бьuю задействовано, о чем свидетельствует отсутствие операций физического ввода-вывода. Структуры nамят и 21 5 При запуске того же самого теста в средах с разными версиям и Orac1e или даже с другими операционными системами вы можете столкнуться с отл ичающимся по­ ведением, а значения во всех случаях будут несколько разн иться от приведе н н ых. Но общее поведение базы дан ных должно быть таким же . Другим и словами, при увеличении размера области сортировки и выполнении крупн ых сортировок объ­ ем памяти , используемой сеансом, будет расти. Может оказаться , что объем памя ­ ти PGA увеличивается и уменьшается или же остается постоянным в о времен и , как только что было показано. Н апример, я уверен , что есл и вы в ыполните предыду­ щий тест в среде Orac1e8i, то заметите, что объем памяти PGA не уменьш ился до первоначального (т.е. во всех случаях значение S E S S I ON_PGA_MEMORY равно значе­ нию S E S S I ON_PGA_MEMORY_МAX) . Этого и следовало ожидать, поскольку в выпус­ ках Orac1e8i память PGA управляется как куча и формируется вызовами ma l l oc ( ) . В Orac1e9i и последующих выпусках новые методы присоеди няют и освобождают рабочие области по мере необходимости с применением фун кци й выделен ия памя­ ти , специфичных для операционной системы. Н иже перечислены важные моменты , о которых необходимо помнить во время использования параметров * _AREA_s I Z E . • Эти параметры управляют максимальным объемом памяти , потребляемой опе­ рацией SORT, НАSН ИЛ И В I ТМАР MERGE. • В рамках одиночного запроса может выпол няться м ножество операций , ко­ торые используют эту память, и может быть создано несколько областей хе­ ш ирования/сортировки . Помните , что одновременно может быть открыто много курсоров, каждый из которых предъявляет собствен н ые требования к SORT _AREA_ RETAI N E D . Таким образом, если вы установите размер области сортировки в 1 0 М байт, то сможете применять в сеансе 1 0 , 1 00, 1 000 или более мегабайтов ОЗУ. Эти значения не явля ются предельными значениями сеанса, а определяют лимиты для оди ночной операции; внутри сеанса могут вы пол­ няться многочисленные операци и сортировки в одном запросе или откры вать­ ся много запросов, требующих одной сортировки . • Память для этих областей выделяется "по мере необходимости " . Есл и вы уста­ новите размер области сортировки в 1 Гбайт, как было сделано в рассмотрен­ ном примере, то это вовсе не означает, что вы распределяете l Гбайт ОЗУ. Это значит лишь то, что вы предоставляете данному процессу O rac1e право выде­ ления такого объема памяти для выполнения операци и сортировки/хеш иро­ вания. Автоматическое управление памятью PGA Н ачи ная с Orac1e9i Re1ease 1 , был введен новый способ управле ния п амятью PGA, исключающи й использование параметров SORT _AREA_ s I Z E , В I ТМАР_MERGE_ AREA_S I Z E и HAS H_AREA_S I Z E . Он был предназначен для решения следующих проблем . • Простота применения. С пособ правильной установки параметров * _AREA_s I ZE вызывал немалую путани цу. Вдобавок возни кали сложности с тем , как эти параметры в действител ьности работал и , и каким образом распределялась память. 21 6 • Глава 4 Ручное управление памятью было методом " один размер на все случаи " . Обычно по мере роста числа пользователей, одновременно выполняющих по­ хожие приложения в отноше н и и базы данных, объем памяти , задействован­ ной под сортировку и хеширование, увеличивалея по линейному закону. Если 1 О параллельна работающих пользователей с областью сортировки размером 1 М байт потреблял и 1 0 М байт памят и , то 1 00 одновременно работающих пользователей , скорее всего, будут использовать 1 00 Мбайт, 1 000 пользовате­ лей 1 000 М байт и т.д. Если только администратор базы дан ных не сидит за консолью, постоянно изменяя размеры областей сортировки/хеширования, то весьма вероятно, что в течение всего рабочего дня все пользователи будут и меть дело с одни м и и теми же значе н ия м и . Вспомните , как в предыдущем примере количество операций физического ввода-вывода во временном про­ странстве снижалось с увеличением разрешенного для применения объема ОЗУ. Если вы самостоятельно выполните это упражнение, то почти наверняка заметите уменьшение времени откл и ка с увеличением объема ОЗУ, доступ­ ного для сортировки . Выделение памяти вручную фиксирует объем памяти , который будет использоваться для сортировк и , на уровне более или менее постоянного числа, независимо от действительно доступного объема памяти . Автоматическое управление п амятью позволяет пользоваться этой памятью, когда она доступна; такой метод управления динамически регулирует объем применяемой памяти на основе рабочей нагрузки. - • Контроль расхода памяти. Предыдущая проблема делала трудным, если не не­ возможны м , удержание экземпляра Orac1e в рамках разумного распределения памяти . Контролировать объем памяти , который экземпляр собирался исполь­ зовать, было невозможно, т. к. не существовало н икакого реального средства управления количеством одновременно выполняющихся операций сортировки и хеширования . Сли ш ком легко можно было попытаться задействовать боль­ ше реальной памяти (действительно свободной физической памяти ) , чем до­ ступно на компьютере . Давайте приступим к и сследован и ю автоматического управления памятью PGA. Сначала нужно просто установить размер области SGA. Эта область является фраг­ ментом памяти ф и кс ирован ного размера, поэтому ее размер можно определить очень точно, и он будет ее полным размером (до тех пор, пока вы его не измените). Затем вы сообщаете СУБД Oracle о том , что этим объемом памяти нужно попро­ бовать ограничить все рабочие области ( новое обобщающее понятие для применя­ емых областей сортировки и хеш ирования) . П осле этого на компьютере с 2 Гбайт физической п амяти теоретически можно выделить 768 Мбайт памяти под область SGA и 768 М байт под область PGA, оставив 5 1 2 Мбайт для операционной системы и других процессов. Формулировка "теоретически " используется потому, что на са­ мом деле все работает не настолько точно, хотя и близко к этому. Прежде чем при­ ступить к обсужден и ю прич и н, почему это так, мы рассмотрим настройку автомати­ ческого управления памятью PGA и его включение. Процесс настройки этого управления памятью предусматривает выбор подходя­ щих значений для двух параметров инициализаци и экземпляра. Структуры памяти 217 • WO RKAREA_S I Z E P O L I C Y . Этот п араметр может быть установлен либо в МANUAL, в результате чего для управления объемом выделенной памяти будут применяться параметры размеров областей сортировки и хеш и рования, либо в AUTO, когда объем выделен ной памяти будет варьироваться на основе памяти PGA, в текуший момент распределенной для экземпляра. Стандартны м и ре­ комендуемым значением является AUTO. • PGA_AGGREGATE_TARGET . Этот параметр управляет суммарным объемом памя­ ти , который экземпляр должен выделять для всех рабочих областей , испол ьзу­ емых для выполнения сортировки или хеш ирования данн ых. Его стандартное значение зависит от версии и может быть установлено посредством разнооб­ разных инструментов, таких как ОВСА ( Database Configuration Assistant - по­ мошник по конфигурировани ю сервера баз данных). В общем случае, если вы применяете автоматическое управление памятью PGA, то должн ы устанавли­ вать этот параметр явным образом. Н а заметку! В Oracle 1 1 g Release 1 и последующих версиях вместо установки P GA AGGREGATE_ TARGET можно установить параметр MEMORY_ TARGET . Когда экземпляр ис­ пользует параметр MEMORY_TARGET, он решает, скол ько памяти выделить для SGA и PGA соответственно. Экзем пляр может также решить повторно выделить эти объем ы памяти прямо во время функционирования базы дан ных. Однако этот факт не затрагивает работу автоматического управления памятью PGA (описанную далее в главе) ; взамен экземпляр просто определяет установку PGA_AGGREGATE_TARGE T . Итак, предполагая , что параметр WORКAREA_S I Z E_POL I CY установлен в AUTO, а параметр PGA_AGGREGAT E _TARGET имеет неиулевое значение, будет применяться новый метод автоматического управления памятью PGA. Его можно " включ ить" в сеансе посредством команды ALT E R S E S S I ON или на уровне системы с помошью команды ALT ER SYSTEM. На заметку! Не забывайте о предыдущем предостережении относительно того, что в Oracle9i подключения посредством разделяемого сервера не будут использовать автоматическое управление памятью. Вместо этого для определения объема ОЗУ, распределяемого под раз­ личные операции, они будут применять параметры SORT_AREA_S I Z E и HAS H_AREA_ S I Z E . В Oracle 1 0g и последующих версиях автоматическое управление памятью PGA доступ­ но для обоих типов подключени й . В случае использования подключений через разде­ ляемый сервер в Oracle9i важно п равильно установить параметры SORT _AREA s I Z E и HAS H AREA S I Z E . _ Таким образом , основная цель применения автоматического управления памятью PGA - максимизация испол ьзования ОЗУ с одновременным предотвращаем при­ менения большего объема ОЗУ, чем требуется . В условиях руч ного управления па­ мятью эта цель была практически недостижимой. При установке S ORT _AREA_ s I Z E в 1 О М байт оди н пользователь, выпол няющий операцию сортировки , задействовал бы до 1 0 Мбайт памяти под область сортировки . Если бы 1 00 пользователей дела­ ли то же самое, они занял и бы до 1 000 М байт памяти . И мея в системе 500 М байт свободной памяти, единственный пользователь, выполняюший сортировку, мог бы занять значительно больш и й объем памяти , а 1 00 пользователей вынужден ы был и 218 Глава 4 бы довольствоваться существенно меньш и м объемом. И менно для решения таких проблем и было разработано автоматическое управление памятью PGA. При незна­ ч ител ьной рабочей нагрузке испол ьзование памяти может быть максимальным, а по мере увеличения нагрузки и роста числа пользователей , выпол ня ющих операции сортировки или хеширования , объем распределяемой для них памяти будет умень­ шаться, обеспечи вая эксплуатацию всего доступного ОЗУ, но не допуская попытки запрашивать больше памяти, чем существует физически . Определение способа выделения памяти Очень часто задают вопросы наподобие " Каким образом эта память выделена?" и " Какой объем ОЗУ используется сеансом? " . На них трудно ответить по той простой причине, что алгоритмы обслуживания памяти при автоматическом управлен ии не документированы и могут (и будут) изменяться от выпуска к выпуску. Когда приме­ няется автоматическое управление, вы частично утрачиваете контроль над процес­ сами, поскольку лежащие в основе алгоритмы самостоятельно прини мают решения о том, что следует делать, и как управлять компонентами . Н а основе примечани й M O S ( М у Oracle Support - Моя поддержка Oracle) под номерами 1 47806. 1 и 223730. 1 можно сделать ряд наблюдений. • П араметр PGA_AGGREGAT E _TARGET является целью верхнего предела. Это не объем, который заранее выделяется при запуске базы дан н ых. В этом легко убедиться , установив PGA_AGGREGAT E_TARGET в значение, которое намного больше, чем доступный объем физической памяти сервера. В результате вы не увидите никаких крупных распределени й памяти (запомните , что если вы уста­ новите MEMORY_TARGET , а затем PGA_AGGREGAT E _TARGET в значение, превы­ шающее MEMORY_TARGET , то при начальном запуске экземпляра Oracle будет сгенерирована ошибка ORA-00838, которая не позволит запустить экземпляр) . • Объем п амяти PGA, доступной задан ному сеансу, вы водится из установки PGA_AGGREGAT E_TARGET. Алгоритм для определения максимального размера, испол ьзуемый процессом , зависит от версии базы дан ных. Объем памяти PGA, распределяемой процессом, обыч но является функцией от доступного объема памяти и количества процессов, соперн ичающих за пространство. • По мере возрастания рабочей нагрузки экземпляра (при увеличении числа па­ раллельно выпол няющихся запросов и одновременно работающих пользовате­ лей) объем памяти PGA, выделенной рабочим областям, будет уменьшаться. База данных будет пытаться сохранять суммарный объем памяти , распределенной всем процессам, в пределах, указанных в параметре PGA_AGGREGATE_TARGET. Это аналогично тому, как если бы администратор базы данных в течение все­ го дня сидел за консолью и устанавли вал параметры S O RT_AREA_S I Z E и HAS H_AREA_S I Z E в соответствии с объемом работы, выпол няемой в базе дан­ н ых. Вскоре мы посредством теста исследуем такое поведение. Хорошо, а как выяснить размеры различных рабочих областей , выделенные се­ ансу? Это можно сделать с помощью той же методики, которая применялась ранее в сеансе с ручным управлением памятью PGA для выяснения объема памяти , исполь­ зуемой сеансом , и коли чества выполненных операций ввода-вывода во временном пространстве . Я выпол н ил следующий тест на четырехпроцессорной машине Oracle Структуры памяти 219 Linux с установленной версией Oracle 1 2. 1 .0. 1 и подключен ия м и посредством вы­ деленного сервера. М ы начнем с создания таблицы для хранения показателей , ко­ торые собираемся отслеживать (приведенный н иже код помеще н в файл по имени stats . sql): create tаЫе s e s s s t a t s as select name , value , О active from select a . name , b . value from v$statname а , v$ ses stat Ь whe re a . stat i s t i c # = b . stat i s t i c # and b . sid = ( select s i d from v$mys tat where rownum=l ) and ( a . name l i ke 1 %ga % 1 or а . name li ke 1 %direct temp % 1 ) union all select 1 total : 1 1 1 a . name , sum ( b . value ) from v$statname а , v$ses stat Ь , v $ s e s s ion с whe re a . stat i s t i c # = b . s t a t i s t i c # and ( a . name l i ke 1 % ga % 1 or а . name l i ke 1 %di rect temp % 1 ) and b . sid = c . s i d and c . use rname i s n o t n u l l group Ьу 1 total : 1 1 1 a . name ); Для представления показателей в этой табли це мы будем применять следующие столбцы . • NАМЕ название статистической и нформации, которую мы собираем ( инфор­ мация PGA и UGA из V$ S E S S TAT для текущего сеанса плюс вся информация о памяти экземпляра базы данн ых, а также о записи во временное табличное пространство) . • VALUE - значение данного показателя . • ACT I VE количество сеансов, выполняющих работу в экземпляре . Перед на­ чалом мы предполагаем, что экземпляр находится в состоян и и ожидания; наш сеанс в данн ы й момент я вляется единствен н ы м пользовательским сеансо м , поэтому значение равно О . - - Затем в интерактивном сеансе запускается показанный н иже сценарий SQL* Pius (сохраненный в файле s i ngle_load . s q l ) . Табли ца т была создана заранее и содер­ жит около 70 000 строк. connect eoda / foo set echo on decla re 1 first time boolean de faul t t rue ; begin for х in ( s e lect * from t o rder Ьу 1 , 2, 3 , 4 ) loop if ( 1 first t ime - - 220 Глава 4 then insert into s e s s s tats ( nате , value , active select name , va l ue , ( se l ect count { * ) f rom v$ s e s s ion where status = ' ACT I VE ' and use rnaтe is not nul l ) from s e l ect a . name , b . va lue from v $ s t atname а, v$ ses s tat Ь where a . statistic# = b . statistic# and b . s i d = ( s elect s i d from v$mys tat whe re rownum=l ) and ( a . name l i ke ' %ga % ' o r а . nате l i ke ' %direct temp % ' ) union a l l s e l ect ' total : ' 1 1 a . name , sum ( b . value ) from v $ s tatnaтe а , v$ses stat Ь , v $ s e s s ion с where a . statistic# = b . statistic# and ( a . name l i ke ' % ga % ' or а . nате l i ke ' %direct temp % ' ) and b . s i d = c . s i d a n d c . us e rnaтe i s n o t nul l group Ьу ' total : ' 1 1 а . nате ); 1 f i r s t t ime . - false ; end i f ; end l oop ; end; 1 commi t ; Этот сценар и й сортирует большую табли цу т , используя автоматическое управ­ ление памятью PGA. Затем для текушего сеанса он захватывает все настройки памя­ ти PGA/UGA, а также активность, связанную с сортировкой на диске. Кроме того, конструкция UN I ON ALL добавляет те же показатели (общая п амять PGA, общая па­ мять U GA и т.д. ) для уровня системы. Сценарий бьm запущен в базе данных со сле­ дующими параметрами и н ициал изации : * . compatiЬle= ' l 2 . 1 . 0 . 1 ' * . control_fi l e s = ' /u 0 1 /dЬ f i l e / ORA1 2 CRl / control 0 l . ct l ' , ' /u 0 2 /dЬ f i l e / ORA1 2 CR 1 / control 0 2 . ct l ' * . dЬ Ьlock s i ze=8 1 92 * . dЬ name= ' ORA1 2 CR1 ' * . pqa_aggregate_target=25 6m * . s ga_ta rget=2 5 6m * . open_cu rsors=З O O * . proce s s e s = б O O * . remote_login_pas s wo rd f i l e= ' EXCLU S I VE ' * . resource l imi t=TRUE * . undo_taЬlespace= ' UNDOTBS l ' Структуры памят и 221 Эти параметры указывают на применение автоматического управления памятью PGA со значением PGA_AGGREGAT E_TARGET , равным 256 М байт, т.е . Oracle отведе­ но вплоть до 256 М байт памяти PGA для сортировки . Я подготовил еще один сценарий для запуска в других сеансах с целью генерации крупной нагрузки , связанной с сортировко й . В этом сценарии организован цикл и используется встроенный пакет овмs _ALERT для проверки необходимости продол­ жения обработки . Если обработка должна продолжаться , в сценарии запускается тот же самый большой запрос, сортирующий все содержи мое таблицы т . По заверше­ нии эмуляции сеанс сигнализирует всем процессам сортировки , т.е . генераторам на­ грузки , о необходимости "останова" и завершения . Сценарий (сохраненный в файле gen_load . s q l ) , применяемый для выполнения сортировки , выглядит следующим образом : declare 1_rnsg long ; l_s tatus nurnЬe r ; begin dЬrns_al ert . regi ster ( 1 WAI T I NG 1 ) ; for i in 1 . . 9 9 9 9 9 9 loop dЬrns_appl i cation_info . s e t_cl ient_i n fo ( i ) ; dЬrns_alert . wai tone ( 1 WAI T I NG 1 , l_rnsg , l_s tatus , О ) ; exit when l_s tatus = О ; for х i n ( s e lect * frorn t order Ьу 1 , 2 , 3 , 4 ) loop null ; end loop ; end loop ; end ; 1 exit А вот сценарий (сохране н н ы й в файле s t op . s q l ) , которы й останавливает вы­ полнение процессов: begin dЬrns_alert . s ignal ( 1 WAI T I NG 1 , 1 1 ) ; cornrni t ; end ; 1 Чтобы понаблюдать за отличиями в объем ах ОЗУ, выделенных измеряемому се­ ансу, вначале я вы полнил запрос S E LECT в изоляции - как единствен н ы й сеанс. Я захватил ту же статистическую информаци ю и сохранил ее в таблице S E S S _STAT S вместе со счетчиком активных сеансов. Затем я добавил в систему 25 сеансов (т. е . запустил приведе н н ы й ранее эталон н ы й сценарий ( g e n l o a d . s q l ) с циклом for i i n l 9 9 9 9 9 9 l oop в 25 новых сеансах). Выждав некоторое время (одну минуту, чтобы система смогла приспоеобиться к этой новой нагрузке) , я создал но­ вый сеанс и запустил запрос для выполнения сортировки , захватывая статистичес­ кие сведения , как и ранее . Я проделывал это многократно, постепенно увеличивая количество одновременно работающих пользователей до 500. . . 222 Глава 4 Совет. Сценарии, задействованные в этом эксперименте, доступны для загрузки на веб-сай­ те издательства. Сценарий run . s ql в каталоге ch 0 4 автоматизирует тест, описанный в настоящем разделе. Следует отм е т и т ь , что зде с ь я п отребовал у э к з е м пляра базы дан н ы х сдел ать н е в о з м о ж н о е . К а к у п о м и н ал о с ь р а н е е , п е р в ы й запус к с ц е н ар и я w a t ch_s t a t . s q l свидетельствует о том , что каждое подключение к базе данных Oracle - еще до выполнения первой операции сортировки - потребляет чуть более 0 , 5 Мбайт ОЗУ. При наличии 500 пользователей только их вход в базу данных, не говоря уже о действительном выполнении какой-то работы, привел бы к потреб­ лению памяти с объемом, очен ь близким к пределу, который определен в парамет­ ре PGA AGGREGATE TARGET! Это служит допол нительным свидетельством того, что параметр PGA_AGGREGATE TARGET я вляется целью, а не директивой . Мы можем, да и будем , превышать его значение по разным причинам. Теперь все готово для фор­ м ирования отчета о результатах; из-за ограниченного пространства мы прекратили вывод на 275 пользователях, т. к. данные стали повторяться: _ _ _ EODA@ORA12CR1> column active format 9 9 9 EODA@ORA1 2CR1> column pga format 9 9 9 . 9 EODA@ORA12CR1> column " tot PGA" format 9 9 9 . 9 EODA@ORA12CR1> column pga_di ff format 9 9 9 . 9 9 EODA@ORA12CR1> column " t emp write" format 9 , 9 9 9 EODA@ORA12CR1> column " tot write s temp " format 9 9 , 9 9 9 , 9 9 9 EODA@ORA 1 2 CR 1 > column writes di f f format 9 , 9 9 9 , 9 9 9 EODA@ORA 1 2 CR 1 > select active , 2 pga , 3 " tot PGA" , 4 " tot PGA" - lag ( " tot PGA" ) over ( order Ьу act ive ) pga_diff, 5 " t emp write " , б " tot writes temp " , 7 " tot writes temp " - lag ( " tot writes temp " � ove r ( orde r Ьу active ) writes diff 8 from ( 9 s elect * from ( 10 1 1 select active , name , 12 case when name l i ke 1 % ga mem% 1 then round ( value/ 1 0 2 4 / 1 0 2 4 , 1 ) 13 � e l s e value end val 14 f rom s e s s stats 15 where active < 2 7 5 16 ) 1 7 pivot ( max ( va l ) for name in 1 s e s s i on pga memory 1 a s " PGA" , 18 1 total : s e s s ion pga memory 1 a s " tot PGA" , 19 1 phys ical writes direct temporary taЫespace 1 a s "temp write " , 20 21 1 total : phys ical writes direct temporary taЫe space 1 � a s " tot writes temp " ) ) 22 23 2 4 order Ьу act ive 25 1 Стру ктуры nамя ти 223 tot PGA PGA D I F F temp write tot wri testemp WRI TES DI FF -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - о 7.6 о 3.5 о о о 15 . 2 19.5 1 1 . 90 о 1 243, 387 243, 387 15 . 2 1 95 . 6 26 176 . 10 о 518, 246 274 , 859 2 92 . 7 7.7 97 . 1 0 1, 045 51 -104 . 00 423, 078 94 1 , 32 4 188 . 7 76 3, 066 5.2 8 92 , 7 1 1 1 , 834, 035 4 3 . 90 232 . 6 5.2 6 , 32 3 101 3, 021 , 4 8 5 1, 187, 450 6, 351 126 291 . 8 59 . 20 5.2 4 , 783, 879 1 , 7 62 , 3 9 4 345 . 0 5.1 53 . 20 151 6 , 32 6 8 , 603 , 295 3, 819, 416 58 . 30 177 403 . 3 6, 321 5.0 4 , 245, 273 201 453 . 2 12, 848, 568 4 9 . 90 6, 327 5.2 15, 225, 399 2 , 376, 831 507 . 5 226 4.8 54 . 30 6, 333 2 , 354 , 103 17, 579, 502 562 . 2 251 54 . 70 6, 315 5.1 12 rows selected . 1 2 строк выбрано . ACT I VE PGA Прежде чем анализировать результаты , давайте посмотрим на запрос, использо­ ванный для формирования отчета. В нем применяется средство, доступное начиная с версии Oracle 1 1g Release l , которое называется вращением (pivot) результирующего набора. Н иже приведен альтернативны й способ записи строк с 1 1 по 24 этого SQL­ зaпpoca, который будет работать в Oracle 1 Og Release 2 и предшествующих версиях: 11 12 13 14 select act ive , max ( decode ( name , ' se s s ion p g a memory ' , va l ) ) pga , max ( decode ( name , ' total : s e s s ion pga memory ' , val ) ) a s " tot PGA" , max ( decode ( name , ' phys ical writes direct temporary taЫespace ' , � val ) ) as " temp write " , 15 max ( decode ( name , ' total : phys ical writes direct temporary taЬlespace ' , � val ) ) as " tot wri tes temp " from ( 16 1 7 select act ive , 18 nате , case when name l i ke ' % ga mem% ' then round ( value/ 1 0 2 4 / 1 02 4 , 1 ) 19 � e l s e value end va l 20 from s e s s s tats 2 1 whe re active < 2 7 5 22 2 3 group Ьу act ive 24 )) Эта часть запроса извлекает записи из таблицы показателей , когда есть менее 275 активных сеансов, преобразовывает показатели памяти ( UGA/PGA) из байтов в мега­ байты и затем вращает четыре интересующих нас показатели , делая из строк столбцы. После получения этих четырех показателей в одной записи с помощью аналитичес­ кой функции LAG ( ) к каждой строке были добавлены значен ия общего наблюдаемо­ го объема PGA и общего наблюдаемого количества операций ввода-вывода во вре­ менную область для предыдущих строк. Это позволяет легко видеть последовательные различия в этих значениях. Вернемся к данным - как видите, при наличии неболь­ того числа активных сеансов все операции сортировки происходили полностью в па­ мяти . При количестве активных сеансов от 1 до 50 сортировка происходила полно­ стью в памяти . Однако к моменту, когда в систему вошло 50 пользователей, активно выполняющих сортировку, базе данных стало не хватать объема памяти , который было 224 Глава 4 разрешено испол ьзовать одновременно. Для того чтобы объем памяти PGA уместил­ ся в допустимые пределы (запрошенные 256 М байт) , потребовалась пара минут, но в конечном итоге это происходило на таком низком уровне одновременно работаю­ щих пол ьзователей. Объем памяти PGA, выделенной сеансу, снизился с 1 5,2 Мбайт до 7,7 Мбайт и остановился на показателе примерно 5,2 Мбайт (вспомните, что части памяти PGA распределяются не для рабочей области (сортировки), а для других опе­ раций ; один лишь вход пользователя приводит к вьщелению 0,5 Мбайт памяти PGA) . Общий объем памяти PGA, задействованной системой, оставался в приемлемых пре­ делах до тех пор, пока в системе не появилось приблизител ьно 1 26 пользователей. Затем объем памяти начал регулярно превышать значение PGA AGGREGAT E_TARGET и это сохранилось вплоть до конца теста. В этом случае перед экземпляром базы была поставлена неразреш имая задача - выделенн ых 256 Мбайт ОЗУ просто не хватало для обеспечения одновременной работы 1 26 пользователей, большинство из которых выполняли код P L/SQL и операции сортировки . Это просто невозможно было сде­ лать. Таким образом, каждый сеанс применял минимально возможны й объем памяти, но вынужден был вьщелять столько памяти , сколько ему требовалось. К моменту за­ вершения теста активные сеансы использовали всего около 560 Мбайт памяти PGA настолько мало, насколько это было возможно. Тем не менее, мы должны обдумать, как этот вывод вы глядел бы при руч ном управлени и памятью. П редположим, что параметр SORT _AREA_ s I ZE установлен в 5 М байт. М атематическая оценка очень проста: кажды й сеанс смог бы выполнять сортировку в ОЗУ ( ил и в виртуальной памяти при нехватке реального ОЗУ) и, сле­ довательно, каждый сеанс потреблял бы от 6 до 7 Мбайт ОЗУ (объем, задейство­ ванн ы й без выполнения сортировки на диске в предыдущем случае с единственным пользователем) . Использование памяти выглядело примерно так: _ EODA@ORA12CR1> co1umn tota l_pga format 9 , 9 9 9 EODA@ORA 1 2 CR 1 > with da ta ( u s er s ) 2 as 3 ( se lect 1 users from dual 4 union а 1 1 5 select u s e r s + 2 5 from data where us er s + 2 5 <= 2 7 5 ) 6 s e l ect u s e r s , 7 my_pga , 7 * users total__pga from data 7 8 orde r Ьу users 9 1 USERS МУ PGA TOTAL PGA ---------- ---------- --------- 7 7 7 7 7 7 7 7 7 7 7 7 182 357 532 707 882 1 , 057 1 , 232 1 , 407 1 , 582 1 , 757 1 26 51 76 101 126 151 176 201 226 251 1 1 rows sel ected . Структуры п ам ят и 225 На заметку! В этом запросе применяется прием рекурсивного выноса подзап роса ( recursive subquery factoriпg), который доступен только в Oracle 1 1 g Release 2 и последующих вер­ сиях. В более ранн их выпусках приведенный запрос работать не будет. Если бы я запустил этот тест (на сервере установлен о 2 Гбайт реальной памя ­ ти , а объем области SGA составляет 256 М байт) , то к моменту появления в системе 250 пользователей подкачка и страничный обмен происходили бы настолько часто, что продолжение работы оказалось бы невозможны м ; при 500 пользователях при­ шлось бы выделить около 3 5 1 4 М байт ОЗУ! Следовательно, в такой системе адми ­ нистратор базы данных, скорее всего, установил б ы значение SORT AREA_ s I Z E н е в 5 Мбайт, а в 0,5 М байт, пытаясь удержать максимальн ы й применяемый объем PGA на приемлемом уровне. При 500 пользователях выделенный объем PGA составил бы около 500 Мбайт, что примерно соответствовало бы ситуаци и с автоматическим уп ­ равлением памятью, но при меньшем количестве пользователей вместо сортировки в памяти все равно выполнялась бы запись во временное пространство на диске. Ручное управление памятью демонстрирует вполне предсказуемое - но далеко не оптимальное - использование памяти при увеличении или умен ьшен и и рабо­ чей нагрузки . Автоматическое управление PGA было разработано именно для того, чтобы позволить небольшому сообществу пользователей задействовать максимально возможный объем ОЗУ, когда он доступе н , уменьшая потребление памяти при воз­ растании рабочей нагрузки и увеличивая объем памяти , выделенной для отдельных операций , при снижении нагрузки . _ Использование параметра PGA AGGF.REGAТE ТARGET для управления выделением памяти _ _ Ранее было указано, что "теоретически " параметр PGA_AGGREGAT E_TARGET мож­ но применять для управления общим объемом памяти PGA, используемой экзем­ пляром . Однако последни й пример показал, что этот предел не является жестким . Экземпляр попытается остаться в границах, определенных PGA_AGGREGATE_TARGET , н о если ему это не удастся, о н н е прекратит обработку, а просто превысит данный порог. Еще одна причина того, что этот предел я вляется "теоретически м " , связана с тем, что хотя рабочие области составляют крупную часть памяти PGA, они не явля­ ются единственными ее фрагментами . Область PGA состоит из м ножества часте й , и только рабочие области находятся под контролем экземпляра базы данных. Если создать и выполнить блок кода PL/SQL, который заполняет данн ы м и бол ьшой мас­ сив в режиме выделенного сервера, когда область UGA размещена в области PGA, то Oracle не останется ничего другого, как разреш ить это. Рассмотри м следующий короткий пример. М ы создадим пакет, который может хранить некоторые постоянные (глобальные) данные на сервере: EODA@ORA12CR1> create or replace pac kage demo_pkg 2 as 3 type a rray is table of char ( 2 0 0 0 ) index Ьу binary_intege r ; 4 g_data array; 5 end; 6 1 Package created . Пакет создан . 226 Глава 4 Теперь измери м объем памяти , которы й в текущий момент наш сеанс использует в PGA/UGA (в этом примере применяется выделенный сервер, поэтому UGA ямя­ ется подобластью памяти PGA) : EODA@ ORA1 2CR1> s e 1 ect a . name , to_char ( b . value, ' 9 9 9 , 9 9 9 , 9 9 9 ' ) bytes , 2 to_cha r ( round ( b . va1ue/ 1 0 2 4 / 1 0 2 4 , 1 ) , 1 9 9 , 9 9 9 . 9 1 ) mЬytes 3 from v$ s tatname а , v$mys tat Ь 4 where а . s ta t i s t i c# = Ь . stat i s t i c# 5 and a . name l i ke 1 % ga memory% 1 ; BYTES NАМЕ s e s s i on uga memory s e s s ion uga memory max s e s s ion pga memor y s e s s i on p g a memory max MBYTES 1 , 526, 568 1 , 52 6 , 568 2 , 208 , 088 2 , 208, 088 1.5 1.5 2.1 2.1 Первоначально наш сеанс использует около 2 , l М байт памяти PGA (как ре­ зультат компиляц и и пакета P L/SQL , выполнения запроса и т.д. ) . Теперь снова за­ п устим этот запрос применительно к табли це т с применением того же значения PGA_AGGREGATE_TARGET, равного 256 М байт (это было сделано в экземпляре, кото­ рый в противном случае бы простаивал; мы затребуем выделение памяти для сеанса прямо сейчас): EODA@ ORA12CR1> s e t autotrace traceon 1 y stat i s t i cs ; EODA@ ORA12CR1> select * from t order Ьу 1 , 2 , 3 , 4 ; 7 2 6 1 6 rows s e 1 e cted . 72 61 б с трок выбрано . Statistics 105 о 1103 993 о 366584 4 53795 4843 recurs ive cal l s dЬ Ы о с k gets cons i s tent gets phys ica1 reads redo s i ze byte s sent via SQL*Net to c l i ent byte s received vi a SQL * Net from cl ient S QL * Ne t roundtrips t o / f rom client 1 sorts (mem.ory) о sorts ( di s k ) rows proces sed 72616 EODA@ ORA12CR1> set autotrace o f f Как видите , сортировка была выполнена полностью в п амяти , и фактически взгля нув на испол ьзование памяти PGA/UGA со сторон ы сеанса, можно выяснить объем потребляемой памяти : EODA@ORA1 2CR1> s e lect a . name , to_char ( b . val ue , 1 9 9 9 , 9 9 9 , 9 9 9 1 ) bytes , 2 to_char ( round ( b . val ue / 1 0 2 4 / 1 0 2 4 , 1 ) , 1 9 9 , 9 9 9 . 9 1 ) mЬytes 3 from v$ s tatname а , v$mys tat Ь 4 where a . s ta tis t i c # = b . statistic# 5 and a . name l i ke 1 % ga memory% 1 ; Структуры nамят и NАМЕ 227 MBYTES BYTES se ss ion uga memory sess ion uga memory max sess ion pga memory 1 , 854 , 008 11, 213, 280 2 , 4 7 0 , 2 32 1.8 10 . 7 2.4 session pga memory max 1 2 , 104 , 024 11 . 5 Легко заметить, что используются 1 1 , 5 М байт ОЗУ с примерны м диапазоном в 1 5 Мбайт, которы й м ы наблюдали ранее в предыдущем тесте сортировки. Теперь за­ полним массив CHAR, имеющийся в пакете (тип дан н ых СНАR дополняется пробела­ ми, поэтому каждый элемент массива имеет длину точно 2000 символов) : EODA@ORA1 2CR1 > begin for i in 1 . . 2 0 0 0 0 0 2 3 loop 4 demo_p kg . g_da ta ( i ) . ' х ' ; end loop; 5 б end; 7 1 PL/SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно завершена . - Измерение текущей утилизации памяти PGA нашего сеанса дает следующие ре­ зультаты: EODA@ORA12CR1> se lect a . name , to_char ( b . va l ue , ' 9 9 9 , 9 9 9 , 9 9 9 ' ) bytes , to_cha r ( round ( b . value/ 1 0 2 4 / 1 0 2 4 , 1 ) , ' 9 9 , 9 9 9 . 9 ' ) mЬytes 2 from v$ statname а , v$mystat Ь 3 4 where а . statistic# = Ь . stat i s ti c # 5 a n d a . name l i ke ' % ga memory% ' ; NАМЕ BYTES se ss ion uga memory se ss ion uga memory max se ss ion pga memory session pga memory max 4 69 , 569, 304 4 69 , 5 6 9 , 3 0 4 4 7 0 , 921 , 560 4 7 0 , 92 1 , 560 MBYTES 447 . 8 447 . 8 449 . 1 449 . 1 Теперь область PGA содержит выделенные сегменты , которым и сам экземпляр управлять не может. Мы уже превысили предел, установленный в PGA_AGGREGATE_ тARGET для всего экземпляра в этом отдельном сеансе, и база данных ничего не мо­ жет с этим поделать. Если бы она действовала и наче , то ей пришлось бы отклонить наш запрос, и она сделала бы это только в случае, есл и бы операционная система сообщила об отсутствии памяти для выделения (ORA-04030 ) . При желан ии можно бьuю бы зарезервировать больше памяти для этого масси ва и поместить в него боль­ ше данных - и экзем пляр всего лишь бы выполнил такое действие. Тем не менее, экзем пляр осведомлен о том , что м ы сделали. Он вовсе не игно­ рирует память, которой не может управлять; он просто идентифицирует, что память используется , и соответствующим образом уменьшает размер памяти , выделен ной для рабочих областей . П оэтому, есл и снова выпол н ить тот же запрос сортировки , то выяснится , что на этот раз сортировка осуществляется на диске - экземпляр не предоставит около 12 Мбайт ОЗУ, которые необходимы для выполнения этой опе­ рации в памяти , поскольку значение PGA_AGGREGATE_TARGET уже превышено: 228 Глава 4 EODA@ ORA1 2 CR 1> s e t autotrace traceon l y statistics ; EODA@ ORA1 2CR1> s e lect * from t order Ьу 1 , 2 , 3 , 4 ; 7 2 6 1 6 rows s e 1 ected . 72 61 6 строк выбрано . Statistics 9 8 986 2025 о 3 6658 4 4 53795 4843 о 1 72616 recurs ive ca1 l s db Ы о с k gets con s i s tent gets phys ical reads redo s i z e byte s sent via SQL*Net to client bytes received via SQL*Net from c l l ent SQL*Net roundtrips t o / f rom client sorts ( memory ) sorts (disk) rows proces sed EODA@ ORA 1 2 CR 1> s e t autotrace off _ Итак, из-за того, что часть памяти PGA находится вне контроля Oracle , легко превысить значение PGA AGGREGATE _TARGET, просто выделяя память для множес­ тва действительно крупных структур дан н ых в коде PL/SQL. Я ни в коем случае не рекомендую поступать так, а просто подчеркиваю, что значение PGA AGGREGATE TARGET - скорее просьба, а не жесткое огран ичение. _ В ыбор между ручным и автоматическим управлением памятью Так какой же метод следует применять: ручной или автоматический? Я однознач­ но предпочитаю по умолчани ю использовать автоматическое управление памятью PGA. Внимание! В этой книге я время от времени повторяю: не вносите никаких изменений в про­ изеодетвенную - реально действующую - систему без предварительного тестирования на п редмет любых побочных эффектов. Например, п редположим , что вы не читали эту главу, проверили свою систему и обнаружили , что в ней применяется ручное управление памятью, а затем просто активизировал и автоматическое управление. В таком случае пла­ ны запросов могут измениться , и это может повлиять на п роизводительность. Возможен один из трех сценариев: • производительность системы останется в точности п режней; • производительность увеличится ; • производительность значительно уменьшится. Будьте внимательны при внесении изменений; в первую очередь проверяйте п редложен­ ное изменение. _ _ Одной из наиболее трудных задач дЛЯ администратора базы данн ых может быть установка и ндивидуальных параметров, особенно таких, как SORT 1 НАS Н AREA s I ZE и т.д. М не часто приходилось сталкиваться с системам и , работающими с невероят­ но низкими значениями этих параметров - настолько н изкими, что это приводи- Структуры памяти 229 ло к очень серьезному снижению производительности . Возможно, это объясняется тем, что зн,ачения таких параметров, устанавл иваемые по умолчанию, очень мал ье 64 Кбайт для сортировки и 1 28 Кбайт для хеш и рован ия . Существует м н ожество проти воречивых мнений по п оводу их оптимальных значе н и й . Кроме того, опти­ мальные значения могут изменяться в течение рабочего дня . В 8 часов утра при наличии двух пользователей размер области сортировки, равн ы й 50 Мбайт, выде­ ленный для одного зарегистрированного пользователя , может быть впол не допус­ тимым. Но в полдень, когда пользователей становится 500, значение 50 М байт мо­ жет оказаться совершенно неприемлемы м . И менно в этой ситуации целесообразно применять параметры WORКAREA_S I Z E POL I CY=AUTO и PGA_AGGREGAT E _TARGET. Концептуально установка значения PGA_AGG REGAT E _TARGET - объема памяти , который СУБД Orac1e должна быть вправе использовать для выполнения операций сортировки и хеширования - проще, чем попытка подбора идеальных значений па­ раметров SORT 1 НАSН_AREA_S I Z E , тем более что таких идеальных значений попрос­ ту не существует. Оптимальные значен ия зависят от конкретной рабочей нагрузки . По исторически сложи вшейся тради ции адми н истраторы баз дан н ых конфи­ гурировали объем памяти , при меняем ы й Orac1e, путем установки размера области SGA (кеш буферов, журнальн ы й буфер, разделяемый пул , большой пул и пул Java). Оставшаяся память компьютера должна была использоваться выделе н н ы м и разде­ ляемым серверами в области PGA. Администратор базы данных обладал очен ь не­ значительны м контролем над тем, сколько этой памяти должно было быть задейс­ твовано или не задействовано. Он мог установить параметр S ORT_AREA_ S I Z E , но при одновремен ном выпол н е н и и 10 операций сортировки СУБД Oracle могла бы применять до l O * S ORT_AREA_S I Z E байт ОЗУ. При параллельном выполнении 1 00 операций сортировки Orac1e использовала бы 1 00 * S ORT _AREA_S I Z E байт, при 1 000 операциях - 1 000 * S ORT _AREA_S I Z E и т.д. Уч иты вая , что в PGA помещаются и другие объекты , администратор лишен реальной возможности управлять максималь­ ным объемом памяти, который задействуется из области PGA системы. Желательно, чтобы испол ьзование этой памяти регулировалось реальн ы м и пот­ ребностями в системе. Чем больше пользователей , тем меньш и й объем ОЗУ каждый из них должен занимать, а чем их меньше, тем больш ий объем памяти должен быть доступен для применения каждым из них. Установка WORКAREA_S I Z E_ POL I CY=AUTO как раз и является способом достиже н ия этой цел и . Те перь адм и н истратор базы данных указывает единственный размер PGA_AGGREGAT E_TARGET, представляю­ щий собой максимальный объем памяти PGA, который база дан ных должна стре­ миться использовать. СУБД Orac1e будет распределять эту память между активн ыми сеансами так, как сочтет нужным. Более того, Orac1e9i Release 2 и последующие вер­ сии предлагают консультативную справку по размеру PGA (часть Statspack и AWR, доступная через ди намическое представление и нформации производительности V$ и отображаемая в окне диспетчера предприятия) , похожую на консультативную справку по настройке кеша буферов. Со временем эта справка подскажет, какое зна­ чение PGA_AGGREG FATE _TARGET будет оптимальным для м и н и мизации количества физических операций ввода-вывода во временных табличных пространствах данно­ го экземпляра. Эту информацию можно применять л ибо для динамического и нтер­ активного изменения размера PGA (при наличии достаточного объема ОЗУ), либо для принятия решения о том, нуждается ли сервер в дополнительном объеме ОЗУ с целью достижения оптимальной производительности . - 230 Глава 4 Однако бывают ли ситуации, в которых пол ьзоваться автоматическим управле­ нием памятью нежелательно? Безусловно, но к счастью они являются скорее ис­ ключением, чем правилом. Этот метод был разработан для многопользовательской среды . В ожидании присоединения новых пользователей к системе автоматическое управление памятью будет ограничивать объем выделяемой памяти в виде некото­ рого процента от значения P GA_AGGREGAT E _TARGET. Но как быть, если требуется задействовать весь доступн ы й объем памяти? Что ж, в таком случае придется с по­ мощью команды ALT E R S E S S I ON отключить автоматическое управление памятью в своем сеансе (оставив е го включенным во всех остальных) и вручную установить нужные значения параметров S O RT 1 HAS H_AREA_S I Z E . Например, каким образом поступить, когда есть круп ный пакетн ый процесс, которы й запускается в 2:00 и вы­ полняет большие хеш -соединения , строит и ндексы и тому подобное? Ему должно быть разрешено эксплуатировать все ресурсы , доступные экземпляру. Этому процес­ су не нужно "скромн ичать" в плане испол ьзования памяти - ему необходима вся доступная память, поскольку в данный момент он я вляется единственным выпол­ няющимся в базе данных. Совершенно очевидно, что это пакетное задание может выдать команду ALT E R S ES S I ON и задействовать все доступные ресурсы . Короче говоря , я предпочитаю применять автоматическое управление памятью для сеансов конечных пользователе й - для приложе н и й , которые ежедневно вы­ полняются в базе данных. Ручное управление памятью целесообразно использовать при запуске больших п акетных задани й , фун кционирующих в те периоды времени, когда они являются единственными активными процессами в экземпляре . З аключительные соображения по поводу использования областей PGA и UGA К настоящему времен и м ы рассмотрели две структуры памяти : PGA и UGA. Теперь вы должны понимать, что область PGA является закрытой для процесса. Она представляет собой набор переменных, которые выделенный или разделяемый сер­ вер Oracle должен хранить независимо от сеанса. Область PGA - это "куча" памя­ ти , в которой могут распределяться другие структуры . Область U GA также является " кучей " памяти , в которой могут быть определены различные структуры , характер­ ные для сеанса. Область UGA распределяется внутри области PGA при подключе­ н и и к базе данных Oracle посредством выделен ного сервера и в области SGA при подключе н и и через разделяемый сервер. Из этого следует, что при использован ии разделяемого сервера необходимо определять размер большого пула области SGA так, чтобы обеспечить достаточн ы й объем для обслуживания любого возможного пользователя , которы й когда-либо подключится к базе данных параллельно. Таким образом , область SGA базы данных, которая поддерживает подключения посредс­ твом разделяемого сервера, в общем случае намного больше области SGA аналогич­ но сконфигурированной базы данных, поддерживающей только режим выделенного сервера. Область SGA подробно рассматривается далее в главе. С исте м ная глобальная область Каждый экзем пляр Oracle имеет одну крупную структуру памяти , которая на­ зы вается системной глобальной областью (System Global Area - SGA) . Это большая Структуры nа м ят и 23 1 структура памяти совместного использова н ия , к которой в тот или и ной момент времени будет обращаться каждый процесс Oracle. Ее размер варьируется от десят­ ков мегабайт в небольших тестовых системах до нескольких ги габайт в средних и больших системах и сотен гигабайт в действительно круп н ых системах. В среде UN IX/Linux область SGA - это физическая сущность, которую можно " видеть" в командной строке операционной систе м ы . Физически она реализована в виде сегмента разделяемой памяти - автономного фрагмента памяти , к которому могут присоединяться процессы. Допускается иметь в системе область SGA без еди­ ного процесса Oracle - память оказы вается предоставленной самой себе . Однако следует отметить, что наличие области SGA безо всяких процессов Oracle свидетель­ ствует об аварийном отказе базы данных по какой -либо причине. Эта ситуация не­ обыч на, но может встречаться . Вот как область SGA " вы глядит" в системе Огасlе Linux: $ ipcs - m 1 grep o ra Ох27Ьа 9 4 4 с 8 8 7 3 2 4 6 7 5 ОхОО О О О О О О 8 8 7 3 5 7 4 4 4 Ох7 4 9а 2 е 0 8 8 8 7 9 4 7 2 6 9 ОхОО О О О О О О 8 8 7 9 8 0 0 3 8 ОхОО О О О О О О 8 8 8 5 3 7 0 9 5 ОхОО О О О О О О 8 8 8 5 6 9 8 6 4 Oxc6e 5 1dc4 8 8 8 6 0 2 6 3 3 oracle oracle oracle oracle oracle oracle oracle 640 640 640 640 640 640 640 14 680064 82 1061158912 41 14 680064 72 511705088 36 8 3 8 8 60 8 16 260046848 16 2 0 97 1 52 16 Н а заметку! Н а моей тестовой/демонстрационной машине функциони рует несколько эк­ земпляров . Мне пенадобилось множество экземпляров для тестирования разнообразных концепций, представленных в этой книге, в разных выпусках. Единственно разумн ы м и корректным количеством экземпляров на рабочей машине является один. В реальных ус­ ловиях никогда не устанавливайте более одного экземпляра на каждый отдельный рабо­ чий сервер. Если вам нужно более одного экзем пляра на физическом сервере, вы должны применять виртуализацию, чтобы разделить этот оди н сервер на несколько виртуальных серверов - каждый с собственным экзем пляром Oracle. Здесь представлены три области SGA, и в отчете показана учетная зап ись опе­ рационной системы , которая владеет SGA ( o r a c l e для всех областей в этом при­ мере), а также размер SGA - 1 Гбайт ( вторая строка) для первого примера. В сре­ де Windows вы не сможете видеть SGA как отдельную сущность, что возможно в UN IX/Linux. Из-за того, что на платформе Windows база данных Oracle выпол няется как одиночный процесс с единственным адресным пространством, область SGA вы­ деляется как закрытая память процесса o r a c l e . ехе. С помощью диспетчера задач Windows или какого-то друтого инструмента мониторинга производительности мож­ но посмотреть, сколько памяти распределено для o r a c l e . ехе, но видеть SGA отде­ льно от остальной распределенной памяти не получится . На заметку! Если только вы не испол ьзуете мои настройки параметров и не работаете в точности с такой же версией Oracle и в точно той же операционной системе, вы почти наверняка увидите другие показатели . Размеры SGA сильно зависят от верси и , операци­ онной системы и параметров. 232 Глава 4 Внутри самой СУБД Oracle информацию об области SGA можно просматривать независимо от платформ ы , применяя еще одно " магическое" представление V$ по имени V$ S GASTAT . И нформация может выглядеть примерно так: EODA@ORA 1 2 CR1 > compute sum of byte s on pool EODA@ORA12CR1> break on pool s kip 1 EODA@ORA12CR1> EODA@ORA 1 2 CR1 > select pool , nате , bytes 2 f rom v$sgastat o rde r Ьу pool , nате ; 3 NАМЕ POOL j ava pool ************ sum la rge pool ************ sum shared pool ************ free memory 4 1 94 3 0 4 РХ msg pool f ree memory 4 1 94304 4 91520 37 0 2 7 8 4 1 0 6 3 . kgght 1 1G QМN so 1 7 7 . kgg fa 4 1 94 3 0 4 36784 4144 398 4 0 1 60 z l l lab G roup T ree Неар De sum ************ BYTES bu f f er cache fixed sga log bu ffe r shared_io_pool sum 3 1 4 57 2 8 0 0 184549376 2 2 90 2 6 4 7938 0 4 8 4 1 94 3 0 4 1 98 9 7 1 992 1 0 6 4 rows s elected . 1 0 64 с тр ок выбрано . Область SGA разделена на разнообразные пулы. Основные пулы описаны ниже. • Пул Java (Java pool). Это фиксированный объем памяти, выделенной для вир­ туальной маши н ы Java (Virtua\ Java Machine JVМ ) , которая действует в базе данных. В Oracle \ Og и последующих версиях пул Java может оперативно изме­ няться во время работы базы данных. - • Большой пул (large pool). Этот пул используется подключениями посредством разделяемого сервера для памяти сеанса, средствами параллельного выполнения для буферов сообщений и резервны м копированием RМAN для буферов диско­ вого ввода-вывода. Большой пул допускает оперативное изменение размера. • Разделяемый пул (shared pool). Этот пул содержит разделяемые курсоры, хра­ нимые процедур ы , объекты состояния , кеш и словаря данных и м ногие десят­ ки других элементов данных. Размеры этого пула могут оперативно изменять­ ся, начиная с верси и Oracle9i. • Пул Streams (Streams pool). Этот пул памяти применяется инструментами сов­ местного использования данных, такими как Oracle Go\denGate, Oracle Strearns и т.д. Пул Streams доступен в Oracle 1 Og и последующих версиях и допускает Структуры памяти 233 оперативное изменение своего размера. Есл и он не сконфигурирован, но фун­ кциональность Streams задействована, то Oracle выделит под память потоков до l 0% объема разделяемого пула. • Неопределенный пул ("Null" pool). В действительности этот пул не и меет на­ звания . Он представляет собой память, предназначенную для хранения буфе­ ров блоков (кешированных блоков базы данных), буфера журнала повторен ия и "фиксированной области SGN' . Типичная область SGA может выглядеть так, как показано на рис. 4. 1 . Область SGА Разделяемый пуn ( Большой пуn ( Пyn Java ) J (Фиксированная область SGА J [Буфер журн,.j повторения Буферы блоков ) Рис . 4. 1 . Ти пичная область SGA Наибольшее влияние на общий размер области SGA оказывают следующие па­ раметры. _ • JAVA_POOL_S I ZE. Управляет размером пула Java. • S HARE D POOL_ s I Z E . Управляет размером разделяемого пула (до не которой степени). • LARGE POOL_S I ZE. Управляет размером большого пула. • STREAМS _ POOL_s I ZE. Управляет размером пула Streams. • DB_ *_CACHE_S I ZE. Восемь параметров CACHE_S I Z E управляют размерами раз­ личных доступных кешей буферов. • LOG_BUFFER. Управляет размером буфера повторения (до некоторой степени). • S GA_TARGET . Применяется с автоматическим управлением памятью SGA в Oracle I Og и последующих версиях; может изменяться оперативным образом. • SGA_МAX_S I ZE. Используется для управления размером области SGA. • MEMORY_TARGET. П р именяется с автоматическим управлением памятью ( как для PGA, так и для SGA) в Oracle l lg и последующих версиях. • MEMORY_МAX_S I ZE. Используется для управлен ия максимальным объемом па­ мяти , которого СУБД Oracle должна стараться придерживаться в отношении размеров PGA и SGA при автоматическом управлении памятью в Oracle l lg и последующих версиях. В действительности это лишь цель; область PGA может превосходить оптимальный размер, если количество пользователей вырастает сверх некоторого уровня , либо когда сеанс (сеансы) распределяет большие не­ управляемые фрагменты памяти , как демонстрировалось ранее. 234 Глава 4 В Oracle9i различные компоненты SGA требуют настройки своих размеров адми ­ н истратором базы данн ых вручную. Однако в Oracle ! Og и последующих версиях по­ явилась возможность автоматического управления разделяемой памятью, посредс­ твом которого экземпляр базы дан ных будет выделять и перераспределять память для разнообразных компонентов SGA во время выполнения в соответствии с изме­ няющейся рабочей нагрузкой . Более того, в Oracle l !g доступен еще один вариант: автоматическое управление памятью, при помощи которого экземпляр базы данных не только автоматически управляет памятью SGA и PGA, но также подбирает оп­ тимальные размеры для областей SGA и PGA, автоматически перераспределяя эти части памяти , когда это представляется разумн ым. П рименение автоматического управления разделяемой памятью в Oracle ! Og и последующих версиях обеспечивается простой установкой параметра S GA_TARGET в желаемый размер SGA, оставляя незатронутыми остальные параметры, связанные с SGA. Экземпляр базы данных будет выделять память для различных пулов по мере необходимости и с течением времени даже перераспределять память между пулами . При использовани и автоматического управления памятью в Oracle l lg и последу­ ющих версиях вы просто устанавливаете значение MEMORY_TARGET. Экземпляр базы данных затем выберет оптимальные размеры для областей SGA и PGA, и эти ком­ поненты будут соответствующим образом настроен ы и станут выполнять собствен­ ное управление памятью в отведен н ых и м пределах. Более того, база данных может и будет изменять размеры выделенных областей SGA и PGA по мере дальнейшего изменения рабочей нагрузки . Независи мо от применяемого управлен ия памятью - автоматического или руч­ ного - вы обнаружите , что память различным пулам в SGA выделяется блокам и, которые называются гранулами. Одна гранула (granule) - это область памяти разме­ ром 4, 8 или 16 Мбайт. Гранула является наименьшей еди ницей выделения памяти , поэтому если запросить для пула Java память 5 М байт при размере гранулы 4 М байт, то в действительности Oracle выделит для пула Java объем 8 М байт (8 - наименьшее целое число, большее или равное 5 и кратное размеру гранулы, равному 4) . Размер гранулы определяется размером области SGA (в определенной степени это утверж­ дение выглядит рекурсивным, т. к. размер SGA зависит от размера гранулы). Размеры гранул , используемых для каждого пула, можно выяснить, запросив представление V$ S GA_ DYNAМI C_COMPONENT S . Фактически это представление можно применять для выяснения влияния общего размера SGA на размер гранул : EODA@ORA 12CR 1> show pa ramete r sga_target NАМЕ ТУ РЕ VALUE s ga_target big i nteger 2 5 6М EODA@ORA1 2CR1> se1ect component , granu1e s i ze from v$ sga_dynami c_ components ; COMPONENT s ha red pool l a rge pool j ava pool s t reams pool DE FAULT b uf f e r cache GRANULE S I Z E 4 194304 4 1 9 4 30 4 4 1 94304 4 1 94304 4 1 94304 Структуры памяти КЕЕ Р bu ffer cache RECYCLE bu f fe r cache DE FAULT 2К buffer cache DE FAULT 4 К buffer cache DE FAULT 8 К buffer cache DE FAULT 1 6К buffer cache DE FAULT 32К buffer cache Sha red IO Pool Data Trans fer Cache ASM Bu ffer Cache 15 rows selected . 1 5 строк выбрано . 235 4 1 94 3 0 4 4 1 94 3 0 4 4 1 94 3 0 4 4 1 94 3 0 4 4 1 94 3 0 4 4 1 94304 4 1 94 3 0 4 4 194304 4 1 94 3 0 4 4 1 94304 Н а заметку! Эта и нформация о памяти SGA относится к экземпляру Oracle , запущенному с файлом параметров инициализации из п редыдущего примера. В этом файле параметров мы самостоятельно указали размеры SGA и PGA. Вследствие этого м ы испол ьзуем авто­ матическое управление разделяемой памятью и автоматическое управление памятью PGA, но не средство "автоматического управления памятью" из Oracle 1 1 g (и последующих вер­ сий ) , которое само должно устанавливать и изменять размеры областей PGA/SGA. В этом примере применялось автоматическое управление разделяемой памятью, а размер SGA устанавл ивался через единстве н н ы й параметр S GA_TARG E T . Когда размер SGA не превы шает прибл из ительно l Гбайт, размер гранул ы составляет 4 Мбайт. Когда размер SGA увеличивается до некоторого порога, превы шающего l Гбайт (конкретное значение варьируется в зависимости от операционной системы и даже от выпуска) , размер гранулы возрастает. Сначала м ы вернемся к использова­ нию хранимого файла параметров, чтобы облегч ить изменение SGA_TARGET : SYS@ORA12CR1> create s p f i l e f rom p fi l e ; Fi le created . Файл создан . SYS@ORA12CR1> sta rtup force ; ORACLE instance s ta rted . Экземпляр ORACLE запущен . Tota1 Sys tem G1obal Area Fixed S i z e Va riaЬle S i ze Database Bu f fers Redo Bu ffers Databas e mounted . Databas e opened . Общий размер системной глобальной обла сти Размер фиксированной обла сти Размер переменной области Буферы базы данных Буферы пов торения База данных смонтирована . База данных открыта . 2 67 2 2 7 1 3 6 2287336 180357400 79691776 4 8 90 62 4 byte s bytes bytes byte s byte s 2 6 722 71 3 6 228 733 6 1 8035 7 4 0 0 79 691 7 7 6 4 8 9 0 62 4 байтов байтов байтов байтов байтов Н а заметку! Есл и ваш экземпляр в текущий момент функциони рует, то команда S TART U P FORCE завершит его работу ( режим п рекращения) и затем перезапустит. 236 Глава 4 Далее м ы модифицируем параметр S GA_TARGET: SYS@ORA1 2 CR 1 > alter s ystem s et s ga_t a rget = 1 5 12m s cope=sp fi1e ; Sys tem altered . Система изменена . SYS @ ORA1 2CR1> sta rtup force ORACLE instance s tarted . Экземпляр ORACLE запущен . 1 5 8 67 0 8 4 8 0 2288824 4 0 2 65 4 0 2 4 1174405120 7 3 60 5 1 2 Total Sys tem Global Area Fixed S i z e VariaЬle S i ze Databas e Bu ffers Redo Bu ffers Database mounted . Database opened . bytes bytes bytes bytes bytes SYS@ ORA 1 2 CR 1 > show pa ramet er s ga_ta rget NАМЕ ТУРЕ VALUE s ga_target Ьig i ntege r 1 5 2 0М Теперь посмотрим на компоненты SGA: SYS@ORA1 2 CR 1 > select component , g ranu1e_s i ze from v$sga_dynamic_components ; COMPONENT GRANULE S I ZE shared pool l a rge pool j ava pool s t reams роо1 DE FAULT b u f f e r cache КЕЕ Р bu f fe r cache RECYCLE b u f f e r cache DE FAULT 2К buffer cache DE FAULT 4К buffer cache DEFAULT 8К buffer cache DE FAULT 1 6К bu ffer cache DE FAULT 32К b uf f e r cache Shared I O Pool Data Tran s fer Cache ASM Bu f fe r Cache 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 1 67 7 7 2 1 6 15 rows selected . 1 5 строк выбрано . Н есложно заметить, что при размере SGA в 1 ,5 Гбайт память под пулы будет вьще­ ляться с гранулами 1 6 Мбайт, поэтому размер любого пула будет кратным 1 6 Мбайт. Имея это в виду, давайте по очереди рассмотрим основные компоненты SGA. Ф и ксированная область SGA Фиксированная область SGA (fixed SGA) - это компонент SGA, размер которого за­ висит от платформы и выпуска. Эта область "компилируется" в сам двоичный модуль Orac1e во время установки (отсюда и название "фиксированн ая " ) . Фиксированная область SGA содержит набор перемен н ых, которые указывают на другие компонен- Структуры nамят и 237 ты SGA, и перемен ных, содержащих значения различных параметров. Размер фикси ­ рованной области SGA н е доступен для управлен ия с о стороны адми н истратора базы данных или программиста и, как правило, он очень мал. Эту область можно считать разделом "начальной загрузки" SGA - чем-то таким, что Orac1e использует внутрен ­ н е для нахождения других элементов и фрагментов области SGA. Буфер повторения Буфер повторения (redo buffer) - это место, где данные, которые должны быть за­ писаны в оперативные журналы повторен ия (online redo 1og) , будут временно кеш иро­ ваться перед их записью на диск. Поскольку передача из памяти в память выпол ня­ ется значительно быстрее передачи из памяти на диск, применение буфера журнала повторения может ускорить работу базы данных. Дан ные будут храниться в буфере повторения не очень долго. В действительности процесс LGWR инициирует сброс со­ держимого этой области на диск в одном из перечисленных ниже сценариев: • каждые три секунды ; • когда выдается COMM I T или ROLLBACK; • когда процесс LGWR получает запрос на перекл ючение журнальных файлов; • когда буфер повторения заполняется на одну треть ил и объем содержащихся в нем кеш ираванн ых данных журнала повторения составляет 1 Мбайт. По этим причи нам лишь очень редкая система выи грает от буфера повторения с размером в пару десятков мегабайт. Крупная система с множеством параллельных транзакций может извлеч ь некоторое преимущества из бол ьшого буфера журнала повторен ия , поскольку пока процесс LCWR (отвечающий за сброс на диск буфера журнала повторения) записы вает порцию журнального буфера, другие сеансы смо­ гут его заполнять. В общем случае дл ительно выпол няющаяся транзакция , которая генерирует много данных повторения, получит максимальный выигрыш от исполь­ зования большого, а не обычного журнального буфера, т. к. она будет постоян н о заполнять часть буфера журнала повторения пока процесс L C W R занят записью на диск другой части буфера (мы детально раскроем феномен зап исывания незафикси ­ рованных данных в главе 9 ) . Ч е м крупнее и дол ьше дл ится транзакция , тем больше преимушеств она может извлечь из большого журнального буфера. Стандартный размер буфера повторения, управляемый параметром LOG_BUFFER, варьируется в ш ироких пределах в зависимости от операционной системы, версии базы данных и настроек других параметров. Вместо попытки объяснить, каким дол­ жен быть наиболее распространенный стандартный размер (его просто нет) , я отсы ­ лаю вас к документации по применяемой верси и Orac1e (руководство Oracle Database Reference) . Мое стандартное значение LOG_BUFFER, учитывая ранее запущенный эк­ земпляр с SGA размером 1 , 5 Гбайт, отображается с помощью следующего запроса: EODA@ORA12CR1> select va lue , i sde fault 2 from v$pa rameter 3 whe re nате = ' log_buf fe r ' 4 1 VALUE I S DEFAULT 7036928 TRUE 238 Глава 4 Размер составляет около 7 Мбайт. М и нимальный размер стандартного журналь­ ного буфера зависит от операционной системы. Если вы хотите выяснить, каков он, просто установите LOG_BUFFER в l байт и перезапустите базу данных. Например, в своем экземпляре Oracle Linux я получаю такой вывод: EODA@ORA12CR1> a l t er s ys tem set log_buffer=1 scope=spfi l e ; System altered . Система изменена . EODA@ORA 1 2 C R 1 > connect 1 as s ysdЬa ; Connected . Подключено . SYS@ ORA1 2CR1> startup force ; ORACLE ins tance s tarted . Экземпляр ORACLE запущен. Total System Global Area 1586708480 Fixed S i ze 2288824 Va r i aЫe S i z e 4 0 2 65 4 0 2 4 Da taba s e Buffers 1174405120 Redo Bu ffers 7360512 Da tabas e mounted . Databa s e opened . SYS@ ORA1 2CR1> show paramete r log_buffer bytes bytes bytes bytes bytes NАМЕ ТУРЕ VALUE log_buffer integer 1703936 SYS@ ORA1 2CR1> s e l e ct 1 7 0 3 9 3 6 / 1 0 2 4 / 1 0 2 4 from dual ; 1703936/ 1024/1024 1 . 62 5 Наименьшим размером буфера, который я действительно могу иметь, независи ­ мо от установок в этой системе будет l ,625 М байт. Ке ш буф еров блоков До сих пор мы рассматри вали сравнительно небольшие ком поненты области SGA. Теперь нам предстоит взглянуть на компонент с потенциально очень большим размером. В кеше буферов блоков Oracle хранит блоки базы данных перед их запи­ сью на диск и после их чтения с диска. Для нас это критически важная область SGA. Если сделать ее сли ш ком малой , то запросы будут выполняться бесконечно долго. Если же сделать ее сли ш ком большой, то это " посадит на голодный паек" остальные процессы (т.е. выделен ному серверу не останется достаточного пространства памяти для создания его области PGA, и мы даже не сможем запустить базу данных) . В ранних выпусках Oracle существовал только оди н кеш буферов блоков, и все блоки из любых сегментов помещал ись в эту еди нствен н ую область. Н ач иная с Oracle 8.0, для хранения кешираванн ых блоков из различных сегментов в SGA мож­ но использовать три местоположен ия . • Стандартный пул (default pool). М есто, где обычно кеш ируются блоки всех сег­ ментов. Это исходн ый - и ранее еди нственный - буферный пул . Структуры п амяти 239 • Удерживающий пул (keep pool). Запасной буферн ы й пул , в котором по согла­ шению будут храниться часто используемые сегменты , перемещенные из стан­ дартного буферного пула в связи с необходимостью освобожден ия места для других сегментов. • Рециклирующий пул (recycle pool). Запасной буферный пул , где по соглаше­ нию будут храниться большие, очен ь редко используемые сегменты , которые приводят к длительному сбросу дан н ых на диск, но не предоставляют н и каких особых преимуществ, поскольку к тому моменту, когда блок потребуется сно­ ва, он уже будет удален из кеша по причине устаревания . Эти сегменты можно выделять из сегментов стандартного и удерживающего пулов для предотвраще­ ния их полного удаления из кеша по истечен и и заданного времен и хранен ия . Обратите вн иман ие, что п р и оп исани и удерживающего и рециклирующего пу­ лов применялось выражение "по соглашению" . В действительности н и кто не при­ нуждает использовать эти пулы только так, как описано. Фактически все три пула управляют блоками почти идентичным образом ; применяемые ими алгоритмы удале­ ния вследствие устаревания или кеширования блоков не имеют существенных отличий. Цел ь использования этих пулов - предоставление адми н и стратору базы дан н ых возможности разделения сегментов на горячие, теплые и " не заслуживающие ке­ ширования" области . Теоретически объекты в стандартном пуле должны были быть достаточно горячими (т.е. применяться довольно часто) , чтобы гарантировано оста­ ваться в кеше при любых обстоятельствах. Кеш будет удерживать такие объекты в памяти из-за их очень высокой популярности . Н екоторые сегменты могут быть до­ статочно популярными, но не по-настоящему горячими , тогда эти блоки считаются теплыми. Они могут сбрасываться из кеша на диск с целью освобождения места для блоков, которые применя ются не настолько часто ( " не заслуживающие кеш ирова­ ния" блоки ) . Для сохранения таких теплых блоков в кеше можно выпол нить одно из следующих действий. • Н азначить эти сегменты удержи вающему пулу, чтобы позволить тепл ы м бло­ кам оставаться в буферном кеше подальше. • Н азначить " не заслужи вающие кеш ирования" сегменты рецикл и рующему пулу, сохраняя размер этого пула достаточно маленьким , чтобы операции по­ мещения блоков в кеш и их удаления из него вы пол нялись чаще (это позволит снизить накладн ые расходы , связан ные с управлением всеми блоками ) . Л юбое из этих двух де йствий увеличи вает объем работы , которую должен в ы ­ полнять адм инистратор базы данных, поскольку е м у придется думать о трех кешах, их размерах и назначенных им объектах. Следует также помн ить, что между эти ­ ми областями отсутствует механизм обмена данными, поэтому, если удерживающий пул содержит бол ьшой объем неиспользуемого пространства, то он не сможет пе­ редать его перегруженному стандартному или рециклирующему пулу. В общем, эти пулы представляют собой очень эффективные средства н изкоуровневой настройки , к которым, однако, следует прибегать после применения всех других средств (есл и запрос можно переписать так, чтобы он выполнял только одну десятую часть опе­ раций ввода-вывода, я предпочту эту возможность вместо настройки множества бу­ ферных пулов) . 240 Глава 4 Начиная с Oracle9i, в дополнение к стандартному, удерживающему и рецикли­ рующему пулам адми н истраторы баз данных получили в свое распоряжение еще четыре необязательных кеша, D B_nK_CACHE_ S I Z E . Эти кеш и были добавлены дЛЯ поддержки в базе данных нескол ьких размеров блоков. До выхода версии Oracle9i база данн ых должна была и меть единственный размер блока (обычно 2, 4, 8, 1 6 или 32 Кбайт) . Н ачи ная с Oracle9i, база данных может располагать стандартным разме­ ром блока, который задает размер блоков, хранящихся в стандартном , удерживаю­ щем и рециклирующем пулах, а также до четырех нестандартных размеров блоков, как объяснялось в главе 3 . Управление блоками в этих буферных кешах производится тем же способом , что и управление блоками в исходном стандартном пуле - используемые алгоритмы не претерпели н и каких изменени й . Давайте теперь посмотрим, как осуществляется уп­ равление блоками в этих пулах. Управление блоками в кеше буферов Для простоты предположим, что в системе существует только стандартный пул. П оскольку управление остальными пулами выпол няется точно так же , достаточно обсудить только оди н из них. П о существу управление блокам в кеше буферов производится из единственной области с помощью двух различных указывающих на них списков: • список грязных (dirty) блоков, которые должны записываться процессом записи блоков базы данных ( DBWn; мы рассмотрим этот процесс несколько позже); • сп исок чистых (nondirty) блоков. В Oracle 8.0 и предшествующих версиях список чистых блоков назывался спис­ ком недавно использовавш ихся блоков ( Least Recently Used - LRU ) . В нем блоки перечислялись в порядке их испол ьзования. В Oracle8i и последующих версиях алго­ ритм управления этими блоками был несколько модифицирован . Вместо того чтобы поддерживать с писок блоков, упорядочен н ы й в определенном физическом поряд­ ке, Oracle задействует алгоритм со счетчиком обращений, который инкрементирует значение счетч и ка, с вязанного с блоком , при обнаружении дан ного блока в кеше. Значение счетчика увеличивается не при каждом попадании блока, а приблизитель­ но каждые три секунды, если блок встречается постоян но. Увидеть этот алгоритм в работе можно на примере одного из действительно загадочных наборов таблиц таблиц Х $ . Эти таблицы абсолютно не документированы Oracle , но время от време­ ни информация о них просачивается во внеш ний мир. На заметку! В последующих при мерах я и мею дело с пользователем, подкл юченным с при­ вилеги я м и S Y S DBA, потому что таблицы Х $ по умолчани ю види мы только этой учетной зап и с и . На практике вы не должны применять учетную запись с привилегиями S YS DBA для вы полнения запросов. Необходимость в запраши вании и нформации о блоках в кеше буферов - редкое исключение из этого правила. Табли ца Х $ В Н отображает и нформаци ю о блоках в ке ше буферов блоков (она предоставляет больше информации , чем документированное представление V$BH). Здесь можно наблюдать и н крементирование значен ия счетчика обращений при об­ наружен иях блоков. Стру к туры памят и 241 Для отыскания пяти "самых горячих в н астоя щий момент блоков" и соедине­ н ия этой и нформации с представленнем DBA_ OBJECTS для выяснения сегментов, которым они принадЛежат, можно выпол нить приведенный н иже запрос к упомяну­ тому представлению. Запрос упорядочи вает строки в табли це Х $ ВН по столбцу т с н (touch count - счетч и к обращен и й ) и сохраняет первые пять строк. Затем и нфор­ мация Х $ ВН соединяется с представленнем DBA_OBJECTS по соответствию столбца Х$ВН . OBJ С DBA-OBJECT S . DATA-OBJECT- I D. SYS @ORA12CR1> sel ect t ch , fi l e # , dЬaЬ l k , 2 case when obj = 4 2 9 4 9 67 2 9 5 then 1 rbs /compat segment 1 3 4 e l s e ( s e l ect max ( 1 ( 1 1 l ob j ect_type l 1 1 ) 1 1 1 owne r 1 1 1 • 1 1 1 obj ect_name ) 1 1 5 6 decode ( count ( * ) , 1 , 1 1 , 1 maybe ! 1 ) f rom dЬa_obj ects 7 8 where data_obj ect_id = X . OBJ ) 9 end what 10 from ( 1 1 select tch , fi l e# , dbaЬ l k , obj 12 from x$bh 1 3 where s tate < > О 1 4 order Ь у tch de s c 15 ) х 1 6 whe re rownum <= 5 17 1 ---------- тсн ---------- F I LE# ---------- DBAВLK WНАТ 98 13 13 11 11 1 1 1 1 1 2825 337 62 1 1 7 4377 209 ( INDEX ) ( INDEX ) ( INDEX ) ( INDEX ) ( ТАВLЕ ) ------------------- - ---- ---- -- S YS . I JOB NEXT S YS . I OBJ1 S YS . I -OBJ1 SYS . SYS С 0 0 8 1 9 SYS . USER$ maybe ! На заметку! Выражение (2.32 - 1 )1 или 4 294 967 2951 в операторе c a s e - это "магическое" число, используемое для пометки "специальных" блоков. Если необходи мо понять, с чем связан лежащий в основе блок, воспользуйтесь запросом s e le c t * f r om dЬа _ e x t e n t s w h e r e f i l e id = < F I LE # > and Ь l o c k i d <= < DBABLK> and Ь l o c k id+Ь l o c ks - 1 > = <DBABLK>. У вас может возникнуть вопрос о том , что означает ' ma ybe ! ' и зачем приме­ няется функция МАХ ( ) в предыдущем скалярном подзап росе. П ричина в том , что , как видно в следующем запросе, столбец DATA_OBJECT_I D не является " первичным ключом" в представлении DBA_OBJECT: SYS@ORA1 2CR1> select data_obj ect_i d , count ( * ) 2 from dЬa_obj ects 3 where data_obj ect_id i s not null 4 group Ьу data_obj ect_id 5 having count ( * ) > 1 ; 242 Гл ава 4 DATA OBJECT I D -------------- COUNT ( * ) ---------- 2 3 3 7 18 3 3 3 2 3 337 6 29 620 2 781 8 750 64 10 1 0 rows se1 ected . 1 О строк выбрано . Это обусловлено нал ичием кластеров (обсуждаются в главе 1 0) , которые могут содержать несколько таблиц. П оэтому при выполнении соединения таблицы Х $ ВН с представлени ем DBA_ OBJECTS для вывода имени сегмента формально необходи­ мо перечисл ить имена всех объектов в кластере, т. к. блок базы данных не прина­ длежит постоянно какой-то одной таблице. М ожно даже наблюдать, каким образом Oracle и н крементирует значения счетчи ка обращений к блоку, которы й запраш ива­ ется многократно. В этом примере мы будем использовать " магическую" таблицу DUAL - нам известно, что она содержит одну строку и один столбец. Н а заметку! До в ыхода Oracle 1 Og запрос табли цы DUAL при вел бы к полному скан ирова­ нию реал ьной табл и цы по имени DUAL, хранящейся в словаре данных. При включенной функции автоматической трассировки и выполнении запроса SELECT DUMMY FROM DUAL во всех выпусках Oracle вы наблюдали бы наличие ряда операций ввода-вы вода (согласо­ ванных операций чтения ) . В Oracle 9i и предшествующих версиях в случае выдачи запроса SELECT S Y S DATE FROM DUAL или переме н н а я : = S Y S DATE В среде PL/SQL также будут п роисходить операци и реального ввода-вы вода. Тем не менее, в Oracle 1 0g этот запрос S E LECT S Y S DATE распознается как не нуждающийся в действительном обращении к таб­ лице DUAL ( из-за того , что вы не запрашиваете из DUAL столбец или идентификатор стро­ ки) и выполняется подобно вызову функции . Следовательно, таблица DUAL не подверга­ ется полному сканированию - приложению возвращается только значение SYSDATE . Это небольшое изменение может радикально уменьшить количество согласованных чтений в системе, которая интенсивно работает с табли цей DUAL. Таким образом, при каждом выполнении следующего запроса мы должны обра­ щаться к реальной табли це DUAL (поскольку явно ссылаемся на столбец DUMMY): SYS @ORA1 2CR1> s elect tch , f i l e # , dЬaЬ l k , DUММУ 2 from x $bh , ( select dummy from dual ) 3 where obj = ( s e lect data_obj ect_id from dЬa_obj ects 4 5 where obj ect_name = ' DUAL ' 6 and data_obj ect_id i s not null ) 7 1 F I LE# ---------- ---------- ---------- DBABLK D 1 2 1 1 92 9 928 х тсн х Структуры nамяти 243 SYS@ORA12CR1> ехес dЬms_loc k . s leep ( 3 . 2 ) ; PL/ SQL procedure s ucce s s ful l y comp l eted . Процедура PL/SQL успешно выполнена . SYS@ORA1 2 CR1> / те н F I LE # DBAВLK D 2 2 1 1 1416 1 4 17 х х SYS@ORA1 2 CR1> ехес dЬms_loc k . s l eep ( 3 . 2 ) ; PL/SQL procedure succe s s ful l y completed . Процедура PL/SQL успешно выполнена . SYS@ORA12CR1> / тсн F I LE # DBAВLK ---------- ---------- ---------- 4 4 1 1 1416 1417 D х х SYS @ORA12CR1> ехес dЬms_loc k . s leep ( 3 . 2 ) ; PL/SQL procedure s ucce s s ful l y comple ted . Процедура PL/SQL успешно выполнена . SYS @ORA12CR1> / те н F I LE # DBAВLK ---------- ---------- ---------- 5 5 1 1 1416 1 4 17 D х х Я ожидаю, что вывод будет варьироваться в зависимости от выпуска Oracle ; вы вполне можете наблюдать возвращение более двух строк. М ожет оказаться , что зна­ чение счетчи ка тсн и н крементируется не каждый раз. В многопол ьзовательской системе результаты будут еще более непредсказуемым и . СУБД Oracle будет пытаться инкрементировать значение тсн каждые три секунды ( время последнего обновления столбца т с н отображается в столбце T IM ) , но точное значение не столь уж важно, поскольку оно достаточно близко к действительному. Кроме того, через определен­ н ые и нтервалы времени Oracle будет намеренно " охлаждать" блоки и декременти ­ ровать значение счетчика тсн. П оэтому, если вы запускаете этот запрос в своей сис­ теме, то будьте готовы к получен и ю отличающихся результатов. Итак, в Oracle8i и последующих версиях буфер блоков больше не перемешается в голову списка, как было ранее; вместо этого он остается в списке на своем месте и имеет увеличивающийся счетчи к обращений. Однако блоки будут иметь тенденцию к " перемещению" по списку с течением времени. Слово " перемещение" приведено в кавычках, потому что физически блок не перемещается . В действительности под­ держиваются несколько списков, которые указы вают на блоки , а блок будет " пе­ ремещаться " из списка в список. Например, измененные блоки задаются грязны м списком (блоков, которые должн ы быть записаны на диск процессом DBWn) . Кроме того, по мере их повторного испол ьзования с течением времен и , когда буферны й кеш оказывается практически заполненн ым и какой -то блок с н изким значением счетчика обращений освобождается , такой блок будет " помещен" прибл изительно в середину списка с новым блоком данн ых. 244 Гл ава 4 П ол н ы й алгоритм , применяемый для управлен ия этими спискам и , достаточно сложен и слегка изменяется от вы пуска к выпуску Oracle по мере внесения усо­ вершенствовани й . П одробности реализаци и не и меют особого значения для раз­ работчи ков; достаточно помнить о том , что и нтенсивно используемые блоки будут кеш ироваться, а блоки , которые применяются редко, не будут кеш ироваться на дли­ тельный период. Н а заметку! Если вы следите за изложением , запуская все примеры в своей базе данных, воспользуйтесь возможностью выйти от имени учетной зап иси SYS DBA и затем войти под своей учетной записью! Использование нескольких размеров блоков Н ачиная с Oracle9i, в одной базе данных можно и меть несколько размеров бло­ ков . До этого все блоки в одной базе дан ных обладали одни м и тем же размером, и для изменения размера блоков нужно бьuю перестраивать всю базу данн ых. Теперь в базе данных можно одновременно применять "стандартный" размер блоков (раз­ мер блоков, указанный при первоначальном создани и базы данн ых; он использует­ ся для табличных пространств S Y S T EM и TEM PORARY) и до четырех других размеров блоков. Каждому уни кальному размеру блоков должна быть назначена собственная область буфер ного кеша. Стандартн ый, удерживающи й и рециклирующий пулы бу­ дут кешировать только блоки стандартного размера. Чтобы применять в базе данных нестандартные блоки , необходимо соответствующим образом сканфигурировать бу­ ферный пул. В следующем примере размер стандартных блоков составляет 8 Кбайт. Я поп ыта­ юсь создать табличное пространство с размером блоков 1 6 Кбайт: EODA@ ORA1 2 CR1> create taЬlespace t s_l б k 2 dat a f i l e ' / tmp/ t s l б k . dЬf ' 3 s i z e Sm 4 Ьlocks i z e l б k ; create taЫespace t s_l б k * ERROR at l ine 1 : ORA- 2 9 3 3 9 : taЬlespace Ыосk s i z e 1 6 3 8 4 does not match configured Ыосk sizes ОПМБКА в строке 1 : ORA -29339 : размер блоков та бличного пространства , равный 1 6384 , не соответствует сконфигурированным размерам блоков EODA@ORA12CR1> s how parameter l б k NАМЕ ТУРЕ VALUE dЬ l б k cache s i z e b i g integer О В настоящ и й момент из-за того, что не был сконфи гурирован кеш 1 6 Кбайт, такое табличное пространство создать нел ьзя . Для исправления ситуаци и можно было бы предпринять одн о из следующих действий . М ожно установить параметр DB _ l б К_САС Н Е_ S I ZE и перезапустить базу дан н ых. М ожно сжать оди н из других компонентов SGA, чтобы освободить место в существующей области SGA под кеш 1 6 Кбайт. Или же, если бы значение параметра S GA_МАХ_ s I ZE было больше текуще­ го размера SGA, можно было бы просто выделить кеш 1 6 Кбайт. Структуры nамяти 245 На заметку! Нач иная с версии Oracle9i, размеры разнообразных ком понентов SGA можно изм енять во время работы базы дан ных. Если нужна возможность "увеличения" разме­ ра SGA свыше начального расп ределен и я , понадобится установить для S GA_МАХ_ s r Z E значение, которое больше выделенного объем а SGA. Наnример, если после заnуска раз­ мер SGA составлял 800 Мбайт и требуется добавить к буферному кешу дополн ительные 200 Мбайт, то придется установить SGA_МAX_S I Z E в 1 Гбайт или большее значение, что­ бы разреш ить подобное разрастание. В этом примере я установлю DB_l бК_САСНЕ s I Z E и перезапущу экземпляр, пос­ кольку использую автоматическое управление разделяемой памятью и не хочу вруч­ ную настраивать другие кеш и : EODA@ORA12CR1> a l t e r system set s ga_target=30 0m s cope=sp f i l e ; System altered . Система изменена . EODA@ORA12CR1> alter sys tem set db_l б k_cache_s i z e = 1 6m s cope=sp f i l e ; Sys tem altered . Система изменена . EODA@ORA12CR1> connect 1 as s ysdЬa Connected . Подключено . SYS@ORA1 2CR1> sta rtup force ORACLE ins tance s ta rted . ORACLE ins tance started . Экземпляр ORACLE запущен . Total Sys tem Global Area 313159680 2 2 8 7 8 64 Fixed S i ze 180356872 VariaЫe S i ze Databa se Buffe rs 125829120 4 68 5 8 2 4 Redo Bu f fers Database mounted . Databa se opened . SYS@ORA1 2CR1 > show pa rameter l б k byte s bytes bytes bytes bytes NАМЕ ТУРЕ VALUE dЬ l б k cache s i ze big intege r l бМ Итак, я определил еще оди н буферн ы й кеш , предназначен н ы й для кеширования блоков размером 1 6 Кбайт. Стандартный пул будет потреблять остальное пространс­ тво буферного кеша, что можно увидеть, запросив V $ S GAS TAT . Эти два буферных кеша являются взаимно исключающими: если оди н из них "запол няется " , он не мо­ жет использовать пространство в другом . Это предоставляет адм и н истратору базы данных очень высоки й уровень контроля над испол ьзованием п амяти , но за счет увеличения сложности и трудоемкости управления . Фун кционал ьность множест­ ва размеров блоков не задумывалась как средство повышения производительности или настройки (если вам нужно несколько кешей , то у вас уже есть стандартны й , удержи вающий и реци клирующий пул ы ) . Вместо этого о н а направлена на подде­ ржку переносимых табличных пространств - возможности изъятия файлов форма­ тированных данных из одной базы данных и их перемещение либо присоединение 246 Глава 4 к другой базе дан н ых. Средство было реализовано для того, чтобы можно бьuю из­ влечь файлы дан н ых из транзакционной системы , в которой применяются блоки размером 8 Кбайт, и перенести эту и нформацию в хранил и ще данных с блоками размером 1 6 или 32 Кбайт. Тем не менее , поддержка нескольких размеров блоков очень удобна при провер­ ке теоретических предположе н и й . Если нужно посмотреть, как база данных будет работать с другим размером блока (напри мер, какой объем памяти будет зан имать определенная таблица, если вместо блоков 8 Кбайт использовать блоки 4 Кбайт) , то это легко проверить, не создавая экземпляр полностью новой базы данных. Нескол ько размеров блоков можно применять также в качестве инструмента очен ь точной настройки определенного н абора сегментов, предоставляя им собс­ твенные закрытые буферные пул ы . Или же в смешанной системе пользователи, вы­ полня ющие транзакци и , могл и бы применять оди н набор данных, а пользователи учетных/складских данных - другой . Транзакционные данн ые получают преиму­ щества от блоков меньшего размера из-за меньшего соперничества за блоки (мень­ ше дан н ых/строк на блок означает, что в общем случае меньше людей будут одно­ временно обращаться к одному и тому же блоку) , а также из-за лучшей утилизации буферного кеша (пользователи считывают в кеш только и нтересующие их данные ­ оди ночную строку ил и же небол ьшой набор строк) . Учетные/складские данные, которые могут быть основаны на транзакционных данных, получают выигрыш от блоков большего размера частично из-за меньших накладных расходов, связанных с блоками (в целом для их хране н ия будет требоваться мен ьше пространства), и, возможно, из-за больших размеров логических блоков ввода-вывода. И поскольку в случае учетн ых/складских данных соперничество за обновление не возникает, то наличие большего количества строк в блоке - не проблема, а преимушество. Более того, пользователи , выполня ющие транзакции, в действительности получают в свое распоряжение собственный буферны й кеш ; им не придется беспокоиться о том , что запросы на генерацию отчетов переполнят их кеш . Н о в общем случае стандартного, удерживающего и реци клирующего пулов должно быть вполне достаточно для оптимальной настройки кеша буфера блоков, а м ножество размеров блоков следует применять главны м образом для переноса дан­ н ых из одной базы данных в другую и , возможно, в смешанных системах с генера­ цией отчетов и выполнен ием транзакций. Р азделяемый пул Разделяемый пул (shared pool) - одна из наиболее важных частей области SGA, особенно с точки зрения производительности и масштабируемости. Слишком ма­ ленький разделяемый пул может привести к такому снижению производительности , что система будет казаться "зависшей " . Слишком большой разделяемый пул может дать аналогичный эффект. Некорректное использование этого пула также может вы­ звать аварийную ситуацию. Что же собой представляет разделяемый пул ? В этой области Oracle кеширу­ ет множество " программ ных" дан ных. При выполнении разбора запроса здесь же кеш ируется проанал изированное представление. П режде чем приступить к разбору всего запроса, Oracle осуществляет поиск в разделяемом пуле, чтобы выяснить, не была л и уже сделана эта работа. Запущенный на выпол нение код PL/SQL также ке- Структуры памяти 247 шируется в разделяемом пуле, чтобы при следующем запуске Oracle не пришлось снова считывать его с диска. При наличии 1 000 сеансов, выпол ня ющих оди н и тот же код, только одна копия кода загружается и совместно используется всеми сеанса­ ми. В разделяемом пуле Oracle сохраняет системные параметры. Здесь же находится кеш словаря (кешированная информация об объектах базы данных) . Короче говоря , в разделяемом пуле хранится буквально все кроме разве что кухон ной утвари . Разделяемый пул характеризуется множеством небольших (обычно 4 Кбайт ил и меньше) сегментов памяти . Имейте в виду, что 4 Кбайт н е я вляется жестким пре­ делом . В ряде случаев размеры сегментов могут быть больше, но основная цель за­ ключается в применении небольших сегментов памяти для предотвращен ия фраг­ ментации, которая возникала бы, если бы память выделялась сегментами , размеры которых сильно отличались друг от друга - от очень маленьких до очень больших. Управлен ие п амятью в разделяемом пуле осуществляется на основе алгоритма LRU . В этом отношении разделяемый пул похож на буферный кеш - есл и он не исполь­ зуется , то теряется . Для изменен ия такого поведе н ия можно применять допол н и ­ тельный пакет овмs _ S HARE D_ POOL, который позволяет при нудительна закреплять объекты в разделяемом пуле. Эту процедуру можно задействовать для загрузки часто используемых процедур и пакетов во время начального запуска базы дан ных, обес­ печив при этом невозможность их устаревания . Однако в обычн ы х условиях, есл и какое-то время часть содержимого памяти разделяемого пула не используется пов­ торно, то это содержимое устаревает. Даже код P L/SQL, который может быть до­ вольно большим, управляется механизмом подкачки страниц, так что при выполне­ нии кода очень большого пакета в разделяемый пул загружается лишь действительно необходимый код, причем небольши м и порция м и . Если с ним не работать в тече­ ние продолжительного периода времени , то этот код устареет и будет удален из раз­ деляемого пула в случае его заполнения и необходимости освобожден ия места для других объектов. Простейший способ разрушения разделяемого пула Oracle - отказ от примене­ ния переменных при вязки . Как было показано в главе 1 , отказ от переменных при­ вязки может "поставить систему на колен и " по двум причинам: • система тратит непомерно большую часть времени процессара на разбор за­ просов; • система использует слишком м ного ресурсов для управления объектами в раз­ деляемом пуле как результат того, что запросы н и когда не используются пов­ торно. Если бы каждый отправленный базе данных Oracle запрос был уни кальным ( из­ за того, что в нем жестко закодированы уни кальные значе н ия ) , то концепция раз­ деляемого пула была бы большей частью ликвидирована. Разделяемый пул разраба­ тывался с расчетом на многократное использование планов запросов. Если каждый запрос я вляется совершенно новым, н и когда ранее не встречавшимся запросом , то кешираванне ведет только к увеличению накладных расходов. Разделяемый пул становится компонентом, который подавляет производительность. Ч асто, но совер­ шенно неоправданно, для решения этой проблемы м ногие п ытаются увели ч ивать размер разделяемого пула, что обычно только ухудшает положение. Когда разделяе­ мый пул неизбежно снова заполняется , он становится еще большей обузой, чем пул 248 Глава 4 меньшего размера, по той простой причине, что управление большим заполненным разделяемым пулом будет более трудоемки м , нежели управление маленьким пол­ ным пулом. Единственно правильным решением этой проблемы я вляется применение раз­ деляемого кода SQL для п овторного использования запросов. Ранее в главе 1 мы бегло рассмотрели параметр C URSOR_ S HAR I NG , которы й может служить кратков­ ременным средством решения данной проблемы. Однако единственный реальный способ ее реше н ия - применение SQL- кoдa многократного использования. Даже в самых бол ьших системах применяется максимум 1 0 000-20 000 уни кальных SQL­ операторов. В большинстве систем выполня ются только несколько сотен уникаль­ ных запросов. Следуюший реальный пример демонстрирует, к каким негативным последствиям может привести некорректное испол ьзование разделяемого пула. Меня попросили поработать над системой , в которой стандартной рабоче й процедурой была оста­ новка базы данных на ночь, очистка области SGA и повторный ее запуск в чистом состоян и и . Причина выполнения этих действий заключалась в том , что в течение рабочего дня в системе возникал и проблем ы , связанные с перегрузкой процессо­ ра, и если база дан н ых продолжала работать более одного дня , ее производитель­ ность действительно начинала деградировать. В системе применялея разделяемый пул в 1 Гбайт внутри области SGA размером 1 , 1 Гбайт. Это бьmо действительно так: О, 1 Гбайт бьmо вьщелено для буферного кеша блоков и других элементов, а 1 Гбайт был п редназначен дтiЯ кеширования уни кальных запросов, которые н икогда более не выдавались снова. П ричина холодного старта обусловли валась тем , что в случае продолжения работы системы дольше одного дня объем свободной памяти в разде­ ляемом пуле полностью исчерпывался . К этому моменту накладные расходы, свя ­ зан н ые с нал ичием устаревших структур (особенно таких круп ных) , становились настолько большими, что система переставала с ними справляться , и производи­ тельность стремительно снижалась (хотя она не бьmа высокой в любом случае, пос­ кольку системе приходилось управлять разделяемым пулом в 1 Гбайт) . Кроме того, в связи с тем , что пол н ы й разбор SQL-запросов требовал большой загрузки про­ цессора, персонал , работающи й с этой системой, постоянно стремился наращи вать количество процессорав ком пьютера. Исправление приложения и разрешение ему при менять переме н н ые привязки не только позволило сн изить предъя вляемые к компьютеру аппаратн ые требован ия (компьютер и без того обладал значительно бо­ лее мощным процессором , чем действительно было необходимо) , но и высвободить память, выделенную дтiЯ различных пулов. В результате вместо 1 Гбайт разделяемо­ му пулу бьm и выделен ы 1 00 М байт, которые н и когда не заполнялись полностью в течение м ногих недель непрерывной работы базы данных. П р и веду последн и й комментари й п о поводу разделяемого п ула и параметра S HARE D_ POOL_ s I Z E . В Oracle9i и предшествующих версиях не существовало ника­ кой прямой взаимосвязи между результатом выполнения следующего запроса: ops$t kyte@ORA9IR2> select sum (bytes ) from v$ sgastat where pool = ' shared pool ' ; SUM ( BYTES ) 1 0 0 6632 96 и параметром SНARE D_POOL S I ZE: Структуры nамят и 249 ops $ t kyte@ORA9 I R2 > show paramet er shared_pool_s i z e NАМЕ ТУРЕ VALUE sha red_pool_s i z e b i g integer 8388 60 8 0 кроме того факта, что значение S UM ( BYT E S ) FROM V$ S GASTAT всегда было бол ь­ ше значения S HARE D_POOL_S I Z E . Разделяемый пул содержит множество других структур, которые выходят за рамки , определяемые эти м параметром . Как прави­ ло, SНARE D_POOL_ S I Z E вносит наибольш и й вклад в размер разделяемого пула, со­ общаемый столбцом suм ( BYTES ) , но он не я вляется единственной составляющей. Например, параметр CONTROL_ FI LES занимает 264 байта для каждого файла в разде­ ле "miscellaneous" (" прочие " ) разделяемого пула. В ыбор имени "shared pool " в п ред­ ставлении V $ S GAS TAT и имени параметра S НARED_POOL_S I Z E не особенно удаче н , поскольку этот параметр вносит наибольший в кл ад в размер разделяемого пула, но он не единственный, кто вносит свой вклад. Однако в Oracle 1 Og и последующих версиях наблюдается полное соответствие при условии использования ручного управления памятью SGA (т.е. при установке значен ия параметра SНARED_ POOL_S I ZE адми н истратором базы данн ых): ops $ t kyte@ORA1 0G> s e l ect sum ( bytes ) / 1 0 2 4 / 1 0 2 4 mЬytes from v $ s gastat whe re pool = 1 shared pool 1 ; MBYTES 128 ops $ t kyte @ORA1 0G> s how pa ramet er shared_pool_s i ze ; NАМЕ ТУ РЕ VALUE sha red_pool_s i z e b i g i nteger 1 2 8М На заметку! В этом при мере использовалось руч ное управление разделяемой памятью! Это достаточно важное изменение по сравнению с Orac!e9i и версиями до Oracle ! Og. В Orac\e ! Og параметр S HARE D_ POOL_S I Z E управляет размером разделяемо­ го пула, в то время как в Oracle9i и предшествующих версиях он л и ш ь вносил на­ ибольший вклад в размер разделяемого пула. Ре комендую выяснить действитель­ ный размер разделяемого пула в Oracle9i и предшествующих версиях (на основе VS SGASTAT) и воспользоваться этой информацией для установки значе н ия парамет­ ра SНARED_POOL_S I Z E в Oracle ! Og и последующих версиях. Теперь предполагается , что память для различных допол нительных компонентов, в нося щих свой вклад в размер разделяемого пула, выделяется адми н истратором базы дан н ых. Б оль ш ой пул Большой пул (large pool) назван так не потому, что я вляется "большой " структу­ рой (хотя его размер вполне может быть достаточно больш и м ) , а из-за того, что он применяется для выделения крупных сегментов памяти , превышающих по размеру те , для обработки которых предназначен разделяемый пул. 250 Глава 4 До поя вления большого пула в Oracle 8.0 вся память выделялась в разделяемом пул е . Это было нежелательно при использова н и и функций , которые требовали " круп н ые" сегменты памяти , такие как сегменты памяти UGA разделяемого серве­ ра. П роблема еще больше осложнялась тем , что обработка, которая обычно требо­ вала очень большого объема выделенной памяти , должна была применять память и наче , чем разделяемый пул управлял ею. Разделяемы й пул управляет памятью по алгоритму LRU, которы й прекрасно подходит для кеш ирования и повторного ис­ п ользован ия данных. Однако выделение больших сегментов обычно предполагает получение сегмента памяти , его применение и прекращение работы с ним - необ­ ходимость в кеш ировании содержимого этой памяти отсутствует. СУБД Oracle нуждалась в механизме, подобном реал изаци и реци клирующего и удерживающего пулов кеша буферов блоков. И менно таким и я вляются большой и разделяемый пул ы в настоящее время . Большой пул представляет собой область памяти, аналогичную рециклирующему пулу, а разделяемый пул больше похож на удерживающий буферны й пул - если оказывается , что какой -то объект использует­ ся часто, он сохраняется в кеше. Управл е н и е памятью, выдел е н н о й в бол ьшом пул е , осуществляется в куче во м ногом подобно тому, как язык С управляет памятью посредством процедур ma l l oc ( ) и f r e e ( ) . Как только вы "освобождаете" сегмент памяти , он может быть задействован другими процессами . Разделяемый пул не имел никаких механ измов освобожден ия сегментов памяти . Он должен бьш выделять ее, использовать, а затем прекратить потребление. По истечении некоторого времени , если возн икала необ­ ходимость повторного испол ьзования этой области памяти , СУБД Oracle должна была удалить содержимое устаревшего сегмента. Проблема с применением одного только разделяемого пула состоит в том , что единственный размер подходит не для всех ситуаци й . Большой пул используется: • подключениями посредством разделяемого сервера для выделения области UGA внутри области SGA; • параллельным выполнением операторов, чтобы сделать возможн ым выделение буферов сообщен и й для взаимодействия между процессами, которые приме­ няются для координации серверов параллельных запросов; • резервным копированием для в ыдел е н и я буферов дискового ввода-вы вода RMAN в некоторых случаях. Как видите, ни одно из этих выделен и й памяти не должно управляться в буферном пуле типа LRU, предназначен ном для управления небольшими сегментами памяти . Например, память, испол ьзуемая подключением посредством разделяемого серве­ ра, н икогда не применяется повторно после выхода из сеанса, поэтому она должна немедленно возвращаться в пул . Кроме того, область памяти разделяемого сервера и меет тенденцию быть " крупной " . Если вы просмотрите при ведеиные ранее приме­ ры работы С параметром SORT_AREA_RETAI NED_S I Z E ИЛИ PGA_AGGREGAT E TARGET, то вспом н ите , что область U GA может становиться очен ь большой и определенно превышать порции в 4 Кбайт. П омещение памяти многопоточного сервера в разде­ ляемый пул ведет к ее разбиению на фрагменты произвольных размеров. Более того, окажется , что большие сегменты памяти , которые н икогда не будут применяться Структуры nамят и 251 повторно, приведут к устареванию и тех сегментов, которые могл и бы испол ьзовать­ ся многократно. В результате база данных будет вынуждена позже выпол нять допол­ нительную работу по перестройке этой структуры памяти . Все сказанное относится и к буферам сообщен и й параллельн ых запросов, пос­ кольку они не пригодн ы для управления по алгоритму LRU. Они выделяются и не могут быть освобожден ы до тех пор, пока их применение не будет прекращено. Как только они доставили свои сообще н ия , они бол ьше н е требуются и должны быть незамедлительно освобожден ы . Это в еще большей степени относится к буферам резервного коп ирован ия - их размер очень велик, и как только Oracle прекращает их использование, они должны немедленно " исчезнуть". В случае применен ия подключений через разделяемый сервер наличие большого пула не обязательно, но настоятельно рекомендуется . Если бол ьшой пул отсутству­ ет и производится подкл ючение посредством разделяе мого сервера, то память вы­ деляется в разделяемом пуле, как это всегда происходило в Oracle 7.3 и предшес­ твующих версиях. Это неизбежно при ведет к с н ижен и ю производительности по истечен и и некоторого време н и , и такой ситуаци и следует избегать. Большой пул получит определенный стандартный размер, если параметр DBWR_ I O_ S LAVE S или PARAL L E L_МАХ_ S E RVERS установлен в какое-то положительное значение. Когда применяется функциональное средство, которое задействует большой пул , его раз­ мер должен быть установлен вручную. Стандартное значение обычно не будет под­ ходить в такой ситуаци и . П ул Java Пул Java появился в версии Oracle 8 . 1 . 5 для поддержки выполнения кода Java в базе данных. Если хранимая процедура нап исана на языке Java, то Oracle будет ис­ пользовать этот сегмент памяти при обработке такого кода. Параметр JAVA_POOL_S I Z E служит для фиксации объема памяти , которая выде­ ляется пулу Java для хранения всего кода и данн ых Java, специфичных для сеанса. Способ применения пула Java зависит от режима функционирования сервера Oracle. В режиме выделенного сервера пул Java включает в себя разделяемые части каждого из классов Java, которые действител ьно испол ьзуются в сеансе . В основ­ ном это части , предназначен н ые только для чте н ия (векторы выполнения , методы и т.п . ) , и их размер составляет около 4-8 Кбайт на класс. Таким образом , в режиме выделенного сервера общий объем памяти, требуемый для пула Java, я вляется до­ статочно умеренным и может быть определен, исходя из количества применяемых классов Java. Следует отметить, что в режиме выделенного сервера н и оди н элемент данных, специфичный для сеанса, не хранится в области SGA, т. к. эта и нформа­ ция содержится в области UGA и, как вы помн ите , в режиме выделенного сервера область UGA входит в состав PGA. При подключен и и к Oracle через разделяемый сервер пул Java содержит оба описанных н иже компонента. • Разделяемая часть каждого класса Java. • Часть области UGA, испол ьзуемая для хранения и нформации о состоя н и и каждого сеанса и выделяемая из сегмента JAVA_ POOL внутри области SGA. Остальная часть области UGA будет как обычно размещаться в разделяемом или в большом пуле, если он сконфигурирован. 252 Глава 4 П оскольку в Oracle9i и предшествующих версиях общи й размер пула Java фикси­ рован, разработчи кам приложе н и й придется оцен ить общий объем памяти , требуе­ мый их приложения м , и умножить это значение на количество одновременно дейс­ твующих сеансов, которые нужно поддерживать. П олученное значение определит общий размер пула Java. Каждый сегмент Java области UGA будет увеличиваться и уменьшаться по мере необходимости , но следует иметь в виду, что размер этого пула должен быть определен так, чтобы в нем могли одновременно умещаться все сег­ менты UGA. В Oracle 1 0g и последующих версиях этот параметр может изменяться , и пул Java может со временем увеличиваться и уменьшаться без перезапуска базы данн ых. Пул Streams П ул Streams ( П отоки ) - это структура SGA, поя вившаяся в Oracle 1 0g. В чис­ ло продуктов Oracle, которые работают с пулом Streams, входят Oracle GoldenGate, XStream, Oracle Streams, Oracle Advanced Queuing и Oracle Data Pump. Размер пула Streams регулируется установкой параметра S T REAMS_POOL_S I Z E . Если параметр S GA_TARGE T и меет неиулевое значение, то автоматическое управ­ ление памятью SGA будет применять параметр S T REAM S_POOL_S I Z E в качестве м и н имал ьного значен ия для размера пула Streams. Если параметры S GA_TARG ET и S T REAМS POOL_S I Z E оба установлены в О, то пул Streams будет испол ьзовать до 1 0% объема разделяемого пула. П родукты , работающие с пулом Streams, будут буферизировать сообщен ия в оче­ редях. Вместо применения постоя н н ых, основан ных на диске очередей, с сопро­ вождающим и их накладными расходами , эти средства используют очереди внутри памяти . По мере заполнения очереди будут сбрасываться на диск. Если по какой­ то причине (из-за программной ошибки , сбоя электроп итания и т. п . ) в экземпляре Oracle с очередями в памяти происходит отказ, то эти очереди в памяти воссоздают­ ся из журналов повторения транзакций. П ул Streams важе н тол ько в системах, и спол ьзующих средства (такие как GoldenGate , Streams и т.д . ) , которы м необходимо пространство в этой области па­ мяти . В этих средах должен быть установлен параметр S T REAМS POOL S I Z E, чтобы избежать расхода 1 0% объема разделяемого пула. _ Управление памятью SGA П араметры, связанные с памятью SGA, относятся к одной из двух областей . • Автоматически настраиваемые параметры SGA. В н астоя щее время это DB_CACHE_S I Z E , SHA�E D_POOL_S I Z E , LARGE_POOL_S I ZE, JAVA_POOL_S I Z E И STREAМS POOL S I Z E . • Настраиваемые вручную параметры SGA. К н и м относятся LOG_BU FFER, DB_NK_CACHE_S I ZE , DB_KEE P_CACHE_S I Z E И DB_RECYCLE_CACHE_S I ZE. В Oracle 1 Og и последующих версиях в любой момент можно запросить представ­ ление V $ S GA I N FO и посмотреть, какие компоненты SGA поддерживают возмож­ ность изменения размера: Структуры памят и EODA@ORA1 2 CR1> se1ect * from V$ SGAINFO ; NАМЕ BYTES -------------------------------- Fixed SGA S i z e Redo Buffers Bu f fer Cache S i z e Shared Pool S i z e Large Pool S i z e Java Р о о 1 S i z e Streams Pool S i ze Shared IO Роо1 S i ze Data Trans fer Cache S i ze Granule S i z e Maximum SGA S i z e Startup overhead i n Shared Pool Free SGA Memory Ava i l aЬle ---------- 2287336 4 8 90624 67 1 0 8 8 6 4 1 8 4 5 4 9 37 6 4 1 94304 4 1 94304 о 4 194304 о 4 1 94304 2 67 2 2 7 1 3 6 1 69940696 о RES No No Yes Yes Yes Yes Yes Yes Yes No No No 253 CON I D ---------- о о о о о о о о о о о о о 1 3 rows selected . 1 3 строк выбрано . Дтуя компонентов памяти SGA, которые мoryr автоматически настраиваться , пре­ дусмотрены три способа управления ими. • Ручное управление разделяемой памятью. Установка всех необходим ых пара­ метров пула и кеша. • Автоматическое управление разделяемой памятью (ил и памятью SGA) , доступ­ ное в Oracle ! Og и последующих версиях. Установка параметра SGA_TARGET. За счет установки п араметра S GA_TARGET вы позволяете экземпляру задавать и изменять размеры разнообразных компонентов SGA. • Автоматическое управление памятью, доступное в Oracle l lg и последующих версиях. Установка п араметра MEMORY_TARGE T . За счет установки параметра MEMORY _TARGET вы позволяете экземпляру задавать и изменять размеры об­ ластей памяти SGA и PGA. Н иже мы обсудим эти способы по очереди. Ручное управление разделяемой памятью Если требуется определен н ы й уровен ь контроля над автоматически настраи вае­ мыми областями памяти SGA, установите параметры MEMORY_TARGET и SGA_TARGET в нулевое значение. Когда в ноль установлен параметр MEMORY_ TARG E T , отклю ­ чается автоматическое управление памятью, а когда в нол ь установлен п араметр SGA_TARGET, отключается автоматическое управление разделяемой памятью. На заметку! В Oracle9i и предшествующих версиях было доступно тол ько ручное управ­ ление разделяемой памятью - параметр S GA_ TARG E T не существовал , а параметр SGA_МАХ_ s I ZE указывал макси мальный размер области SGA. Когда автоматическое управление памятью отключено, вы можете вручную уста­ навливать размер области SGA, указывая значен ия для следующих п араметров па­ мяти : DB_CACHE_S I Z E , SНARED_POOL_S I Z E , LARGE_POOL_S I Z E , JAVA_POOL_S I Z E и STREAМS POOL_ S I Z E . Каждый из перечислен н ых параметров и меет стандартное значение, которое Oracle будет применять в случае, есл и параметр не установлен 254 Глава 4 явным образом. Н апример, параметр DB _САСНЕ s I Z E будет установлен в значение 48 Мбайт или 4 М байт, умноженное на количество процессоров, в зависимости от того, какая величина окажется больше в конкретной системе. Н иже приведен пример содержимого файла и н ициализации , в котором включа­ ется ручное управление разделяемой памятью: * . compatiЬle= ' 1 2 . 1 . 0 . 1 ' * . cont rol_f i l e s = ' / u 0 1 /dЬ f i l e / ORA1 2 CR1 / control 0 1 . ct l ' , ' /u 0 2 /dЬ f i l e / ORA1 2 CR1 / contro l 0 2 . ct l ' * . dЬ Ьlock s i ze=8 1 92 * . dЬ name= ' ORA1 2 CR1 ' * . memory_target=O * . sga_target=O * . dЬ cache s i ze=lG * . shared_poo l_s i ze=2 5 6M * . pga_aggregate_target=2 5 6m * . open_cur sors=З O O * . proce s s e s= б O O * . remote_login_pas swordfi l e = ' EXCLUS IVE ' * . resource l imit=TRUE * . undo_taЬle space= ' UNDOTBS l ' - - В Oracle l lg Release 2 и последующих версиях с ручным управлен ием разделяе­ мой п амятью связан оди н аспект, о котором следует знать: даже когда вы явно от­ ключаете все автоматическое управление памятью (устанавли вая в нол ь параметры MEMORY_TARGET и S GA_TARGET ) , Oracle может по-прежнему делать ряд автоматичес­ ких перераспределений памяти из кеша буферов базы данных в разделяемый пул. В случае исчерпания пространства в разделяемом пуле Oracle будет автоматичес­ ки добавлять к нему пространство, чтобы избежать появления ошибки ORA-0403 1 " UnaЬle to allocate %s bytes of shared memory" (" Не удается выделить %s байтов раз­ деляемой памяти" ) . Понаблюдать з а автоматическим изменением размера памяти SGA можно, за­ просив представлен ие V$MEMORY_RE S I ZE _O P S . Столбец OPER_MODE будет содержать значен ие DE FERRED или IММE DIAT E для любых операций автоматического изменения размера SGA. Когда используется ручное управление п амятью SGA, автоматическое изменение размера SGA отключается для запросов в режиме DE FERRED, но разреше­ но для запросов в режиме IММEDIATE. Следовательно, в случае применения ручного управлен ия разделяемой памятью вы можете обнаружить наличие операций GROW и SHRINK (в столбце OPER_Т УРЕ) для запросов автоматической настройки I MMEDIATE в отношен и и размеров областей памяти DB_CACHE_S I Z E и S HARED_POOL. П родемонстрируем утвержден и я из предыдущих абзацев на п ростом примере. Для начала создадим пакет овмs _ S HARE D POOL, чтобы можно было закрепить объ­ екты в разделяемом пуле : _ SYS @ ORA1 2CR1> @ ? / rdЬms / admin /dbmspool S e s s ion a l te red . Сеанс изменен. Package created . Пакет создан . Grant succeeded . Выдано успешно . Стру к туры n амяти 255 Sess ion a l tered . Сеанс изменен . SYS@ORA12CR1> grant execute on dЬms_shared_poo1 to eoda ; Grant succeeded . Выдано успешно . Далее запустим код, которы й быстро начнет заполнять разделяемый пул (закре­ пив множество процедур P L/SQ L в разделяемом пуле) : SYS@ORA1 2CR1> conn eoda / foo Connected . Подключено . EODA@ORA12CR1> dec1are 2 k varchar2 ( 3 0 ) ; 3 ss varchar2 ( 2 0 0 0 ) ; 4 begin for i in 1 . . 1 0 0 0 0 0 l oop 5 б ss : = 1 create or replace procedure S P ' 1 1 i 1 1 1 i s 7 а numЬer ; 8 begin 9 а : = 1 2 3 4 5 67 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ; 10 а : = 1 2 3 4 5 67 8 9 0 1 2 3 4 5 6 7 8 90 1 2 3 4 5 6 7 8 90 ; 11 а : = 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 67 8 90 1 2 3 4 5 67 8 90 ; 12 а : = 1 2 3 4 5 67 8 9 0 1 2 3 4 5 67 8 90 1 2 3 4 5 6 7 8 90 ; 13 а : = 1 2 3 4 5 67 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 90 ; 14 а : = 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 90 1 2 3 4 5 6 7 8 90 ; 15 а : = 1 2 3 4 5 67 8 9 0 1 2 3 4 5 67 8 90 1 2 3 4 5 6 7 8 9 0 ; 16 а : = 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 90 ; 17 а : = 12345678901234567 8 90 1 2 3 4 5 67 8 9 0 ; 18 а : = 1 2 3 4 5 6 7 8 90 1 2 3 4 5 67 8 90 1 2 3 4 5 6 7 8 90 ; 19 а : = 1 2 3 4 5 67 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 90 ; 20 а : = 1 2 3 4 5 67 8 9 0 1 2 3 4 5 67 8 9 0 1 2 3 4 5 67 8 9 0 ; 21 а : = 1 2 3 4 5 67 8 9 0 1 2 3 4 5 67 8 9 0 1 2 3 4 5 6 7 8 9 0 ; 22 а : = 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 67 8 90 ; 23 а : = 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 90 1 2 3 4 5 6 7 8 9 0 ; 24 end; 1 ; execute immediate s s ; 25 26 k : = 1 SP 1 1 1 i ; 27 s ys . dЬms_shared_poo1 . keep ( k ) ; end loop ; 28 2 9 end; 30 1 А теперь из другого сеанса запроси м словарь дан н ых, чтобы увидеть операции изменения размера памяти, связанные с тем , что Oracle перемещает память в разде­ ляемый пул : EODA@ORA12CR1> select component , parameter , oper_typ e , oper_mode from v$memory_r e s i z e_ops ; DEFAULT buffer cache shared pool DEFAULT buffer cache DE FAULT buffer cache dЬ cache s i z e shared_pool_s i ze dЬ cache s i z e dЬ cache s i z e - - - - - - SHRINK GROW SHRINK SHRINK IММEDIATE IММEDIATE IММEDIATE IММEDIATE 256 Глава 4 shared pool DE FAULT buffer cache shared pool shared_poo l_s i z e dЬ cache s i ze shared_pool_s i z e - - GROW SHRINK GROW IММEDIATE IММEDIATE IММEDIATE Итак, вы должн ы знать о возможности выполнения в Oracle I lg Release 2 и пос­ ледующих версиях определенного автоматического перераспределен ия памяти SGA, даже когда дан ное средство было отключено. Как отмечалось ранее , это делается Oracle для того, чтобы процессы не исчерпали пространство в разделяемом пуле. Совет. Дополнительные сведения об автоматическом изменении размера области SGA во время использования руч ного уn равления разделяемой памятью можно найти в примеча­ нии MOS под номером 1 2691 39. 1 . А втоматическое управление разделяемой памятью При автоматическом управлен и и разделяемой памятью основным параметром указания п олного размера автоматически н астраиваемых компонентов является S GA_TARGET , который может динамически изменяться во время работы базы данных вплоть до значения , установлен ного в SGA_МАХ_ s I ZE. Его стандартное значение рав­ но величине S GA_TARGET, поэтому если вы планируете увеличение SGA_TARGET, то перед запуском экземпляра базы данных должн ы установить SGA_МАХ_s I ZE в более высокое значение. База данных будет работать с памятью с объемом, равным значе­ н и ю S GA_TARGE T минус значен ия размеров любых других компонентов с вручную заданными размерами , подобных DB_KEE P_CACHE_S I Z E , DB_RECYCLE_CACHE_S I Z E и т.д. Этот объем памяти будет использоваться для установки размеров стандартно­ го, разделяемого, большого пулов и п ула Java. Динамически во время выполнения экземпляр будет выделять и перераспределять п амять между этим и четырьмя об­ ластям и по мере необходимости . Вместо возвращен ия пользователю сообщения об ошибке ORA-0403 1 " UnaЬle to allocate %s bytes of shared memory" ("Не удается выде­ л ить %s байтов разделяемой п амяти" ) в случае нехватки памяти в разделяемом пуле экземпляр может уменьшить буферный кеш на определенное количество мегабайт (размер гранулы) и увеличить размер разделяемого пула на это ч исло. На заметку! Чтобы можно было применять автоматическое уnравление разделяемой па­ мятью, nараметр S TAT I S T I C S L EVE L должен быть установлен В T Y P I CAL И Л И AL L . Если сбор статистики не вкл ючен , база данных н е будет располагать хронологической информацией, требуемой для при нятия необходимых решений относител ьно установки размеров. Со временем, когда потребности экзем пляра в памяти прояснятся , размеры разнообразных компонентов SGA станут более или менее фиксированными. База дан н ы х запоминает также размеры этих четырех ком понентов между запуском и остановом , поэтому выяснять их заново при каждом запуске экземпляра не при­ дется. Это делается посредством четырех параметров, имена которых начинаются с двух символов подчеркивания: dЬ_c ache_s i z e , j ava_poo l_s i z e , l a r ge poo l_s i z e и _s h a r e d_poo l_s i z e . Во время нормального или немедленного за­ вершения работы база данных будет записывать эти параметры в файл хранимых па­ раметров, а затем использовать их при запуске для установки стандартных размеров каждой области . Структуры nам ят и 257 На заметку! Последнее средство сохранения рекомендованных значений для пулов работа­ ет, только если применяются файлы хран и м ых параметров (также известн ые как файлы sptile ) . Кроме того, если известно определенное минимальное значение размера дл я од­ ной из указанных пяти областей , этот параметр можно установить в дополнение к SGA_TARGET . Экземпляр будет использовать это значение в качестве н ижней грани­ цы, т.е. наименьшего размера, который может иметь данн ая конкретная область. Автоматическое управление памятью В Oracle l 1g Release 1 и последующих версиях база дан н ых также предлагает автоматическое управление памятью - своего рода и сточн и к значен и й для всех настроек памяти . С появлением Огас1е 1 Og и автоматического управления памятью SGA администратору базы данных оставалось устанавл ивать только две основные настрой ки памяти : PGA_AGGREGAT E_TARGET и S GA_TARG E T . База данн ых автома­ тически выделяла и перераспределяла порции памяти внутри каждой области , как было описано ранее. В Oracle 1 1g администратору базы данных необходимо устано­ вить всего один параметр памяти - MEMORY_TARG E T , представляющий суммарный объем памяти , в пределах которого должны находиться объединенные области SGA и PGA (помните, что память PGA может быть в некоторой степени неконтролиру­ емой ) . База данных динамически определит подходящие размеры областей SGA и PGA на основе хронологии рабочей нагрузки . П о мере изменения рабочей нагрузки с течением времени размеры выделенных областей SGA и PGA также будут изме­ няться . Например, если в течение дня у вас производится и нтенсивная оперативная обработка транзакций (OLTP) и и нтенсивная пакетная обработка по ночам, вы мо­ жете обнаружить, что дневной размер SGA намного больше, чем PGA, а ночью все наоборот. Это отражает разные потребности в памяти указанн ых двух типов прило­ жений. Н а заметку! Перед внедрением автоматического уnравления памятью nредусмотрите изуче­ ние любых примечаний MOS, специфичных для имеющейся операционной систе м ы , таких как 74985 1 . 1 (для Lin ux) и 1 399274. 1 (для Solaris) . Как и п р и автоматическом управлен и и памятью SGA, адми н истратор базы дан ­ н ы х может определять нижние границы дл я размеров всех областей памяти , уста­ навливая параметры S GA_TARGET и PGA_AGGRE GATE_TARGET, ИЛ И НИЖНЮЮ границу каждого пула в SGA, устанавл ивая в нее значения их параметров . База данн ых за­ помнит оптимал ьные настрой ки для пулов и областей SGA и PGA в файле храни­ мых параметров, если он применяется. Например, в одной из своих тестовых систем я установил следующие параметры: • memory_t a rget 7 5 6m • sga_t a rget = 2 5 6m • pga_aggregate_ta rget = 2 5 6m = Файл хранимых параметров для данной базы дан н ых в н астоящий момент вы­ глядит так: 258 Глава 4 SYS@ORA1 2CR1> create p f i l e= ' / tmp/pfi le ' from spfi l e ; F i l e created . Файл создан . SYS @ ORA 1 2 CR 1 > ! ca t / tmp/pfi le ; ORA1 2 CR1 . data transfer cache s i ze=O с1Ь cache si ze=67 1 0 8 8 64 - ORA12CR1 . ORA12CRl . ORA12CRl . ORA1 2CRl . - - j ava�ol_size=4 1 94304 large_pool_si ze=4 1 94304 __ __ oracle_base= ' /orahome /app/oracle ' #ORACLE_BASE set from envi ronment __ ORA12CRl . �a_aggregate_target=520093696 ORA12CRl . sga_target=2726297 60 ORA12CRl . shared_io�ol_size=O ORA12CRl . shared�ol_size=l 8454 937 6 ORA12CRl . streaшs_pool_si ze=O __ __ __ __ * . compatiЬle= ' 1 2 . 1 . 0 . 1 ' * . control f i l e s = ' / u 0 1 /dЬ f i l e / ORA1 2 CRl / control O l . ctl ' , ' / u 0 2 /dbfi l e / ORA1 2CR1 / control 0 2 . ctl ' * . dЬ Ьlock s i ze=8 1 92 * . dЬ name= ' ORA1 2 CR 1 ' * . memory_target=7 92 7 2 3 4 5 6 * . open_cursors=З O O * . pga_aggregate_target=2 68435456 * . proce s s e s = б O O * . remote_login_pas swordfi l e= ' EXCLUS I VE ' * . resource l imit=TRUE * . sga_target=2 68435456 * . undo_taЬl espace= ' UNDOTBS l ' Как видите , параметры с именам и , нач инающимиен с двух символов подчерки­ вания , которые выделены полужирным, теперь включают настройки sga ta rget и _pga_aggregate t a rget , а также различные пулы. Эти значения вы водятся на основе последн их трех параметров, выделенных полужирным, и наблюдаемой ра­ бочей н агрузки сервера. Таким образом, Oracle будет запоминать ваши последн ие оптимальные н астройки SGA/PGA и использовать их при следующем перезапуске . _ Р ез ю ме В этой главе м ы взглянули н а структуры памяти Oracle. М ы начал и с уровня про­ цессов и сеансов, исследовав области PGA и UGA и взаимосвязь между ними. Мы выяснил и , какое влияние на организацию памяти оказывает режим подключен ия к базе данных Oracle . П одключение через выделен н ы й сервер предусматривает более и нтенсивное испол ьзование памяти процессом сервера, чем подключение посредс­ твом разделяемого сервера, но подключение через разделяемы й сервер требует вы­ делен ия значительно большего объема для области SGA. Затем мы обсудили основ­ ные структуры самой области SGA. М ы обнаружили отличия между разделяемым и большим пулам и , и установили прич и н ы , по которы м может требоваться большой пул для " экономи и " объема разделяемого пула. Мы раскрыли особенности пула Java и способы его применения в разнообразных ситуациях, а также рассмотрели буфер­ н ы й кеш блоков и возможность его разделения на меньшие, более специализиро­ ванные пул ы . Теперь можно переходить к исследованию физических процессов, ко­ торые формируют остальную часть экземпляра Oracle. ГЛ А В А 5 Про ц ессы Oracle н аконец, м ы добрались д о последнего фрагмента архитектурной головоломки . М ы уже исследовали базу дан ных и набор образующих ее физических файлов. Рассмотрев память, используемую Oracle, м ы раскрыли первую половину экземпля­ ра. Осталось ознакомиться с еще одним вопросом, касающимся архитектуры - на­ бором процессов, которые образуют вторую половину экземпляра. Каждый процесс в Oracle будет выпол нять отдельную задачу или набор задач , и каждый из них будет и меть внутреннюю память ( память PGA) , выделенную им для выполнения своего задания. С экзем пляром Oracle связаны три обширных класса процессов. • Серверные процессы. Эти процессы выполняют свою работу на основе кли ­ ентского запроса. М ы уже д о определенной степени знакомы с вьщеле нным и разделяемым серверами . Они являются серверными процессами . • Фоновые процессы. Эти процессы запускаются вместе с базой дан н ы х и вы­ полняют разнообразные задачи обслуживан и я , такие как запись блоков на диск, ведение операти вных журналов повторе н и я , очистка после преры ва­ ния процессов, поддержка автоматического репазитария рабоч е й нагрузки (Automatic Work.Ioad Repository - AWR) и т.д. • Подчиненные процессы. Эти процессы подобны фоновым , но выполняют допол­ нительную работу по поручен и ю л ибо фонового, л ибо серверного процесса. Мы уже упоми нали некоторые из этих процессов, например, процесс зап иси блоков базы данных ( D BWn) и процесс записи в журнал (LGWR) , но здесь м ы более подробно рассмотрим фун кционирование каждого п роцесса, выпол няемые и м и действия и причины такой и х реал изации . Н а заметку! Термин процесс в этой главе должен трактоваться как синоним термина поток в операционных системах, в средах которых СУБД Oracle реал изована посредством по­ токов (например, Windows). В контексте главы термин процесс охватывает как n роцессы, так и потоки. Если вы используете реализаци ю Oracle с множеством п роцессов, такую как в среде UN IX/Lin ux, то тер м и н процесс полностью адеквате н . Если же вы п р и меня­ ете реал изацию Oracle с единственным процессом , характерную для среды Windows, то термин процесс в действительности будет означать поток внутри процесса Oracle. Таким образом, напри мер, когда речь идет о процессе oвwn , его эквивалентом в среде Windows является nоток DBWn внутри п роцесса Oracle. 260 Гл ава 5 С ерверные про ц ессы Серверн ые п роцессы - это процесс ы , которые выполняют работу от имени сеанса кл иента. Такие процессы в итоге при н и мают и де йствуют согласно SQL­ операторам , которые наши приложения отправляют базе данных. В главе 2 м ы кратко посмотрели на два основных типа подключений к Oracle. • Подключение посредством выделенного сервера. На сервере для подключения имеется выделенный процесс. При этом между подключением к базе данных и серверным процессом или потоком существует однознач ное соответствие. • Подключение посредством разделяемого сервера. М ножество сеансов совмест­ но испол ьзуют пул серверных процессов, порожденных и управляемых экзем­ пляром Oracle . П одключение производится к диспетчеру базы данн ых, а не к процессу выделенного сервера, которы й создан специально для подключения. Н а заметку! Важно понимать разницу между подключением и сеансом в контексте терми­ нологии Oracle. Подключение (соппесtiо п ) - это просто физически й путь передачи ин­ формации между процессом клиента и экземпляром Oracle (например, сетевое соединение между пользователем и экземпляром ) . С другой сторон ы , сеанс (sessioп) - это логичес­ кая сущность в базе дан ных, в которой процесс кл ие нта может выполнять SQL-зап росы и т.д. С еди нственным подкл ючением может быть связано несколько независимых сеансов, и эти сеансы могут даже существовать независимо от подключения. Вскоре мы обсудим это более подробно. П роцессы выделенного и разделяемого серверов реш ают одну и ту же задачу: они обрабаты вают все предоставляемые им SQ L-запросы . Когда вы отправляете базе данных запрос S ELECT * FROM ЕМР, процесс выделенного/разделяемого сервера производит синтаксически й разбор запроса и помещает его в разделяемый пул (или находит его в разделяемом пуле, если он там уже присутствует) . При необходимости процесс создает план запроса и выполняет его, возможно отыски вая нужные дан­ ные в буферном кеше или считывая данные с диска в буферн ы й кеш . Серверные процессы делают всю рутинную работу. Ч асто в ы будете обнаружи­ вать, что эти процессы я вля ются основн ы м и потребителям и ресурсов процессара в системе, поскольку они выполняют сортировку, сум мирован ие и соеди нение практически все необходим ые действия . П одключения посредством выделенного сервера В режиме вьщеленного сервера между подключением клиента и серверным про­ цессом (или потоком) устанавливается однозначное соответствие. При наличии на компьютере UN IX/Linux ста подключений через вьщеленный сервер от их имени бу­ дут выполняться сто процессов. Эта ситуация графически представлена на рис. 5. 1 . Клиентское приложен и е будет содержать скомпонован ные с ним библиотеки Oracle . Эти библиотеки предоставляют АРI-интерфейсы , которые требуются для об­ мена и нформацией с базой данных. Таким АРI - интерфейсам известно, каким обра­ зом отправлять запрос базе данных и обрабатывать возвращаемый курсор. Они так­ же умеют объединять запросы в сетевые вызовы , которые выделенный сервер будет распаковы вать. П р о цессы Oracle 26 1 Кл иентское приложение о о Рис . 5 . 1 . Тиnичное nодключение nосредством выделенного сервера Эта часть программ нога обеспечения н азывается Oracle Net (Сеть Oracle ) , хотя в предшествующих версиях ее называли SQL*Net или Net8. Она представляет собой сетевое программное обеспечение/протокол, которы й Oracle применяет для реали­ зации клиент-серверной обработки (в многозвенной архитектуре также присутствует клиент-серверное программное обеспечение ) . СУБД Oracle использует эту же архи­ тектуру, даже если Oracle Net формально не принимает участия . То есть такая двух­ процессная архитектура (которую также назы вают двухзадачной) задействована даже в ситуации , когда клиент и сервер находятся на одном и том же ком п ьютере. Эта архитектура предоставляет два преимущества. • Возможность удаленного выполнения. Ситуация, когда кл иентское приложение выполняется на компьютере , отличном о того, где функционирует база дан ­ ных, является вполне естественной. • Обеспечение изоляции адресного пространства. Серверн ы й процесс и меет до­ ступ по чтению и записи к области SGA. Если бы кл иентский и серверный процессы был и физически связаны друг с другом , то ошибочный указатель в клиентском процессе легко мог бы легко повредить структуры данных в SGA. В главе 2 было показано, как эти выделенные серверы порождаются, или со­ здаются , проелуши вающим процессом Oracle. Я не буду описывать это снова; вза­ мен мы кратко рассмотрим, что происходит в тех случаях, когда проелушивающий процесс не задействован. Механизм во многом похож на тот, который применяется вместе с проелуши вающим процессом, но теперь выделенный сервер создается не проелуш ивающим процессом посредством вызова fork ( ) /ехес ( ) в U N IX/Linux или вызова I PC (interprocess communication - взаимодействие между процессам и) в Windows, а самим клиентским процессом . 262 Глава 5 На заметку! Существует м ного разновидностей вызовов f o r k ( ) и ехес ( ) вроде v f o r k ( ) и exe cve ( ) . Вызов, исnользуемый Oracle, может варьироваться в зависимости от оnера­ ционной системы и реализаци и , но конечн ы й результат остается тем же сам ы м . Функция f o r k ( ) создает нов ы й n роцесс, который является клоном родител ьского nроцесса; в среде U N IX/Unux это единственный сnособ создания нового nроцесса. Функция ехес ( ) загружает в nамять образ новой nрогра м м ы nоверх образа существующей nрограмм ы , nриводя к заnуску этой новой n рограмм ы . Таким образом, и нтерфейс SQL*Pius может раз­ ветвиться nосредством f o r k ( ) ( скоnировать себя ) и затем запустить с nомощью ехес ( ) двоичный файл Oracle, nерекрыв коn и ю самого себя этой новой nрограммой. Создание такого родительского/дочернего процесса можно отчетливо наблюдать в UN IX/Linux в случае выполнения клиента и сервера на одном и том же компью­ тере: $ sqlplus eoda / foo SQL * Plus : Release 1 2 . 1 . 0 . 1 . 0 Production on Thu Mar 20 1 4 : 2 9 : 0 0 2 0 1 4 Copyright ( с ) 1 9 8 2 , 2 0 1 3 , Oracle . Al l rights reserved . Las t Succe s s ful login t ime : Thu Mar 2 0 2 0 1 4 1 3 : 4 7 : 0 1 - 0 7 : 0 0 Connected to : Oracle Databas e 1 2 с Ente rp r i s e Edi t i on Release 1 2 . 1 . 0 . 1 . 0 6 4 b i t Production With the Parti t i oning , OLAP, Advanced Anal ytics and Rea l Application Testing opt i ons EODA@ORA1 2 CR1 > s e l ect a . spid dedicated_s erve r , b . p roce s s clientpid 2 f rom v$p roce s s а, v $ s e s s ion Ь 3 whe re а . addr = Ь . paddr 4 and b . s i d = s ys_context ( ' us e renv ' , ' s id ' ) ; DE D I CATE D SERVER C L I ENT P I D 18571 18570 EODA@ORA12CR1> ! /b i n /ps - fp 1 8 5 7 1 1 8 5 7 0 UID P I D P P I D С S T I МE ТТУ STAT oracle 1 8 5 7 0 1 1 7 8 2 О 1 5 : 1 7 p t s / 4 S+ oracle 1 8 5 7 1 1 8 5 7 0 О 1 5 : 1 7 ? Ss Т I МЕ CMD 0 : 0 0 sqlplus 0 : 0 0 oracl eORA1 2 CR1 ( DESCRI PT ION= ( LOCAL= . . . Здесь с помощью запроса выясняется идентифи катор процесса (process I D PI D), ассоциированн ы й с выделен н ы м сервером (значение S P I D из V$ PROCESS это идентификатор P I D операционной систем ы дЛЯ процесса, который применялея во время выполнения этого запроса). В ывод /b i n/ ps - fp включает идентификатор родительского процесса (parent process I D - P P I D ) и показы вает процесс выделен­ ного сервера, 1 857 1 , как дочерн и й процесс процесса S Q L* P1us: идентификатором процесса является 1 8570. Подключения посредством разделяемого сервера Давайте теперь более подробно рассмотрим процесс разделяемого сервера. Этот тип подключения требует испол ьзован ия O racle Net, даже если кл иент и сервер П роцессы O rac l e 263 установлены на одном и том же ком пьютере - применение разделяемого сервера без проелуш ивающего процесса Огасlе TN S невозможно. Как было указано ранее , клиентское приложение будет подключаться к проелуш и вающему процессу Огасlе TN S, а затем переадресовываться или передаваться диспетчеру. Диспетчер действует в качестве средства передачи между клиентским приложеннем и процессом разде­ ляемого сервера. На рис. 5 . 2 при ведена диаграмма архитектуры подключения к базе данных посредством разделяемого сервера. г Дост уп через сеть Досту п в пам ять Клиентск ие приложен ия Область SGА Разделяем ые серверы Оче редь заnросов Оч ере дь ответов Рис. 5 . 2 . Тип ичное подключение посредством разделяемого сервера Как видите, клиентские приложения со скомпонованн ы м и в н их библиотеками Огасlе будут физически подключен ы к процессу диспетчера. Для любого заданно­ го экземпляра может быть сконфиrурировано множество диспетчеров, но не так уж редко единственный диспетчер используется для сотен и даже тысяч пользователей. Диспетчер отвечает лишь за прием входящих запросов от клиентских приложен и й и помещение их в очередь запросов внутри области SGA. Первый доступн ы й процесс разделяемого сервера из пула заранее созданных процессов выделенного сервера из­ влечет запрос из очереди и присоедин ится к области U GA связанного сеанса (на рис. 5.2 это прямоуrольники, помеченные " С " ) . Разделяемы й сервер обработает за­ прос и поместит полученн ы й из него вывод в очередь ответов. Диспетчер постоя нно отслежи вает очередь ответов на предмет появления в ней результатов и передает их обратно клиентскому приложению. С точки зрения клиента невозможно сказать, подключен он посредством выделенного или разделяемого сервера - оба типа под­ кл ючения для него выглядят оди наково. Различие проявляется тол ько на уровне базы данных. 264 Глава 5 Резиден тный пул соединений с базой данных Резидентн ы й пул соеди не ни й с базой дан н ых ( Database Resident Connection Pooling - D RC P) представляет собой дополнительный метод подключения к базе данных и установлен ия сеанса. Он спроектирован как более эффективный метод ор­ ганизации пула соединений для интерфейсов приложений, которые не имеют прак­ тичной встроен ной поддержки пула соединени й , подобных РН Р - уни версальному языку веб-сценариев. М етод DRC P - это смесь концепций выделенного и разделя­ емого сервера. Он наследует от разделяемого сервера кон цепцию организации пула серверных процессов, тол ько процессы в пуле будут выделенными, а не разделяе­ мыми серверами ; от выделенного сервера наследуется конце п ция самой специали­ зации. П р и подкл ючении посредством разделяемого сервера процесс разделяемого сер­ вера совместно используется множеством сеансов, и один сеанс будет, как правило, работать с множеством выделенных серверов. В случае DRC P это не так; процесс выделенного сервера, выбранный из пула, станет выделенным для клиентского про­ цесса на время жизни его сеанса. Если внутри сеанса разделяемого сервера выпол­ н ить применительно к базе данных три оператора, то высока вероятность того, что эти три оператора будут обработаны тремя разными процессами разделяемого сер­ вера. В случае использования D RC P те же три оператора будут выполнены выде­ лен н ы м сервером, назначенным из пула - и этот выделенный сервер будет прина­ длежать сеансу до тех пор, пока он не возвратит его обратно в пул . Таким образом , D RC P обладает возможностями организации пула разделяемого сервера и характе­ ристиками производительности выделенного сервера. П озже в этой главе мы прове­ дем сравнение производительности выделенного и разделяемого серверов. П одключения и сеансы М ногие уди вляются , когда узнают, что подкл ючение - это не синоним сеанса. В глазах большинства людей эти термины идентичны, но реальность такова, что они не должн ы быть одинаковым и . П одключение может и меть ноль, один или более установленных в нем сеансов. Каждый сеанс является отдельным и независи мым, даже если все они совместно испол ьзуют одно и то же физическое подключение к базе данных. Фиксация в одном сеансе не оказывает вл ия н ия на любые другие сеан­ сы этого подключен ия . В действительности каждый сеанс, применяющий одно под­ ключение, мог бы использовать разные идентификационные данные пользователя! В среде Огасlе подключение представляет собой просто физическую линию свя­ зи между клиентским процессом и экзем пляром базы данных - чаще всего сетевое подкл ючение. П одключение может производиться к процессу выделенного серве­ ра или к диспетчеру. Как утверждалось ранее , подключение может иметь ноль или большее число сеансов, т.е . допустимо наличие подключения без соответствующих ему сеансов. Вдобавок сеанс может иметь, а может и не иметь подключение. С по­ мощью усовершенствованных фун кциональных средств Oracle Net, таких как ор­ ганизация пула подключен и й , клиент может закрывать физическое подключение, оставляя сеанс незатронутым (но бездействующим). Когда клиенту потребуется вы­ полнить определенную операцию в этом сеансе, ему придется заново установить фи­ зическое подключение. Давайте определим эти термины более точно. П р о цессы Oracle • 265 Подключение. Подключение (connection) - это физическая линия связи между клиентом и экземnляром Oracle . П одключение устанавливается либо по сети, либо посредством механизма I PC. Как правило, подключение создается между клиентским процессом и выделенным сервером либо диспетчером. Однако с применением диспетчера подключен и й Oracle (Connection M anager - СМАN ) подключение можно устанавливать между клиентом и C MAN и между C MAN и базой данных. П одробное описание C MAN выходит за рамки этой кни ги , но определенные сведения об этом инструменте можно найти в руководстве ад­ министратора сетевых служб базы данных Oracle (Oracle Database Net Services Administrator's Guide), которое доступно бесnлатно по адресу: http : / /otn . orac l e . com • Сеанс. Сеанс (session) - это логическая сущность, находящаяся в экземпля­ ре. Каждый уникальный сеанс представлен состоянием сеанса, или коллекци­ ей структур дан н ых в памяти . И менно о нем возникает первая мысль у боль­ ш и нства люде й , когда они думают о п одключен и и к базе данн ых. Запросы SQL, фиксация транзакций и хранимые процедуры выполняются внутри се­ анса на сервере. Чтобы увидеть подключения и сеансы в работе и действительно удостовериться в возможности существования в подключен и и более одного сеанса, можно восполь­ зоваться SQL*Plus. М ы просто применим команду AUTOTRACE и обнаружим наличие двух сеансов. Через одиночное подключение, использующее единственный процесс, мы установим два сеанса. Вот первый сеанс: EODA@ ORA12CR1> select use rname , s i d , s e rial # , s e rve r , paddr , s tatus 2 from v $ s e s s i on 3 whe re use rname = USER 4 1 USERNAМE SID SERIAL# EODA 10 15 SERVER PADDR S TATUS DED I CATED 0 0 0 0 0 0 0 0 7 2 7 FE9BO ACT IVE В текущий момент есть оди н сеанс - сеанс, подключен н ы й через вьщеленн ы й сервер. В столбце PADDR находится адрес единственного процесса выделенного сер­ вера. На этот раз мы включим функцию AUTOT RACE для получения статистических сведений об операторах, выполняемых в среде SQL*Plus: EODA@ORA12CR1> set autotrace on stati s t i c s EODA@ORA12CR1> select use rname , s i d , serial # , s e rve r , paddr , s tatus 2 from v $ s e s s ion 3 where use rname = USER 4 1 USERNAМE SID SERIAL# EODA EODA 10 21 15 721 SERVER PADDR S TATUS DED I CATED 0 0 0 0 0 0 0 0 7 2 7 FE9BO ACT IVE DED I CATED 0 0 0 0 0 0 0 0 7 2 7 FE9BO INACT IVE 266 Глава 5 Statistics 8 О 2 О О 1004 543 2 О О 2 recurs ive ca l l s d.Ь Ьlock gets cons i s tent gets phys ical reads redo s i ze bytes sent via S QL*Net to client bytes rece ived vi a SQL*Net from c l i ent SQL * Ne t roundt rips t o / f rom c l i ent sorts (memo r y ) sorts ( d i s k ) rows proce s s ed EODA@ORA 1 2 CR1 > set autotrace o f f Теперь в системе присутствуют два сеанса, н о о н и оба применяют единственный процесс выделенного сервера, о чем свидетельствует одно и то же значение PADDR. В операционной системе не было создано ни одного нового процесса, и для обоих сеансов испол ьзуется единственный процесс - одно подключение. Обратите вни­ ман ие, что оди н из сеансов (исходны й ) и меет состояние ACT IVE (активн ы й ) . Это вполне объясн и мо: он выпол няет запрос для отображения при ведеиной инфор­ маци и , так что, естественно, он активе н . Но что собой представляет неакти вный ( I NACT IVE) сеанс? Это сеанс AUTOTRAC E . Его задачей является слежение за ре­ альным сеансом и сообщение о том, что он делает. В случае включения функции AUTOTRAC E в SQL* Plus при выполнении опера­ ций D M L ( I NS ERT , U P DAT E , DELET E , SELECT и MERGE) среда SQL*Plus будет выпол­ нять перечисленные н иже действия. 1 . Она создаст новый сеанс, использующий текущее подключе ние, если второй сеанс пока еще не существует. 2 . Она потребует от нового сеанса запросить представление V$ S E S S TAT для за­ поминания начальных статистических значен и й сеанса, в котором мы будем выпол нять операци ю D M L. Это очень похоже на фун кцию, реализованную сценарием wat ch_s t a t . s ql в главе 4. 3. Она выполнит операци ю D M L в исходном сеансе . 4. П осле завершения оператора D M L среда SQL* Plus снова потребует от нового сеанса выполнения запросить представление V$ S E S S TAT и сгенерировать ра­ нее показанн ы й отчет, отображающий отл ичия в статистических сведениях о сеансе, который выполнил операцию D M L. Есл и в ы отключ ите фун кцию AUTOTRAC E , то среда S Q L* Plus завершит ра­ боту этого доп олнительного сеанса, и вы больше не увидите его в представлен ии V$ S E S S TAT . П очему S Q L* Plus предпринимает такой трюк? Ответ довольно прост. Среда SQL* Plus делает это по той же причине, по которой в главе 4 мы использова­ ли второй сеанс SQL* Plus для мониторинга потребления памяти и временного про­ странства: есл и бы мы применяли для отслеживания использования памяти единс­ твенный сеанс, то определенный объем памяти был бы потрачен на сам мониторинг. Н аблюдая за статистическим и сведениями в одном сеансе , мы неизбежно измени­ л и бы их. Если бы среда SQL* Plus применяла единственный сеанс для сообщения П роцессы O rac l e 267 о количестве выполненных операций ввода-вывода, объеме данн ых, переданных по сети , и числе выполненных операций сортировки , то запросы, используемые для по­ лучения этих сведени й , также внесл и бы свой вклад в статистическую информацию. Они могли бы выпол нять сортировку, операции ввода-вывода, передачу данн ых по сети и т. п . Следовательно, для получения корректных данн ых измерений необходи­ мо применять другой сеанс. До сих пор мы видели подключение с одним или двумя сеансами . Теперь было бы желательно воспользоваться SQL* Plus, чтобы посмотреть на подключение, не имею­ щее сеансов. Это достаточно легко. В том же окне SQL* Plus, которое было открыто в предыдущем примере, введите команду с обманчивым именем D I S CONNECT: EODA@ORA12CR1> dis connect Dls connected from Oracle Databa s e 1 2 с Ente rp r i s e Edi t i on Release 1 2 . 1 . 0 . 1 . 0 - 64bit P roduct i on With the Part i t ioning , OLAP , Advanced Ana1ytics and Rea l App l i cati on Testing opt ions Формально эта команда должна была б ы назы ваться D E S T ROY_ALL_S E S S I ON S (уничтожить все сеансы ) , а не D I SCONNECT (отключиться) , т. к. в действительности она не выполняет физического отключения от базы данных. Н а заметку! Настоящее отключение в SQL* Pius обесnечивает команда exi t, nоскольку для nолного разрыва соеди нения вы должны nроизвести выход. Тем не менее, мы закрыли все сеанс ы . Откроем еще оди н сеанс с применением учетной записи какого-то другого пользователя и выдадим следующий запрос к базе данных (разумеется , замените EODA именем своей учетной записи ) : $ sqlp1us 1 as sysdЬa SQL* Plus : Release 1 2 . 1 . 0 . 1 . 0 Product i on on Thu Mar 20 1 5 : 5 7 : 5 6 2 0 1 4 Copyright ( с ) 1 9 8 2 , 2 0 1 3 , Oracle . А11 rights rese rved . Connected to : Orac1e Databas e 1 2 с Enterprise Edition Release 1 2 . 1 . 0 . 1 . 0 - 64bit Product ion With the Part itioning , OLAP , Advanced Ana l yt i cs and Real App l i ca t i on Testing opt ions SYS@ORA1 2CR1> select * from v$ s e s s i on where use rname = 1 EODA 1 ; no rows selected строки не выбраны Легко заметить, что сеансы отсутствуют, но по-прежнему и меется процесс, физи­ ческое подключение (используется предьщущее значение PADDR) : SYS @ORA12CR1> select use rname , program 2 from v$proce s s 3 whe re addr = hextoraw ( 1 0 0 0 0 0 0 0 0 7 2 7 FE 9B O 1 ) ; USERNAМE PROGRAМ oracle oracle@cs - xvm2 ( TNS V1 -V3 ) Итак, здесь есть подключение без ассоциированн ых с ним сеансов. Для создания нового сеанса в существующем процессе можно применять также не очен ь удач- 268 Глава 5 но названную команду CONNECT из SQL* Plus (более п одходящим именем было бы C REAT E_ S E S S I ON (создать сеанс)). Используя экзем пляр SQL* Plus, в котором было произведено отключение, мы выполняем следующие команды: EODA@ ORA 1 2 CR1 > connect eoda / foo Conne cted . Подключено . EODA@ ORA1 2CR1> s elect use rname , s id , serial # , s e rve r , paddr, status 2 from v$ s e s s i on 3 whe re use rname = USER ; USERNAМE SID SERIAL# EODA 10 25 SERVER PADDR STATUS DED I CATE D 0 0 0 0 0 0 0 0 7 2 7 FE9BO ACT IVE Обратите вниман и е , что значе н ие PAD DR осталось таким же , как ранее, следо­ вательно, мы имеем дело с тем же самым физическим подключением. Но значение S I D п отенциально может быть другим . Потенциально означает, что сеансу может быть назначен и тот же самы й идентифи катор S I D - это просто зависит от того, вошли ли другие пользователи в систему, пока мы были от нее отключены, и от до­ ступности первоначального S I D . Н а заметку! В Windows или других оnерационных систем ах, основанных н а потоках, вы мо­ жете получ ить отличающиеся результаты - адрес процесса может изменяться , поскольку вы подключаетесь к многопоточ ному процессу, а не к специализи рованному процессу, как это происходит в U N IX/Li n ux. До сих пор все тесты выполнял ись с применением подключения посредством выделенного сервера, поэтому значение PADDRR представляло адрес процесса вьще­ ленного сервера. А что происходит, когда используется разделяемый сервер? На заметку! Для подключения через разделяемый сервер экзем пляр базы данных должен быть заnущен с необходимой настройкой. Тема конфигури рования разделяемого сервера выходит за рамки этой кни ги , но подробно рассматривается в руководстве администрато­ ра сетевых служб базы данных Oracle (Oracle Database Net Services Administrator's Guide ) . Давайте войдем в систему с применением разделяемого сервера и выполним за­ прос в этом сеансе : EODA@ ORA1 2CR 1> se1ect a . use rname , a . s i d , a . s e rial # , a . s e rve r , 2 a . paddr , a . status , b . program from v$ s e s s ion а 1 e f t j oi n v$proce s s Ь 3 4 on ( a . paddr = b . add r ) 5 whe re а . use rname = ' EODA ' б 1 USERNAМE S I D SERIAL# SERVER EODA 485 1105 SНARED PADDR S TATUS PROGRAМ 0 0 0 0 0 0 0 0 7 1С4ВЕ68 ACTIVE orac1e @ c s -xvm2 (S004 ) Н аше подключение посредством разделяемого сервера ассоциировано с процес­ сом - есть значение PADDR и с помощью соединения с V$ PROCESS можно извлечь П роцессы Oracle 269 имя этого процесса. В этом случае мы види м , что процесс я вляется разделяемым сервером , о чем свидетельствует строка S O O O . Однако если дл я запроса той ж е информац и и воспол ьзоваться другим окном SQL* Plus, оставив наш сеанс разделяемого сервера бездействующим, мы получ и м примерно такой результат: $ sqlplus 1 as sysdЬa SYS @ORA12CR1> se lect a . use rname , a . s i d , a . serial # , a . s erve r , 2 a . paddr , a . s tatus , b . program 3 from v$ s e s s ion а l e f t j oi n v$proce s s Ь 4 on ( a . paddr = b . addr ) 5 where а . username = 1 EODA 1 б 1 PROGRAМ USERNAМE S I D SERIAL# SERVER PADDR EODA 0 0 0 0 0 0 0 0 71С4 б78 8 INACTIVE oracle@cs -xvm2 ( DO O O ) 485 1 1 0 5 NONE S TATUS Обратите вни ман ие, что значение PAD D R отличается , и и мя процесса, с кото­ рым мы связаны , также изменилось. Бездействующее соединение с разделяе м ым сервером теперь ассоциировано с диспетчером , D O O O . Следовательно, и меется еще один метод наблюдения за множеством сеансов, указывающих на оди н п роцесс. Диспетчер может иметь сотни или даже тысячи указывающих на него сеансов. И нтересная особен ность соеди н е н и й с разделяе м ы м сервером закл ючается в том , что применяемый нами процесс разделяемого сервера может меняться от вы ­ зова к вызову. Есл и я я вля юсь еди н стве н н ы м п ол ьзователем систе м ы ( и это так для проводимых тестов) , то м ногократны й запуск этого запроса от и м е н и E O DA должен производить одно и то же значение PADDR - О О О О О О 0 0 7 1 С 4 ВЕ 6 8 . Однако если открыть больше подкл ючен и й посредством разделяемого сервера и начать их использовать в других сеансах, то можно заметить, что применяем ы й разделяемый сервер варьируется . Рассмотрим пример. Я запрошу и нформацию о текущем сеансе, в том числе имя используемого разделяемого сервера. Затем в другом сеансе разделяемого сервера я выполню длительную операцию (т.е. монополизирую этот разделяемый сервер). При повторном запросе базы данных о применяемом разделяемом сервере , скорее всего, отобразится другой сервер (как если бы исходный сервер обслуживал другой сеанс) . В приведеином ниже примере выделен н ы й полужирным код представляет второй сеанс SQL*Plus, подключенный через разделяемый сервер: EODA@ORA1 2 CR1> sel ect a . use rname , a . s i d , a . seria l # , a . s e rve r , 2 a . paddr, a . s tatus , b . program 3 from v$ s e s s ion а l e f t j o in v$proces s Ь 4 on ( a . paddr = b . addr ) 5 where а . username = 1 EODA 1 б 1 USERNAМE S I D SERIAL# SERVER PADDR EODA 0 0 0 0 0 0 0 0 7 1 С 4 ВЕ б 8 ACT IVE oracle@cs -xvm2 ( 8 0 0 4 ) 485 1105 SНARED S TATUS PROGRAМ 270 Глава 5 В другом терминальном сеансе подключимся к базе данных от имени пользова­ теля sсотт (текст sha red в следующей строке подключения отображается на запись в файле t n sname s . ora, которая и нструктирует SQL* Pius использовать подключение посредством разделяемого сервера): $ sqlplus scott/ tiger@ shared SCOTT@ ORA1 2CR1> ехес dЬms lock . sleep ( 2 0 ) ; PL/SQL procedure successf�lly completed . Процед,ура PL/SQL ;успешно эавершена . В исходном подключении как EODA снова запустим запрос для просмотра инфор­ мации в столбце PROGRAМ: EODA@ORA12CR1> select a . userпame , a . sid, . a . seria l # , a . serve r , 2 a . paddr , a . s tatus , b . program from v$ s e s s ioп а left j oi п v$p roce s s Ь 3 4 оп ( a . paddr = b . addr ) 5 where а . userпame = 1 EODA 1 6 1 USERNAМE S I D SERIAL# SERVER EODA 485 1 1 0 5 SНARED PADDR STATUS PROGRAМ 0 0 0 0 0 0 0 0 7 1С 4 7 8 Е8 ACT IVE oracle@cs -xvm2 ( SOOO ) На заметку! Вам необходимо использовать учетную запись, которая имеет привилегии вы­ полнения для пакета о в м s _ LOCK. Я выдал демонстрационной учетной записи s с о т т п р и в илегии в ы полнения для о в м s LOCK следующи м образом: S Y S @ ORA1 2 C R 1 > graпt execute оп dbms l o c k t o s co t t ; Обратите внимание, что при первой вьщаче запроса в качестве разделяемого сер­ вера применялея S 0 0 4 . Затем во втором сеансе (от имени SCOTT ) был запущен дли­ тельно выполняющийся оператор, которы й монополизировал разделяемый сервер; на этот раз им оказался S 0 0 4 . Выполнение работы назначается первому незанято­ му разделяемому серверу, и поскольку в этом случае н и кто другой не запраш ивал использование разделяемого сервера S 0 0 4 , команда DBMS_LOCK передается именно ему. Когда я снова вьщал запрос в первом сеансе SQL* P\us, он был назначен процес­ су другого разделяемого сервера, S O O O , т. к. разделяемый сервер S 0 0 4 был занят. И нтересно отметить, что синтаксический разбор запроса (который пока не воз­ вращает каких-либо строк) мог быть произведен разделяемым сервером S O O O , из­ влечение первой строки - сервером s О О 1 , извлечение второй строки - сервером S 0 0 2 , а закрытие курсора - сервером S О О З . То есть отдельный оператор может пос­ ледовательно обрабатываться множеством разделяемых серверов. Итак, в этом разделе мы убедились, что подключение - физическая линия связи между клиентом и экзем пляром базы дан ных - может иметь ноль, оди н и более установленных для него сеансов. Мы видели оди н из возможн ых сценариев, когда применяли средство AUTOTRAC E и нтерфейса SQL*Pius. Эту возможность эксплу­ атируют также и м ногие другие инструменты. Н апример, компонент Oracle Forms организует несколько сеансов одного подключения для реализации своих функций отладки . Средство многозвенной прокси-аутентификации Oracle, обеспечи вающее П роцессы O rac l e 271 сквозную идентификацию пол ьзователе й от браузера до базы данных, и нтенсив­ но испол ьзует концепцию единственного подключения с м ножеством сеансов, но в каЖдом сеансе потенциально может быть задействована учетная запись другого пользователя . Мы видели , что с течением времени сеансы могут применять множес­ тво процессов, особенно в среде с разделяемым сервером . Кроме того, в случае ис­ пользования пула подключений Oracle Net сеанс может быть вообще не связан ни с одним процессом ; кл иент будет разрывать соединение по истечен и и установленного интервала бездействия и прозрачн ы м образом восстанавл ивать его при обнаруже­ нии активности. Короче говоря , меЖду подкл ючения м и и сеансами существует отношение типа "многие ко многи м " . Однако наиболее распространенным вари антом , с которым большинство из нас сталкивается день ото дня , является отношение "один к одному" меЖду выделенным сервером и единственным сеансом. Сравнение режимов выделенного сервера, раздел я емого сервера и DRCP ПреЖде чем продолжить исследования остальных процессов, давайте обсудим причины, по которым существуют три режима подключения и когда оди н из них может оказываться более подходящим, чем другой. Когда следуе т использовать выд еле нный сервер Как отмечалось ранее, в режиме выделенного сервера меЖду клиентским под­ ключением и серверн ым процессом и меется соответствие типа " один к одному" . В настоящее время дл я всех приложе ний, основанных на SQL, этот метод подклю­ чения к базе дан ных Orac\e является наиболее распространенным. Он очень прост в настройке, предоставляет самый легкий способ установления подключен и й и требу­ ет незначительного конфигурирования или вообще в нем не нуждается . Поскол ьку есть однозначное соответствие, можно не беспокоиться о том , что длительно выпол няющиеся транзакци и заблокируют другие транзакции . Эти другие транзакции просто будут обрабатываться собственными вьщеленными процессами . Следовательно, такой метод подключения будет единственным, который в ы долж­ ны применять в среде , отличной от OLTP (On- Line Transaction Processing - опе­ рати вная обработка транзакци й ) , где могут существовать дл ительные транзакци и . Конфи гурация с выделенным сервером является рекомендуемой дл я Oracle , и она довольно хорошо масштабируется . До тех пор , пока сервер располагает оборудова­ нием (процессором и ОЗУ) , достаточн ы м для обслуживания необходимого числа процессов выделенного сервера, выделен ный сервер может обеспечивать поддержку тысяч параллельных подключен и й . Определен н ые операции , такие как запуск и л и останов базы данных, должны выполняться только в режиме выделен ного сервера, поэтому каЖдая база данных будет содержать либо обе конфигураци и , л ибо только конфигураци ю с выделенным сервером . Когда следуе т использовать разд еляе мый сервер Установка и конфи гурирование разделяемого сервера хотя и не сложны , но все же требуют выполнения дополнительных действий по сравнению с настройкой вы- 272 Глава 5 деленного сервера. Тем не менее, основное отличие между этим и конфи гурациями связано не с их установкой и конфигурирован ием , а с режимом работы . В случае выделенного сервера между клиентс ки м и подключен иями и серверными процес­ сами и меется однозначное соответствие. В случае разделяемого сервера существует отношение "многие к одному": с одни м разделяемым сервером связано несколько клиентов. Как следует из названия, разделяемый сервер является совместно используемым ресурсом, тогда как выделен ный сервер - нет. При работе с совместно использу­ емым ресурсом необходимо соблюдать осторожность, чтобы не монополизировать его на дл ительные периоды времени. Как уже было показано ранее , выдача прос­ той команды овмs _ LOCK . SLEE Р ( 2 О ) в одном сеансе монополизировала бы процесс разделяемого сервера на 20 секунд. Монопол изация ресурсов разделяемого сервера может создавать видимость "зависания " системы. Н а рис. 5 . 2 были изображен ы два разделяемых сервера. При наличии трех кл и­ ентов, которые все пытаются выполн ить 45-секундный процесс приблизительно в одно и то же время , два из них получили бы ответ за 45 секунд, а третий - за 90 се­ кунд. Отсюда правило номер оди н для разделяемого сервера: обеспечьте , чтобы все транзакции были короткими по продолжительности . Они могут выполняться часто, но должны быть кратким и (в соответствии с характеристиками систем OLTP). Если они не являются коротким и , вы попадете в ситуацию, когда работа всей системы будет выглядеть замедленной из-за того, что разделяемые ресурсы монополизиро­ ван ы нескол ькими процессами . В экстремальных ситуациях, если все разделяемые серверы заняты , система будет казаться зависшей всем пользователям за исключе­ нием нескольких счастл и вчиков, которые монополизировали разделяемые серверы. Еще одна и нтересная ситуация , которую можно набл юдать при работе с раз­ деляем ым сервером - искусственная взаимоблокировка. В случае применения раз­ деляемого сервера несколько сер верных процессов совместно используются по­ тен циально большим сообществом п ользователей . Представим ситуацию с пятью разделяемыми серверами и сотней установленных сеансов пользователей . П ри таких условиях в каждый момент време н и могут быть активными максимум пять из этих сеансов пользователей. П редположим, что оди н из сеансов пользователей обновляет строку и не выпол няет фиксацию . Пока этот пользователь сидит и размышляет над своей транзакцией, пять других сеансов пользователей пытаются заблокировать эту же строку. Естественно, они окажутся заблокированными и будут вынуждены терпе­ ливо дожидаться момента, когда эта строка станет доступной . Наконец, сеанс поль­ зователя , которы й установил блокировку дан ной строки , предприни мает попытку зафиксировать свою транзакци ю (снимая тем сам ым блокировку со строки) . Этот сеанс пользователя обнаружит, что все разделяемые серверы монополизирован ы пя­ тью ожидающими сеансами . Возни кает ситуация искусственной взаимоблокировки : владеле ц блокировки не получит в свое распоряжение разделяемый сервер, чтобы выпол н ить фиксацию транзакци и , есл и только оди н из ожидающих сеансов не ус­ туп ит свой разделяемый сервер. Но если для ожидающих сеансов не определен ин­ тервал истечения времени ожидания, то они никогда не уступят свои разделяемые серверы (разумеется , можно потребовать от администратора, чтобы он уничтожил свой сеанс разделяемого сервера дЛЯ выхода из этой тупиковой ситуации ) . П о описан н ым причинам разделяемый сервер подходит только дл я систем опе­ ративной обработки транзакций (OLTP), которые характеризуются коротки ми, час- П роцессы O racle 273 то выпол няющим ися транзакциям и . В системе OLTP транзакци и выпол ня ются в течение нескольких миллисекунд; нет ничего, что зани мало бы более доли секун­ ды. Разделяемый сервер совершенно не подходит для и нформационных хранилищ. В них MOJYf выполняться запросы, которые зан имают одну, две, пять и более м инут. В режиме разделяемого сервера это было бы смертельно опасным. Если система на 90% является OLTP и на 1 0% - "не совсем OLTP", то в одном и том же экземпляре можно совместно применять выделенные серверы и разделяемый сервер. П одобным образом можно радикально уменьшить количество серверных процессов для пол ь­ зователей OLTP и одновременно предотвратить монопол изацию своих разделяемых серверов пользователям и , которые не являются "в полной мере OLTP" . Вдобавок администратор базы дан н ых может испол ьзовать встроен н ы й диспетчер ресурсов ( Resource Manager) для еще большего контроля над утилизацией ресурсов. Естествен но, веской причиной применения разделяемого сервера я вляется от­ сутствие выбора. М н огие усовершенствованные функци и п одкл ючения требуют использования разделяемого сервера. Если нужны пулы подкл ючений Oracle Net, то применение разделяемого сервера обязательно. Кон центрация соеди нений не­ скольких баз данн ых также требует использован ия разделяемого сервера для таких подключений. Н а заметку! Если в приложении вы уже при меняете пул подкл ючений (например, пул под­ ключений J2EE), и его размер соответствующим образом установлен , то испол ьзовани е разделяемого сервера при ведет только к сниже н и ю п роизводительности. Пул подклю­ чений уже настроен на поддержку такого кол ичества подкл ючени й , которое будет иметь место в любой момент времени; вы хотите , чтобы каждое из этих подключений было пря­ мым подкл ючением к выделенному серверу. В п ротивном случае вы п росто получите пул подключени й , соединяющи йся с еще одни м пулом подкл ючений. Потенциальные преимущества разделяемого сервера Каковы преимущества применения разделяемого сервера с учетом того, что не­ обходимо соблюдать определен ную осторожность в отношении типов транзакци й , которым разрешено его испол ьзовать? Разделяемый сервер делает три вещи: умень­ шает количество процессов/потоков операционной систем ы , искусственно ограни­ чивает уровен ь параллелизма и снижает требуемый объем памяти в системе. Давайте обсудим эти моменты более подробно. Умен ь шение количества процессовjпотоков операционной системы В системе с несколькими тысячами пользователей поп ытка управления тысячами процессов может быстро при водить к перегрузке операционной системы . В типич­ ной системе в любой момент времени одновременно активна только часть из этих тысяч пользователей . Н апример, недавно мне пришлось работать с системой , кото­ рая обслуживала 5000 параллельных пользователей. В каждый кон кретны й момент времени макси мум 50 из них был и акти вн ыми. Эта система могла бы эффективно работать при организаци и 50 процессов разделяемых серверов, что позволило бы со­ кратить количество процессов, которыми должна управлять операционная система, на два порядка (в 1 00 раз) . При такой конфигурации операционная система может в значительной степени избегать переключен ия контекста. 274 Глава 5 И скусственное о граничение уровн я пара лл е лизма М не , как челове ку, который принимал участие во множестве сравн ительных тестов, это преимущества совершенно очевидно. П ри выполне н и и сравнительных тестов люди часто просят создавать максимал ьное количество пользователей вплоть до отказа работы системы . Одни м из результатов таких сравн ительных тестов всегда я вляется график зависимости числа транзакци й от количества одновременно рабо­ тающих пользователей (рис. 5 . 3 ) . К ол и чество транзакций за секу нду Максимальн ы й параллелизм � Коли ч ество одновременно работа ющи х п оль зователей Рис. 5 . 3 . Зависимость ч исла транзакций в секунду от количества одновременно работающих пол ьзователей П ервоначально по мере добавления одновремен но работающих пол ьзователей количество транзакци й увели ч и вается . Однако в определенный момент добавле­ н ие пол ьзователей не приводит к увеличению числа транзакци й , выполняемых в секунду; кривая графи ка начинает понижаться . Пропускная способность достигла максимум а, и теперь начало расти время отклика. Другими словами , вы делаете то же самое количество транзакци й в секунду, но конеч ные пол ьзователи отмечают увеличившееся время отклика. Дал ьнейшее добавление пользователей ведет к дейс­ твительному снижению пропускной способности . Ч исло одновременно работающих пол ьзователей, предшествующее этому снижению, соответствует максимальному уровню п араллел изма, которы й допустим для дан ной системы . Выше этого поро­ га система становится переполиенной и для выполнения работы начинают форми­ роваться очереди . П одобно затору на пун кте дорожного сбора, система больше не может справляться с нагрузкой . В этот момент не только существенно возрастает время откли ка, но также может снижаться пропускная способность системы, пос­ кольку накладные расходы , обусловленные перекл ючением контекста и совместным испол ьзован ием ресурсов между сли ш ком большим кол ичеством потребителей , сами требуют допол н ительных ресурсов. Есл и ограничить максимальный уровень параллелизма значением , непосредственно предшествующим этому спаду графика, Процессы O racl e 275 можно сохранить максимальную пропускную способность и свести к минимуму рост времени отклика для большинства пользователей . Разделяемый сервер позволяет ог­ раничить максимальный уровень параллелизма в системе этим значением. В качестве аналоги и этого процесса можно привести простую дверь. Ш ирина двери и ш ирина каждого человека ограничивают кол ичество л юдей, которые могут пройти через дверь за одну минуту. При низкой нагрузке нет н и каких проблем; од­ нако по мере того, как подходит больше людей, некоторые из них вынуждены ждать ( квант времени процессора). Если пройти через дверь хотят много людей, возни кает эффект обхода - сл и ш ком многие говорят " после вас" и топчутся на месте , при­ водя к падению пропускной способности . Каждый человек проходит с задержкой . Применение очереди означает повышение пропускной способности . Н е которые люди проходят через дверь почти так же быстро, как если бы не было никакой оче­ реди, в то время как другие (попавшие в хвост очереди) ожидают долго и могут бес­ покоиться о том , что " это было плохой идее й " . Но когда вы и змеряете, насколько быстро каждый человек проходил через дверь (включая последнего в очереди), вы­ ясняется , что модель с очередью (разделяемый сервер) работает лучше свободного для всех прохода (даже в случае хорошо воспитанных л юде й ; но вообразите себе двери в магазине в ден ь большой распродажи , когда все грубо толкаются , п ытаясь попасть внутрь) . Снижение требований к памяти системы Это оди н из наиболее громко реклам ируемых доводов в пол ьзу разделяемого сервера: он сн ижает объем требуемой памяти. Действительно, снижение есть, но не настолько значител ьное, как вы могл и бы подумать, особенно с учетом автомати­ ческого управления памятью PGA, обсуждаемого в главе 4, когда рабочие области выделяются процессу, используются и освобождаются - причем их размеры изме­ няются на основе параллельной рабочей нагрузки . Таким образом , этот довод был более весомым в старых версиях Oracle , но в наши дни он не так важен . Кроме того, помните , что когда вы применяете разделяемый сервер, область U GA располагается в области SGA. Это означает, что при переходе на разделяемый сервер вы должны быть способны точно определить ожидаемые потребности в памяти UGA и выде­ лить соответствующий объем в области SGA через параметр LARG E_ POOL_S I Z E . Требования к памяти SGA ДJJЯ конфигурации с разделяемым сервером обычно очень высоки. Эта память должна, как правило, выделяться заранее и , следовательно, мо­ жет использоваться только экземпляром базы данных. Н а заметку! Это nравда, что nри нал и ч и и области SGA изменяемого размера в ы можете увеличи вать и уменьшать ее размер с течением времени, но в целом ею будет владеть экземnляр базы данных, и она не доступна для исnользования другими nроцессами. Сравните это с выделен н ы м сервером , где любой желающий может работать с любой памятью, не выделенной в области SGA. Н о если размер области SGA на­ много больше из-за нахождения в ней области UGA, то откуда берется экономия па­ мяти? Она обусловлена тем , что выделяется гораздо меньше областей PGA. Кажды й выделенный/разделяемый сервер имеет область PGA. В ней хранится информация о процессе . Здесь же расположен ы области сортировки , области хеширования и дру­ гие структуры , связанные с процессом . И менно эту память вы изымаете из системы 276 Глава 5 за счет применения разделяемого сервера. Если вы переходите от 5000 выделенных серверов к 1 00 разделяемым серверам, то экономия памяти, связанная с использо­ ванием разделяемых серверов, будет равна суммарному размеру 4900 областей PGA (исключая их области UGA) , которые больше не нужны. DRCP А что можно сказать о D RC P средстве , доступном в Oracle 1 Ig и последую­ ших версиях? Оно обладает м ноги м и преимуществами разделяемого сервера, таки ­ ми как сокращение количества процессов ( применяется пул), что делает возможной экономи ю памяти без отрицательных последствий . Здесь нет шансов столкнуться с искусствен ной взаимоблокировкой ; например, сеанс, удерживающи й блокировку на ресурсе в рассмотрен ном ранее примере , будет и меть собственный выделенный сервер, назначенный ему из пула, и этот сеанс, в конечном счете , сможет снять эту блокировку. Средство D RCP не поддерживает м ногопоточность разделяемого серве­ ра; когда клиентский процесс получает выделенный сервер из пула, он владеет этим процессом до тех пор, пока клиентски й процесс не освободит его. Следовательно, средство D RC P лучше подходит для клиентских приложений, которые часто под­ ключаются , выполняют некоторое относительно короткое действие и отключают­ ся - и так снова и снова; короче говоря , оно предназначено для клиентских процес­ сов, и меющих АРI-и нтерфейс, который не располагает собственным эффективным пулом соединен и й . - Заключительные соображения по поводу выделенного/ разделяемого сервера Есл и только ваша система не перегружена или вы должны использовать разде­ ляемый сервер для отдел ьной функци и , то выделенный сервер, скорее всего, будет сам ы м подходящим вариантом . Он прост в установке (фактически , вообще ее не требует) и легче в настрой ке. На заметку! В случае подключений с помощью разделяемого сервера информация трас­ сировки сеанса ( в ы вод SQL_TRACE=TRUE ) может распространяться по множеству отде­ л ьных трассировочных файло в ; таким образом, воспроизведение того, что сделал сеанс, становится труднее. С появлением пакета oвмs_MON I TOR в Oracle 1 0g и последующих версиях бол ьшая часть сложностей устранена, но воспроизведение по- прежнему является непростой задаче й . Кроме того, при наличии м ногочисленных связанн ых трасси ровоч ных файлов, сгенерированных сеансом , можно при менять утилиту TRC S E S S для объеди нения всех этих файлов. Если вы и меете дело с очен ь большим сообществом пользователей и знаете, что развертывание будет осуществляться посредством разделяемого сервера, я на­ стоятельно рекомендую проводить разработку и тестирование с использованием разделяемого сервера. Разработка с применением только выделенного сервера без тестирован ия на разделяемом сервере увеличит вероятность возн и кновения сбоя . Обеспечьте максимальную нагрузку в системе , проведите сравнительные тесты про­ изводительности и удостоверьтесь, что приложение будет нормально работать с раз­ деляемым сервером . То есть убедитесь, что приложение не монопол изирует разделя­ емые серверы на сли ш ком длительный период. Если вы обнаружите, что оно делает Процессы O rac l e 277 это, во время разработки , то ситуацию гораздо легче исправить на данном этапе, чем на стадии развертывании. Для преобразования дл итель но выпол ня ющегося процес­ са в предположительно коротки й можно воспользоваться средствами наподобие AQ (Advanced Queuing - усовершенствован ная организация очередей), но это должно быть спроектировано внутри приложен ия . Такого рода вещи лучше делать во время разработки . Кроме того, исторически сложилось так, что между наборами функци ­ ональности , которые доступны подключениям через разделяемый сервер и подклю­ чениям через выделенный сервер, и ме ются отличия. Н апример, мы уже обсуждали отсутствие автоматического управления памятью PGA в Oracle9i, но в прошлом для подключений через разделяемый сервер не был и доступны даже такие важные фун­ кции , как хеш -соединения двух таблиц. (Хеш-соединения доступн ы в текушем вы­ пуске Oracle9i и последующих версиях с разделяемым сервером!) Ф о н о вые процессы Экзем пляр Oracle образован двумя компонентами : памятью SGA и фоновы м и процессами . Фоновые процессы выполняют обычные задачи по обслуживанию, не­ обходимые для поддержан ия базы данных в рабочем состоянии. Н апример, сушес­ твует процесс , которы й обслуживает кеш буферов блоков, по мере необходимости записывая блоки в файлы данных. Другой процесс отвечает за копирование файла оперативного журнала повторен ия при его заполнении в каталог архива. Еще оди н процесс выпол няет очистку за п рерван н ы м и п роцессами и т.д. Каждый из этих процессов довольно точно ориентирован на решение своей задачи , но работает во взаи модействии со всем и остальными процессами. Например, когда процесс , от­ вечающий за зап ись журнальных файлов, заполнит оди н журнал и перейдет к сле­ дующему, он уведомит процесс , который отвечает за архивирование заполненного журнального файла, о появи вшейся для него работе . Доступно представление V$ , которое можно применять для просмотра всех воз­ можных фоновых процессов Oracle и выяснения, какие из них используются в сис­ теме в текущий момент: EODA@ORA1 2 CR1 > s e l ect padd r , name , de scription from v$bgproces s 2 3 orde r Ьу paddr de sc 4 1 NАМЕ DESCRI PT I ON PADDR 0 0 0 0 0 0 0 0 7 2 FD4 4 C 8 ММОN 0 0 0 0 0 0 0 0 7 2 7 FD8 5 0 ММNL 0 0 0 0 0 0 0 0 7 2 3 FE 1 3 8 LREG 0 0 0 0 0 0 0 0 7 2 3 FC FD8 SMON 0 0 0 0 0 0 0 0 7 2 3 F9BB8 СКРТ 0 0 0 0 0 0 0 0 7 2 3 FBA58 LGWR 0 0 0 0 0 0 0 0 7 2 3 F7 8 F8 DBWO Manageab i l i t y Monitor Proc e s s Manageabi l i t y Monitor Proce s s 2 Li s tener Reg i s tration System Monitor Proce s s checkpoint Redo etc . dЬ writer p roce s s О vмво 00 AC FS 00 SCRB 00 XDMG 00 XDWK 00 4 0 1 rows s e l e cted . Vol ume MemЬership О AC FS C S S ASM Sc rubbi ng Ma s t e r ce l l automa t i on manager ce l l automation worker actions 278 Глава 5 Строки этого представления со значением PADDR, отличающимся от 0 0 , пред­ ставляют процессы (потоки) , сконфигурированные и выпол няющиеся в системе. Совет. Другой способ просмотра фоновых п роцессов, в ыполняющихся в текущий момент, п редусматривает запрашивание строк представления v $ PROCE s s , в которых значение РNАМЕ не равно nul l . Различают два класса фоновых процессов: ориентированные н а конкретные за­ дачи (как только что описанный) и предназначенные для выполнения многообразия других задач (т.е. служебные процессы). Н апример, существует служебн ый фоно­ вый процесс для обработки внутрен н их очередей задани й , доступный через пакеты DBMS_JOB / DBMS_S C H E DULER. Этот процесс отслежи вает очереди задан ий и запус­ кает все , что в них появляется . Во многих отношениях он н апоминает процесс вы­ деленного сервера, но без клиентского подключения. Давайте исследуем каждый из этих фоновых процессов, начав с тех, которые ориентированы на конкретные зада­ чи, а затем перейдя к служебны м процессам . Спе ц иализированные ф оновые про цессы Кол ичество, и мена и тип ы специал изированных фоновых процессов варьируют­ ся в зависимости от выпуска. На рис. 5 .4 показан типичный набор фоновых процес­ сов Oracle, и меющих конкретное назначение. �-------------------------������������- : �--т;�:� - --т7:i-· 1 1 1 1 1 1 1 1 Буфе р ы бл о ков 1 ( ) �1111111111111111111'11) Жу р нал nовтор ен ия ( ) Фа й л ы базы данных журна лы - - - - - Р аздел я емая пам ять ------- Сеть --- п овторен ия Д исковы й ввод-вывод Рис . 5 .4 . Специализированные фоновые п роцессы Процессы O rac l e 279 Совет. Пол ная диаграм ма, отображающая все фоновые процессы и структуры памяти Oracle 1 2с, доступна в файле по адресу: www . o racle . com / technetwo r k / tu to r i a l s /po s te r f i l e s - 1 9 7 4 1 0 3 . pd f Например, рассмотрим базу данных, запускаемую с применением м и н имального числа параметров i n i t . ora, в версии Oracle 1 2с Release 1 . SYS@ ORA1 2CR1 > create p f i le= 1 /tmp /p f i l e 1 from sp f i l e ; File created . Файл создан . SYS@ORA12CR1 > ! cat /tmp/pfile * . compatiЫe= 1 1 2 . 1 . 0 . 1 1 * . cont rol_files= 1 /u 0 1 /dЬ fi l e /ORA12CRl /control 0 1 . ctl 1 , 1 /u 0 2 / dЬ fi l e / ORA12CR1 /control 0 2 . ctl 1 * . dЬ Ыосk s i ze=8 1 92 * . db name= 1 0RA12CR1 1 * . memory_target= 5 0 0M * . undo_taЬle space= 1 UNDOTBS 1 1 В Orac1e 1 2с Release 1 запускается около 22 ф оновых процессов: EODA@ORA12CR1> select paddr, name , des cription 2 from v$bgproce s s 3 where paddr <> 1 0 0 1 4 orde r Ьу paddr de s c 5 1 PADDR NАМЕ DESCRI PT ION 0 0 0 0 0 0 0 0 7 F 1 8 8 5 5 8 VKRМ 0 0 0 0 0 0 0 0 7 F1 7 FA58 CJQO 0 0 0 0 0 0 0 0 7 F1 7 E 8 F8 AQPC 0 0 0 0 0 0 0 0 7 F1 7 D7 9 8 FBDA 0 0 0 0 0 0 0 0 7 Fl 7 C 6 3 8 SMCO 0 0 0 0 0 0 0 0 7 F17A3 7 8 TMON 0 0 0 0 0 0 0 0 7 F1 7 5DF8 ММNL 0 0 0 0 0 0 0 0 7 F1 7 4 C 98 LREG 0 0 0 0 0 0 0 0 7 F1 7 3B 3 8 RECO 0 0 0 0 0 0 0 0 7 F1 7 2 9 D8 SMON 0 0 0 0 0 0 0 0 7 F 1 6 F5B8 СКРТ 0 0 0 0 0 0 0 0 7 F1 6E 4 5 8 LGWR 0 0 0 0 0 0 0 0 7 Fl 6D2 F8 DBWO 0 0 0 0 0 0 0 0 7 Fl 6C 1 9 8 DIAO 0 0 0 0 0 0 0 0 7 F1 6B 0 3 8 DBRМ 0 0 0 0 0 0 0 0 7 F 1 6 9ED8 DIAG 0 0 0 0 0 0 0 0 7 F1 6 8 D 7 8 ММОN 0 0 0 0 0 0 0 0 7 F1 6 7 C l 8 ММАN 0 0 0 0 0 0 0 0 7 F1 6 6АВ8 GENO 0 0 0 0 0 0 0 0 7 F 1 6 5 9 5 8 VKTM 0 0 0 0 0 0 0 0 7 F1 6 4 7 F8 P S P O 0 0 0 0 0 0 0 0 7 F 1 6 3 6 98 PMON 22 rows sel ected . 22 строк выбрано . Vi rtual sKedul e r for Resource Manage r Job Queue Coordinator AQ Proce s s Coord Flashback Data Archive r Proce s s Space Manage r Proce s s T ransport Monitor Manageab i l i t y Monitor Proce s s 2 Li stener Regi s t ration di st ributed recove ry System Monitor P roce s s checkpoint Redo etc . dЬ writer proce s s О diagno s ibi l i t y p roce s s О DataBa se Res ource Manage r diagno s ibi l i t y proce s s Manageab i l i t y Monitor Proces s Memo ry Manager gene ricO Vi rtual Keeper o f TiMe proce s s p roce s s spawne r О proces s cleanup 280 Глава 5 В версии Oracle l lg Release 2 с тем же самым файлом i n i t . ora запускается око­ ло 1 7 фоновых процессов: ops $ t kyte@ORA 1 1 GR2 > se lect paddr , name , de scription 2 f rom v$bgproces s 3 where paddr <> ' 0 0 ' 4 o rde r Ьу paddr des c 5 1 PAOOR NАМЕ OESCRI PT ION 3 2AFOE 6 4 CJQO 32AE F B B 4 QМNC 3 2АЕЕ 3 0 4 ММNL 32АЕ О 8 2 С ММОN 32АЕСО 5 4 RECO 32АЕС2 7 С SMON 32АЕВ7А4 СКРТ 3 2АЕАССС LGWR 32AEA1 F4 OBWO 32АЕ 97 1 С ММАN 32АЕ В С 4 4 OIAO 32АЕ 8 1 6С P S P O 32АЕ 7 6 9 4 ОВRМ 32АЕ 6ВВС OIAG 32АЕ 6 0 Е 4 GEN O 32АЕ 5 6 0 С VKTM 32АЕ 4 В 3 4 PMON Job Queue Coordinator AQ Coordinator Manageab i l i ty Moni tor Proce s s 2 Manageabi l i t y Monitor P roce s s dist ributed recove ry S ys tem Moni tor Proce s s checkpoint Redo etc . dЬ writer proce s s О Memory Manager diagnos ibil i t y proce s s О proce s s spawner О OataBase Re source Manage r diagno s i b i l i t y proces s genericO Virtual Keeper o f T iMe p roces s p roce s s cleanup 1 7 rows selected . Воспользовавшись тем же файлом i n i t . ora, но с заменой в нем MEMORY TARGET на S GA_TARGET и PGA_AGGREGATE_TARGET, в 0rac1e l Og Re1ease 2 вы увидите всего 1 2 процессов: _ ops $ t kyte@ ORA1 0GR2 > s e l ect paddr , name , de scription 2 f rom v$bgproces s 3 where paddr <> ' 0 0 ' 4 o rde r Ьу paddr des c 5 1 PAOOR NАМЕ OESCRI PT ION 2 3 02 7АС4 CJQO 2 3 02 7 5 0 8 QМNC 2 3 02 6 9 9 0 ММNL 2 3 02 6 304 ММОN 2 3 02 5E l 8 RECO 2 3 О2 5 8 5С SMON 2 3 02 52АО СКРТ 2 3 02 4СЕ4 LGWR 2 3 02 4 7 2 8 OBWO 2 З О2 4 1 6С ММАN 2 3 02 3ВВО PSPO 2 3 02 3 5 F4 PMON Job Queue Coordinator AQ Coordina tor Manageab i l i t y Monitor Proce s s 2 Manageab i l i t y Monitor Proces s distributed recove ry S ys tem Monitor Proce s s checkpoint Redo etc . dЬ writer proce s s О Memory Manager proce s s spawner О p roces s cleanup 12 rows selected . П роцессы Oracl e 281 Обратите внимание, что при запуске экземпляра вы можете не увидеть все эти процессы, но большинство из них будет присутствовать. П роцесс ARCn (архиватор) вы будете наблюдать только в режиме ARC H I EVELOG при включе нном автоматичес­ ком архи вировании . П роцессы LMD O , LCKn, LMON и LMSn (подробнее они рассмат­ риваются н иже) будут видны только в случае запуска Oracle RAC конфигураци и Oracle, которая позволяет множеству экзем пляров на разных компьютерах в класте­ ре монтировать и открывать одну и ту же физическую базу данных. - На заметку! Начиная с вы пуска Oracle 1 2с, на некоторых платформах U N IX/Liпux вы можете применять смесь п роцессов и п отоков. Эта возможность включается установкой пара­ метра инициализации THREADED_EXECUT I ON в T RUE (стандартны м значением я вляется FAL S E ) . Фундаментально ничего не меняется - все "процессы " по-прежнему на месте ; вы лишь можете не увидеть их с помощью команды p s операционной систе м ы , т. к. теперь они выполняются в виде потока в рамках более крупного п роцесса. Итак, на рис. 5.4 грубо изображено то, что можно видеть после запуска экземпляра Oracle и последующего монтирования и открытия базы данн ых. В среде операцианной системы, где Oracle реализует архитектуру с м ножеством процессов , такой как U N IX/Linux, вы можете физически наблюдать эти процессы . П осле запуска экземпляра я вижу следующую и нформацию: $ ps -ae f 1 grep ora_ . . . . _$0RACLE_S I D 1 grep -v g rep 1 о 10 : 33 ? 0 0 : 0 0 : 0 0 o ra_pmon_ORA1 2CR1 2276 oracle 2278 1 о 10 : 33 ? orac1e 0 0 : 0 0 : 0 0 ora_pspO_ORA12CR1 1 о 10 : 33 ? 2280 0 0 : 0 0 : 0 4 ora vktm ORA1 2CR1 oracle 1 о 1 0 : 33 ? 2284 oracle 0 0 : 0 0 : 0 0 ora_gen0_0RA1 2CR1 1 о 1 0 : 33 ? 2286 oracle 0 0 : 0 0 : 0 0 ora mman ORA1 2 CR1 1 о 1 0 : 33 ? 0 0 : 0 0 : 0 0 o ra_diag_ORA1 2CR1 22 90 oracle 1 о 10 : 33 ? 2 2 92 0 0 : 0 0 : 0 0 ora dЬrm ORA1 2CR1 oracle 1 о 1 0 : 33 ? 22 94 0 0 : 0 0 : 0 0 ora diaO ORA1 2 CR1 oracle 1 о 1 0 : 33 ? 22 9 7 0 0 : 0 0 : 0 0 o ra dЬwO ORA1 2CR1 oracle 1 о 1 0 : 33 ? 22 99 0 0 : 0 0 : 0 0 o ra_l gwr_ORA1 2 CR1 oracle 1 о 10 : 33 ? 2301 oracle 0 0 : 0 0 : 0 0 o ra_ckpt_ORA1 2CR1 2303 1 о 1 0 : 33 ? 0 0 : 0 0 : 0 0 o ra_l g O O_ORA1 2 CR1 oracle 1 о 1 0 : 33 ? 2305 0 0 : 0 0 : 0 0 o ra_lg0 1_0RA1 2 CR1 oracle 1 о 1 0 : 33 ? 2307 0 0 : 0 0 : 0 0 o ra smon ORA 1 2 CR1 oracle 1 о 1 0 : 33 ? oracle 2309 0 0 : 0 0 : 0 0 ora reco ORA 1 2 CR1 1 о 1 0 : 33 ? 2311 0 0 : 0 0 : 0 0 o ra_l reg_ORA1 2CR1 oracle 1 о 1 0 : 33 ? 2313 oracle 0 0 : 0 0 : 0 1 ora mmon ORA1 2 CR1 1 о 1 0 : 33 ? 2315 0 0 : 0 0 : 0 0 ora mmnl ORA1 2 CR1 oracle 1 о 1 0 : 33 ? 2327 oracle 0 0 : 0 0 : 0 0 o ra_p O O O_ORA1 2CR1 1 о 1 0 : 33 ? 232 9 0 0 : 0 0 : 0 0 o ra_p 0 0 1_0RA1 2 CR1 oracle 1 о 1 0 : 33 ? 0 0 : 0 0 : 0 0 ora tmon ORA1 2 CR1 2331 oracle 1 о 1 0 : 33 ? 2333 0 0 : 0 0 : 0 0 ora t t O O ORA1 2CR1 oracle 1 о 1 0 : 33 ? 2335 0 0 : 0 0 : 0 0 ora smco ORA1 2CR1 oracle 1 о 1 0 : 33 ? 0 0 : 0 0 : 0 0 o ra fbda ORA1 2CR1 2337 oracle 1 о 1 0 : 33 ? 2339 oracle 0 0 : 0 0 : 0 0 o ra_aqpc_ORA1 2 CR1 1 о 1 0 : 33 ? 0 0 : 0 0 : 0 0 o ra_cj qO_ORA1 2CR1 2343 oracle 1 о 10 : 33 ? 2345 oracle 0 0 : 0 0 : 0 0 o ra_p 0 0 2_0RA1 2CR1 1 о 1 0 : 33 ? 2347 0 0 : 0 0 : 0 0 ora_p 0 0 3_0RA1 2CR1 oracle 1 о 1 0 : 33 ? 2349 0 0 : 0 0 : 0 0 ora_p 0 0 4_0RA 1 2 CR1 oracle - - - - - - 282 Глава 5 oracle o racle oracle oracle o racle oracle oracle oracle 2351 2353 2355 2383 2385 2389 2391 2 4 65 1 1 1 1 1 1 1 1 о 10 : 33 ? о 10 : 33 ? о 10 : 33 ? о 10 : 33 ? о 10 : 33 ? о 10 : 33 ? о 1 0 : 33 ? о 1 0 : 38 ? 0 0 : 0 0 : 0 0 ora_p 0 0 5_0RA12CR1 0 0 : 0 0 : 0 0 ora_p00 6_0RA1 2CR1 0 0 : 0 0 : 0 0 ora_p 0 0 7_0RA12CR1 0 0 : 0 0 : 0 0 ora w O O O ORA12CR1 0 0 : 0 0 : 0 0 ora_qm0 2_0RA1 2CR1 0 0 : 0 0 : 0 0 ora_q00 2_0RA1 2CR1 0 0 : 0 0 : 0 0 ora_q0 0 3_0RA1 2CR1 0 0 : 0 0 : 0 0 ora w0 0 1 ORA12CR1 И нтересно отметить испол ьзуемое этим и процессами соглашение по именова­ н и ю . И мя процесса начинается с префикса o r a _. За ним следуют четыре символа, представля ющие действительное и мя процесса, а потом - _ORA1 2CR1 . Так получи­ лось, что мой ORACLE_S I D (идентификатор узла) выглядит как ORA1 2CR1 . В системе U N I X/Linux это соглашение по именованию позволяет без труда идентифицировать фоновые процессы Oracle и ассоциировать их с конкретным экземпляром (в системе Windows простого способа достичь аналогичной цели не существует, поскольку фо­ новые задачи являются потоками внутри большого одиночного процесса). Н аиболее и нтересная , но не сразу заметная в приведеином коде особенность, заключается в том , что все эти процессы в действительности представляют собой одну и ту же дво­ ичную исполняемую программу - не существует отдельного исполняемого файла для каждой "программы ". Как бы тщательно вы не искал и , вы н и где не обнаружите на диске двоичный исполняемый файл с именем ora_pmon_ORA 1 2 C R 1 . В ы не найдете и файл o r a l gw r_ORA1 2 CR1 л ибо o r a_reco_ORA 1 2 CR1 На самом деле все упомя ­ нутые процессы - это o r a c l e (таково имя запускаемого двоичного исполняемого файла) . Просто во время запуска экземпляра они назначают себе псевдонимы, об­ легчающие их идентификацию. На платформе U N I X/Linux такой подход обеспечи­ вает эффективное совместное использован ие значительной части объектного кода. В среде Windows данное обстоятельство не представляет такого интереса, поскольку эти компоненты являются л и ш ь потоками внутри процесса и , следовательно, они входят в оди н большой двоичный файл . Давайте теперь взглянем на фун кцию, вы пол няемую каждым крупным процес­ сом , нач и н ая с основных фоновых процессов Oracle. Полный список возможных фоновых процессов и краткое описание выпол няемых ими фун кци й вы найдете в руководстве Oracle Database Refereпce, свободно доступном по адресу: http : / / otn . oracle . com PMON. монитор процессов Этот процесс отвечает за очистку после ненормального закрытия подключений. Н апример, если выделе н н ы й сервер выдает сбой ил и ун ичтожается по какой -то причине, то PMON является процессом, которы й отвечает за исправлен ие ситуации (восстановление или отмену работы) и освобождение ресурсов. П роцесс PMON будет и н и ц иировать откат незафиксированн ых транзакци й , снятие блокировок и осво­ божден ие ресурсов SGA, выделенн ых отказавшему процессу. В дополнение к очистке после прерванн ых подключений процесс PMON отвечает за мониторин г других фоновых процессов Oracle, а также их перезапуск в случае не­ обходимости (есл и это возможно). Если в разделяемом сервере или диспетчере про­ исходит отказ (авария ) , п роцесс PMON вступает в действие и перезапускает другой процесс (после выполнения очистки за отказавши м процессом) . Процессы Oracle 283 Процесс PMON будет наблюдать за всеми процессами Oracle и л ибо перезапускать их, л ибо прекращать работу экземпляра подходящим образом. Н апример, в случае отказа процесса записи журнал а базы дан н ых, LGWR, и меет смысл прервать работу экземпляра. Эта серьезная ошибка, и наиболее безопасным образом действий будет немедленное прекращение работы экзем пляра и предоставление программе восста­ новления возможности исправления дан н ых. (Следует отметить, что подобная ситу­ ация встречается редко, и о ней нужно немедленно сообщать в службу поддержки Oracle Support.) Н а заметку! До выхода версии Oracle 1 2с, п роцесс PMON обрабатывал задачи регистраци и прослушивателем . Начиная с Oracle 1 2с, фоновый п роцесс регистраци и прослушивателем ( LREG) регистрирует экземпляры и службы посредством прослуши вателя. LREG: процесс ре rистрации прослушивателем Процесс LREG (доступный, начиная с выпуска Oracle 1 2с) отвечает за регистрацию экземпляров и служб с помощью проелушивающего процесса Oracle TN S . Когда эк­ земпляр запускается , процесс LREG запрашивает известный адрес порта, если только он не переадресован в другое место, чтобы выяснить, функционирует ли проелуши ­ вающий процесс. Известным/стандартным портом, применяемым Oracle , я вляется порт 1 52 1 . Что случится , если проелуши вающий процесс запущен на каком-то дру­ гом порте? В этом случае механизм остается таким же за исключением тоrо, что адрес проелушивающего процесса должен быть явно указан в параметре LOCAL _L I S T ENER. Вы можете также использовать параметр REMOTE_L I STENER, чтобы проинструктиро­ вать LREG о необходимости регистрировать службу посредством удаленного проелу­ шивающего процесса (это распространенная ситуация в средах Oracle RAC) . Если проелушивающи й процесс работает в о время запуска экземпляра базы дан ­ ных, то LREG связывается с проелушивающим процессом и передает ему соответс­ твующие параметры, такие как и мя службы и показатели нагрузки экземпляра. Если же проелушивающий процесс не был запущен , LREG будет периодически (обычно каждые 60 секунд) пробовать связаться с ним, чтобы зарегистрировать себя . Вы мо­ жете также выдать команду ALT E R S YSTEM REG I S TER, указав LREG о том, что нуж­ но попытаться немедленно зарегистрировать службу с помощью проелушивающего процесса (это полезно в средах с высокой готовностью). sмон: системный монитор SMON это процесс, который делает всю работу на уровне системы. В то вре­ мя как PMON обслуживает отдельные процессы , SMON занят проблемами системного уровня и является своего рода сборщиком мусора в базе данн ых. Н иже перечислены некоторые выпол няемые и м задач и . - • Очистка временного пространства. С появлением н астоящих времен н ых таб­ личных пространств задача оч истки временного п ространства стала менее трудоемкой , но н е исчезла. Н апример, при построен и и и ндекса экстенты , выделенные для и ндекса во время создания , помечаются как TEMPORARY (вре­ менный). В случае прерывания сеанса CREAT E I N DEX по какой-либо причине процесс SMON должен очистить эти экстенты . Другие операции также создают временные экстенты , за очистку которых также отвечает PMON. 284 Глава 5 • Объединение свободного пространства. При использовании табличных про­ странств, управляемых словарем , процесс SMON отвечает за объединение групп свободных, расположенных по соседству друг с другом экстентов табличного пространства в один большой свободный экстент. Это объединение выполня ­ ется только в табличных пространствах, управляемых словарем, со стандарт­ ной конструкцией хранения , которая и меет параметр PCT I NCREAS E, установ­ ленный в иенулевое значение. • Восстановление активных транзакций с учетом недоступных файлов. Эта зада­ ча аналогична решаемой во время запуска базы данных. В ходе ее выполнения процесс SMON восстанавливает отказавшие транзакции, которые были пропу­ щен ы во время восстановлен ия экземпляра или состояния после аварии из-за недоступности файла (файлов) процессу восстановлен ия . Н апример, файл мо­ жет размещаться на диске, которы й бьm недоступен или не был смонтирован. Когда файл станет доступным, процесс SMON восстановит его. • Восстановление экземпляра для отказавшего узла в среде RAC. В конфигура­ ции Oracle RAC при отказе экзем пляра базы дан ных в кластере (например, если отказы вает комп ьютер, на котором выполнялся экземпляр) какой-то дру­ гой узел этого кластера откроет файлы журнала повторен ия отказавшего эк­ земпляра и проведет восстановление всех его данных. • Очистка OBJ$ . Здесь O B J $ это н изкоуровневая табли ца словаря дан ных, которая содержит записи для практически всех объектов (таблиц, и ндексов, три ггеров, представлени й и т.д. ) базы данных. Во многих случаях в ней нахо­ дятся записи удаленных объектов или "отсутствующих" объектов, используе­ мых механизмом зависимостей Oracle. Процесс SMON удаляет эти строки , ко­ торые больше не нужн ы . • Управление сегментами отмены. П роцесс SMON будет выполнять автоматичес­ кое присоединение, отсоединение и сегментов отмены. • Отсоединение сегментов отката. Когда применяется руч ное управление сег­ ментами отката (не рекомендуется ; вы должны использовать автоматическое управлен и е сегментами отката) , адм и н истратор базы дан ных может отсо ­ единять, или делать недоступн ы м , сегмент отката, которы й имеет активные транзакции . Акти вные транзакции могут пол ьзоваться этим отсоединенным сегментом отката. В таком случае сегмент отката не я вляется действительно отсоедин е н н ы м ; он помечается как " ожидающий отсоединен ия " . Процесс SMON будет в фоновом режиме периодически пробовать отсоеди нить его, пока это ему не удастся. - И зложе н н ы й материал должен дать вам представление о том , что делает про­ цесс SMON. Он выпол няет м ного других действий, таких как сброс на диск статис­ тической и н формаци и монитори н га, отображаемой в представлении D BA_ ТАВ _ MOD I FICAT I ONS, зап ись информации преобразования временной метки , хранящейся в табли це S MON_SCN_T I M E , и т.д. Со временем процесс SMON может занимать до­ вольно большую дол ю ресурсов процессора, и это должно сч итаться нормальным. Периодически SMON пробуждается (самостоятельно или другими фоновыми процес­ сами) для решения своих задач по наведению порядка в системе. П роцессы O rac l e 285 RECO: распределенное восстановление базы данных Процесс RECO решает очень узкую задачу: он восстанавл ивает транзакц и и , кото­ рые остались в подготовленном состоянии вследствие авари и или утери подключе­ н ия во время двухфазной фиксации (two-phase commit - 2 РС). 2 РС - распределен­ ный протокол, которы й делает возможной автоматическую фиксацию изменени й , влияющих н а множество физически разрозненных баз данн ых. Перед фиксацией о н предпринимает попытку максимально сузить временное окно распределенного сбоя . В рамках протокола 2 РС среди N баз дан ных одна из них - обычно (но не всегда) база данных, в которую клиент вошел первоначал ьно - будет координатором. Этот узел будет запраши вать остальн ые N - 1 узлов об их готовности к фи ксации. Каждый из N- 1 узлов сообщает свое состояние готовности как YES (да) или NO (нет) . Если любой из узлов возвращает NO, производится откат всей транзакции. Есл и все узлы сообщают YES , то узел-координатор распространяет сообщение о необходимости выполнить фиксацию на каждом из N - 1 узлов. Если после того, как узел сообщил о своей готовности к фи ксаци и , но до по­ лучения от координатора директи вы о необходимости действительного выполнения фиксации происходит сбой в сети или какая-то другая ошибка, транзакция стано­ вится сомнительной распределенной транзакцией. П ротокол 2РС пытается ограничить временное окно, в рамках которого это может случиться , но не в состоян и и устра­ нить его полностью. Если отказ возник здесь и сейчас, то транзакция переходит под ответствен ность процесса RECO. Этот процесс попытается связаться с координато­ ром транзакции для выяснения ее результата. До тех пор, пока он не сделает это, транзакция будет оставаться в незафиксированном состоян и и . Когда процессу RECO удастся снова связаться с координатором транзакции , он выполнит либо фиксацию , либо откат транзакции. Следует отметить, что при наличии каких-то невыполненных транзакций и дл и ­ тел ьном периоде п ростоя фиксаци ю/откат эти х транзакций можно производить вручную. Это может понадобиться по той причи н е , что сом н ительные распреде­ ленные транзакци и могут приводить к блокированию процессов чтения процессами записи - одна из ситуаци й , которая может произойти в среде Orac1e. В этом случае адми н истратор базы данных может связаться с администратором другой базы дан ­ ных и попросить его проверить состоя н ие таких сомнительных транзакци й . Затем адми нистратор базы данных может выпол нить фиксацию или откат этих транзак­ ций, освобождая процесс RECO от этой задачи . СКРТ: процесс выполнения контрольных точек Вопреки своему названию, процесс выполнения контрольн ых точек не произво­ дит зап ись контрольных точек (контрольные точки обсуждались в главе 3, в разделе , посвященном журналам повторения) - по большей части это задача процесса DBWn. Процесс СКРТ просто облегчает работу процессу записи контрольных точек, обнов­ ляя заголовки файлов данн ых. Ран ьше СКРТ считался необязательным, но, начи ная с версии Огас1е 8.0, он запускается всегда. П оэтому если вы введете команду p s в UNIX/Linux, то обычно увидите его (здесь указано "обычно" потому, что в Огас1е 1 2с процесс выполнения контрольных точек может быть запущен внутри потока опера­ ционной системы и, следовательно, не отображаться в качестве процесса). 286 Глава 5 П р инято считать, что работа по обновлению заголовков файлов данных и нфор­ мацией о контрольных точках принадЛежит процессу LGWR. Однако с увеличением количества файлов и ростом размера базы дан н ых с течением времени эта дополни­ тельная задача становится сл и ш ком большой нагрузкой для LGWR. Если бы процесс LGWR был вынужден обновлять десятки , сотни или даже тысячи файлов, то вполне вероятно, что сеансам пришлось бы очень долго дожидаться фиксации этих тран­ закций. Процесс СКРТ освобождает LGWR от этой обязанности . DBWn: процесс записи блоков базы данных П роцесс записи блоков базы данных ( DBWn ) - фоновый процесс, отвечающи й за запись грязных блоков на диск. Этот процесс будет записывать грязные блоки из буферного кеш а обычно с целью освобождения в нем места (Д!IЯ подготовки буфе­ ров к чтению других дан ных) или для продвижения контрольной точки (Д!Iя пере­ хода на следующую позицию в файле оперативного журнала повторения, с которой СУБД Oracle должна будет начинать чтение при восстановлении экземпляра пос­ ле аварийного отказа) . Как обсуждалось в главе 3, при переключении журнальных файлов выдается с игнал о создании контрольной точки . СУБД Oracle необходимо продвинуться к следующей контрольной точке, чтобы больше не нуждаться в только что заполнен ном файле оперативного журнала повторен ия . Если это не будет сде­ лано к моменту, когда потребуется снова испол ьзовать файл журнала повторения , отобразится сообщение "checkpoint not complete" ( " контрол ьная точка не заверше­ на") и придется дожидаться завершения операци и . На заметку! П родвижение журнальных файлов - только один и з м ногих способов создания контрольных точек. Существуют и н крементныв контрольные точки, управляемые таким и параметра м и , как FAS T_S TART_M T T R_TARG E T , и другие триггеры , которые вызывают сброс грязных блоков на диск. Как видите, производительность процесса DBWn может быть критически важной. Если он не будет записывать блоки в свободные буферы (буферы , которые могут пов­ торно использоваться для кеширования других блоков) достаточно быстро, то мы за­ метим увеличение количества и ДJiительности периодов ожидания Free Bu ffer Wai t s (Ожидание появления свободного буфера) и Wri te Complete Wa i t s (Ожидание окон­ чания записи) . М ы можем сконфигурировать более одного процесса oвwn; на самом деле в Oracle l lg допускается настраивать до 36 процессов DBWn ( DBW O . . . DBW 9 , DBWa . . . DBW z ) , а в Oracle 1 2с - до 1 00, о чем свидетельствует следующий запрос: EODA@ORA12CR1> select name , de scription from v$bgproce s s 2 where de s cription l i ke ' dЬ wri ter proces s % ' ; NАМЕ DESCRI P T I ON DBWO dЬ writer proce s s о DBW 1 dЬ writer proce s s 1 DBW2 dЬ writer proce s s 2 BW 9 7 d b w r i t e r proce s s 9 7 BW 9 8 dЬ writer p roce s s 9 8 BW 9 9 d b writer proce s s 9 9 1 0 0 rows selected . П роцессы O rac l e 287 Большинство систем работают с одн и м процессом записи блоков базы данных, но в круп ных многопроцессорн ы х системах могут применяться несколько таких процессов. Обычно это делается для распределения рабочей нагрузки , связанной с поддержанием в чистом виде большого буферного кеша блоков внутри области SGA, путем сбрасывания грязных (модифицированн ых) блоков на диск. В оптимал ьном случае для записи блоков на диск процесс D B W n испол ьзует асинхронный ввод-вывод. В этом случае DBWn собирает пакет блоков, п одлежащих зап иси , и передает их операционной системе. П роцессу D BWn не приходится ожи­ дать, пока операционная система действительно зап и шет блоки ; вместо этого про­ цесс приступает к сборке следующего п акета, которы й должен быть записан. Когда операционная система завершает зап ись, она аси нхронно уведомляет об окончан и и процесс DBWn. Это позволяет процессу DBWn работать намного быстрее, ч е м при вы­ полнении всех действий последовательн ым образом. П озже в разделе " Подчиненные процессы " вы узнаете , как применять подч и ненные п роцессы ввода-вывода для эмуля ции асинхронного ввода-вы вода на платформах или в конфигурациях, кото­ рые его не поддерживают. Я хотел бы сделать фи нальное замечание относительно процесса DBWn. М ожно почти не сомневаться , что процесс DBWn будет записывать блоки вразброс по все­ му диску - он производит множество операци й записи с разнесением данных. П р и выполнении обновления вы будете модифицировать индексные блоки , хранящиеся в различных областях диска, и блоки дан ных, которые также распределены по диску случайным образом. С другой стороны , процесс LGWR выпол няет множество п осле­ довательн ых операци й записи в журнал повторения . Это важное отличие и одна из причин нал ичия в Oracle журнала повторения и процесса LGWR, а также процесса DBWn. Зап ись с разнесением данных происходит значительно медленнее последова­ тельных операций зап иси. И мея в своем распоряжении грязные блоки буфера SGA и процесс LGWR, выполняющий объемные последовательные записи, которые могут воссоздавать эти грязн ые буфер ы , можно увеличить производительность системы. То, что процесс DBWn делает свою медленную работу в фоновом режиме, в то вре­ мя как процесс LGWR запускает свои более быстрые операции в периоды ожидания пользователя, способствует увеличен и ю общей производительности систе м ы . Это действительно так, несмотря на то, что Oracle может формально выпол нять боль­ ше операци й ввода-вывода, чем необходимо (запись в журнал и в файл данных). Теоретически запись в операти вный журнал повторен ия можно было бы пропустить, если бы во время фи ксации вместо этого СУБД Oracle физически записывала изме­ ненн ые блоки на диск. На практике дело обстоит и наче : LGWR выполняет запись ин­ формации повторения в операти вные журналы повторен ия для каждой транзакци и , а DBWn сбрасывает блоки базы данн ы х н а диск в фоновом режиме. LGWR: процесс записи журналов П роцесс LGWR отвечает за сброс на диск содержимого буфера журнала повторения, находящегося в области SGA. Это делается в одном из следующих сценариев: • каждые три секунды ; • когда выдается COMMI T или ROLLBACK; • когда процесс LGWR получает запрос на переключение журнальных файлов; • когда буфер повторения заполняется на одну треть или объем содержащихся в нем кешираван ных дан ных журнала повторения составляет l М байт. 288 Глава 5 По этим причинам нал ич ие огромного (объемом в сотни или тысячи мегабайт) буфера журнала повторения нецелесообразно; Oracle н и когда не сможет задейство­ вать его цел и ком , т. к. практически постоянно производит сброс буфера на диск. В отличие от ввода-вы вода с разнесен ием данных, которы й должен выпол няться процессом D B W n , журналы запол няются с помощью последовател ьных операци й записи . Выполнение таких п акетных операций записи значительно эффективнее выполнения множества операций записи с разнесением данн ых в различные час­ ти файла. Это одна из основных причин применения процесса LGWR и журналов повторения. Повышение эффективности за счет использования последовательного ввода-вывода для записи только изменившихся байтов перевеши вает недостаток, связанн ы й с увеличением количества операций ввода-вы вода. СУБД Oracle могла бы просто записывать блоки базы данных прямо на диск во время фиксации , но это привело бы к м ногочисленным операция м ввода-вывода с разнесением данн ых целых блоков, которые происходил и бы значител ьно медленнее последовательной записи изменен и й процессом LGWR. На заметку! Начи ная с выпуска Oracle 1 2с, на многоп роцессорных машинах будут запус­ каться дополнительные процессы LGO ( Log Writer Worker - обработч ик п роцесса записи в журнал ) , направленные на повышение п роизводительности записи в файлы оперативных журналов повторен и я . AR Cn: архивный процесс Задачей процесса ARCn является коп ирование файла операти вного журнала пов­ торения в другое место, когда он запол няется процессом LGWR. Затем эти архивные файлы журналов повторен ия можно применять для восстановления с носителя . В то время как оперативный журнал повторения используется для исправления файлов данных при сбое электроп итания ( когда экзем пляр прекращает работу), архивные журналы повторен ия служат для исправления файлов данных в случае аварийного отказа диска. П р и выходе из строя дискового устройства, содержащего файл дан ­ ных, / u 0 1 / db f i l e / O RA 1 2 C R 1 / s y s t em 0 1 . db f , можно обратиться к резервным коп иям , созданн ы м на прошлой неделе, восстановить эту старую копи ю файла, и затем потребовать от базы данных применения всех архивных и операти вн ых жур­ налов повторения, сгенерированных с момента последнего резервного копирования. Это свяжет упомянутый файл с остальными файлами в базе дан ных, и мы можем продолжать работу без утери какой-л ибо информации . Процесс ARC n обычн о коп ирует файлы оперативного журнала повторения, по крайней мере , в два доп ол нительных местоположения (избыточность - ключевое средство предотвраще ния утери дан ных). Эти м и местоположениями могут быть диски на локальном компьютере или , что более целесообразно, хотя бы один из них должен находиться на совершенно друтом компьютере на случай катастрофического отказа. Во м ногих ситуациях эти архивные файлы журналов повторения коп ируют­ ся другим процессом на какое-то третье устройство хранения, подобное магнитной ленте. Они могут также пересылаться на другой комп ьютер для применения к ре­ зервной базе дан н ых - вариант обхода отказа, предлагаемый Oracle. Мы вскоре об­ судим испол ьзуемые при этом процессы. П роцессы Oracle 289 DIAG: процесс диагностики В прежних вы пусках процесс D I AG применялея исключ ительно в среде RAC . Начиная с Oracle l lg, с его средством ADR (Advanced Diagnostic Repository - репо­ зитарий расширенной диагностики ), именно процесс D IAG отвечает за мониторинг общей работоспособности экземпляра и фиксирует и нформацию, необходимую для обработки отказов экземпляра. Это касается как конфигураций с одним экземпля­ ром , так и многоэкземплярных конфигураций RAC. FВDA: процесс архивации ретроспективных данных Процесс архивации ретроспективных данных ( Fiashback Data Archiver - FB DA) доступен в Oracle l lg Release 1 и последующих версиях. Это кл ючевой компонент средства архивирования ретроспективных данных - возможности запраш ивать дан­ ные в том виде , в каком они пребы вали в определенный момент времени в про­ шлом (например, запросить данные таблицы, как они выглядели год назад, пять лет назад и т.д.). Такая возможность достигается благодаря ведению хронологии измене­ ний каждой строки в таблице со временем. Эта хронология , в свою очередь, подде­ рживается процессом FBDA в фоновом режиме. Указанн ы й процесс функционирует, выполняя свою работу вскоре после фиксации транзакци и . Процесс F B DA читает данн ые отката, сгенерированные этой транзакцией, и производит откат сделанных ею изменени й . Затем он регистрирует полученные в результате отката строки (ис­ ходные значения) в архиве ретроспективных данных. DBRМ процесс диспетчера ресурсов Процесс диспетчера ресурсов базы данн ых ( Database Resource Manager - DBRM) реализует планы ресурсов, которые могут быть сконфигурированы для экземпляра базы данных. Он устанавливает эти планы ресурсов и выполняет различные опера­ ции, связанные с принудительным применениемjвнедрен ием этих планов ресурсов. Диспетчер ресурсов позволяет адми н истраторам базы данных и меть детал изирован ­ ный контроль над ресурсами , используемыми экзем пляром базы данных, приложе­ ниям и , и меющими доступ к базе дан н ых, либо и ндивидуальными пользователями , обращаюшимися к базе данных. GENO: процесс выполнения общей задачи Процесс выполнения общей задачи (General Task Execution Process) , как сле­ дует из его назван ия , предоставляет поток выполнения общей задачи . Его главная цель - выгрузить потенциально блокирующую обработку ( которая может остано­ вить функцион ирование процесса) из другого процесса и реализовать ее в фоновом режиме. Например, если главному процессу ASM необходимо выпол нить некоторую операцию, блокирующую файл , но данная операция может быть безопасно произ­ ведена в фоновом режиме (AS M может благополучно продолжать обработку перед завершением операции), то процесс ASM может запросить у процесса GEN O выпол­ нение этой операции и уведомление о ее завершении . Это похоже по своей природе на подчиненные процессы, которые описаны далее в главе. Остальные специализированные процессы В зависимости от применяемых средств Oracle в системе могут наблюдаться и другие специализированные процессы . Некоторые из них снабжаются кратким опи ­ санием их функций. 290 Глава 5 На заметку! П р иложение F ( " B ackground Processes" - "Фоновые п роцессы " ) руководства Oracle Database Refereпce, доступное по адресу ht tp : 1 1 otn . o r a c l e . сот/ , содержит полный список фоновых п роцессов и их функци й . Больш и нство описанных ранее процессов неизменны - о н и есть в любом вы­ пол няющемся экзем пляре Огасlе . ( Процесс ARC n формально не считается обяза­ тельным, но, по моему мнению, должен быть неотъемлемой частью любой произ­ водствен ной базы данных!) Описанные далее процессы не являются обязательн ыми, и они будут действовать в системе только при использовани и конкретных функци­ ональных средств. Следующие процессы характерны только дЛЯ экземпляра базы дан ных, в котором включена функция AS M (Automatic Storage Management - авто­ матическое управление пространством хранения ) , описанная в главе 3 . • q)оновый процесс автоматического управления пространством хранения (Automatic Storage Management Background - АSМВ). Процесс ASMB выполня­ ется в экзем пляре базы данн ых, применя ющем средство AS M . Он отвечает за обмен данными с экземпляром AS M , который управляет пространством хране­ ния, снабжение экземпляра AS M обновленными статистическими сведениями и предоставление такта (heartbeat) экземпляру ASM , чтобы знать, действует ли он по-прежнему. • Процесс ребалансировки (ReBALance - RВAL). Процесс RBAL также действует в экземпляре базы дан ных, испол ьзующем функци и AS M . Этот процесс от­ вечает за обработку запроса ребалансировки (запроса перераспределения) при добавлении/удалени и дисков из групп ы дисков ASM . П еречисленные н иже процессы можно найти в экземпляре Огас!е RAC. Как уже упоми налось, RAC - это конфигурация Огасlе, где нескол ько экземпляров, каж­ дый из которых действует в отдельном узле (как правило, на отдельном физическом компьютере) кластера, могут монтировать и открывать одну базу данн ых . Это поз­ воляет более чем одному экземпляру получать полный доступ по чтению и записи к одиночному набору файлов базы данных. Основных целей RAC две . • Высокая доступность. В случае применения Oracle RAC отказ одноm узла/ком­ пьютера в кластере из-за проrраммной , аппаратной или человеческой ошибки позволит остальн ы м узлам продолжить функционирование. База данных оста­ нется доступной через другие узл ы . При этом вычислительная мощность сис­ темы может несколько снизиться , но доступ к базе данных не будет утеря н. • Масштабируемость. Вместо того чтобы приобретать все более мощн ые ком­ п ьютеры дЛЯ обработки постоя н но возрастающей нагрузки (такой подход называют вертикальным масштабированием ) , технология RAC позволяет до­ бавлять ресурсы в форме большего ч исла комп ьютеров в кластере (этот под­ ход носит название горизонтального масштабирования) . Вместо замены 4-про­ цессорного комп ьютера 8- или 1 6-процессорным технология RAC позволяет просто добавить еще оди н сравнительно недорогой 4-процессорный компью­ тер (или несколько) . Следующие процессы уникальны дЛЯ среды RAC . В других местах вы их не увидите . П роцессы O racle 29 1 • Процесс монитора блокировки (lock monitor - LМON). П роцесс LMON отслежи­ вает все экземпляры в кластере на предмет выявлен ия отказа экзе м пляра. В случае его обнаружен ия LMON восстанавл ивает глобальные блокировки , уста­ новленные отказавшим экземпляром . Этот процесс отвечает также за рекон­ фигурирование блокировок и других ресурсов в случае удаления экзем пляров либо их добавления в кластер (при их отказе и повторном подключении или при добавлении в кластер новых экземпляров в реальном времен и ) . • Процесс демона диспетчера блокировки (lock manager daemon - I.М:>). П роцесс LMD обрабатывает запросы службы диспетчера блокировки , связанные с гло­ бальным кешем (поддерживающие согласованность буферов блоков между эк­ земплярам и ) . Главным образом этот процесс и грает роль посредника, отправ­ ляя запросы на предоставление ресурсов в очередь, которая обрабатывается процессам и LMS n . П роцесс LMD обеспечивает выявление/распознаван ие гло­ бальных взаимоблокировок и мониторинг тай м-аутов , связанных с блокиров­ кам и , в глобал ьной среде . Кроме того, начин ая с Oracle 1 2с , для содей ствия рабочему потоку могут существовать подчиненные процессы LDDn, порождае­ мые процессом LMD O . • • Процесс сервера диспетчера блокировки (lock manager server - IМSn). Как от­ мечалось ранее, в среде RAC каждый экземпляр Oracle действует на отдельном ком п ьютере в кластере , и все они имеют доступ по чте н и ю и записи в точ ­ ности к тому же самому набору файлов базы дан н ых . Для достижен ия этой цели кеши буферов блоков SGA должн ы быть согласованными друг с другом. Обеспечение такой согласован ности - одна из основных задач процесса LMSn. В ранних выпусках паралл ельного сервера Oracle (Oracle Parallel Server - OPS) это было реализовано посредством выгрузки из кеша (ping) . То есть, если узел в кластере нуждался в согласованном по чтению представлени и блока, кото­ рый бьm заблокирован в монопольном режиме другим узлом, то обмен данны­ ми осуществлялся посредством сброса на диск (блок бьm выгружен из кеша). Такая операция была очень затратной даже для чте н ия дан н ых. Теперь, бла­ годаря процессу LMSn, этот обмен производится через очен ь быстр ы й обмен данн ы м и между кешами по высокоскоростному подкл ючен и ю кластеров. Экземпляр может иметь до десяти процессов LMSn. Процесс блокировки (LCKO). П о своему действию этот процесс подобен опи­ санному ранее процессу LMD, но он обрабатывает запросы на предоставление всех других глобальных ресурсов , отличных от буферов блоков базы данн ых. Н иже перечислены общие фоновые п роцесс ы , которые присутствуют в боль­ шинстве одиночных экземпляров или экземпляров RAC. • Процесс генератора процессов ( Process Spawner - PSPO). П роцесс P S P O от­ вечает за порождение (запуск/создание) разнообразных фоновых п роцессов. Это процесс, которы й создает новые процессыjпотоки для экземпляра Oracle. Большую часть своей работы он выполняет во время запуска экземпляра. • Процесс виртуального хранителя времени (Virtual Keeper of Time VКТМ). Процесс vктм реализует согласованные и детализированные часы для экземп­ ляра Oracle. Он отвечает за предоставление времени в формате обычных часов - 292 Глава 5 (читабельном дЛЯ человека), а также высокоточного таймера (который не обя­ зательно использует формат обычных часов, а скорее я вляется секундомером , отслеживающим очен ь малые еди ницы времен и ) , применяемого для измере­ ния продолжительностей и и нтервалов. • Процесс виртуального планировщика для диспетчера ресурсов (Virtual Sch(K) eduler for Resource Manager VКRМ). Планировщик для диспетчера ресурсов, которы й управляет графи ком загрузки процессара и управляемыми процесса­ ми с активными планами ресурсов. - • П роцесс координатора управления пространством ( S pace Management Coordinator - SМСО). Процесс SMCO я вляется частью и нфраструктуры управ­ ления. Он координ ирует работу средств упреждающего управлен ия пространс­ твом базы данн ых, таких как процессы, обнаруживающие пространство, кото­ рое может быть освобождено, и процессы, выполня ющие это освобождение. Сл ужебные ф оновые про ц ессы Эти фоновые процессы я вляются совершенно необязательными и создаются искл ючительно по необходимости . Они предоставляют функциональные средства, которые не требуются при повседневной работе базы дан ных, если только вы сами не используете их, например, очереди заданий , ил и не применяете использующее их средство, такое как диагностические возможности (в Oracle l Og и последующих версиях) . Такие процессы будут видны в среде U N IX/Linux как л юбые другие фоновые процессы - в выводе команды p s . В примере вывода команды p s , приведеином в начале раздела "Специализированные фоновые процессы", легко заметить наличие следующих элементов. • Сконфи гурированные очереди задани й . Процесс S JQO - это координатор оче­ редей задани й . • Сконфигурированное средство Advanced Queuing (AQ) , о ч е м свидетельствуют процессы Qnnn ( процесс очереди AQ) и QMNC (процесс монитора AQ). • Включен ное автоматическое управление памятью, что подтверждается процес­ сом диспетчера памяти ( Memory Manager - ММАN) . • Включенные средства управления/диагности ки Oracle, о чем свидетельствуют процессы монитора управляемости ( Manageabllity M onitor - ММОN) и облегчен­ ного монитора управляемости ( Manageabllity Monitor Light - ММNL). Давайте рассмотрим процессы, которые могут присутствовать в зависимости от применяемых функционал ьн ых средств. Процессы CJO O и Jnnn: очереди заданий В первом выпуске Oracle 7.0 была предложен а возможность репл икации в форме объекта базы дан н ых, называемого моментальной копией (snapshot). Очереди зада­ н и й был и внутрен н и м механизмом , с помощью которого эти моментальные копии обновлялись, или делались текущими. П роцесс очереди отслеживал табли цу задани й , содержащую информацию о том , когда необходимо обновлять различные моментальные копи и в системе. П роцессы Oracle 293 В верси и Orac1e 7 . 1 эта возможность стала доступ ной для всех через пакет базы дан н ых по имени D B M S JO B . Таки м образом, процесс, которы й в версии 7.0 был связан исключительно с обработкой моментальных копи й , в верси и 7 . 1 и последующих версиях стал " очередью задани й " . С течением времен и имена па­ раметров, управляющих поведением очереди задани й , изме н ились с S N A P S H O T RE FRESH_ INTERVAL и SNAPSHOT _RE FRE S H_ PROC E S S E S на JOB_QUEUE_ INTERVAL И JOB_QUEUE_ PROCES S E S . В текущем выпуске для настройки пользователем доступен только параметр JOB_QUEUE_ PROCE S S E S . В системе можно и меть до 1 000 процессов очередей задани й с именами J O O O . . . J 9 9 9 . Эти процессы интенсивно используются п р и репликаци и в качестве состав­ ной части процесса обновления материал и зованного представления. П отоконая репликация (доступная в Orac1e9i Re1ease 2 и последующих версиях) применяет д11я репликаци и средство AQ и , следовательно, не использует процессы очередей зада­ ний. Разработчики также часто применяют очереди задан и й для планирования ра­ зовых (фоновых) заданий л ибо повторяющихся заданий вроде фоновой отправки электронной почты или обработки длительно выполняющегося пакетного процес­ са, запускаемого в фоновом режиме. Проделывая часть работы в фоновом режиме, можно создавать видимость значительно более быстрого выполнения д11 ител ьных задач (нетерпел ивому пользователю будет казаться , что задание выполняется быс­ трее, хотя оно может быть еще не завершено) . Это подобно тому, что Orac1e делает с помощью процессов LGWR и DBWn; большую часть своей работы они производят в фоновом режиме, поэтому нам не придется дожидаться , пока упомянутые процессы завершат все задачи в реальном времени. Процессы Jnnn (где nnn - некоторое число) очен ь похожи на разделяемый сер­ вер, но с рядом аспектов выделенного сервера. Они я вляются разделяемыми в том смысле, что обрабаты вают одно задание за другим , но управляют памятью в мане­ ре , больше подобной способу, которы й используется выделенным сервером (их па­ мять UGA размещена в области PGA, а не SGA) . Каждый процесс очереди зада­ ний времени будет вы пол нять только одно задание за раз, одно за други м , вплоть до завершения . И менно поэтому для одновременного выполнения заданий может требоваться множество процессов. Не существует н и какого метода организации многопоточного или приоритетного выполнения заданий. После того как задание запущено, оно будет вы полняться до полного завершения (ил и отказа) . Вы заметите , что с течен ием времени процессы Jnnn появля ются и исчезают, т.е. если система сконфигурирована с поддержкой 1 000 таких процессов, то не все 1 000 процессов будут запускаться вместе с базой данных. Вместо этого будет запущен единственный процесс координатора очереди заданий (CJQ O ) , который будет запус­ кать необходимые процессы Jnnn по мере поя вления задани й , подлежащих выпол­ нению, в таблице очереди задани й . Выполнив свою работу и обнаружив, что новая работа отсутствует, процессы Jnnn начнут завершаться и исчезать. Таким образом, если вы запланируете большинство своих заданий на запуск в 2:00, когда в помеще­ нии никого нет, то эти процессы Jnnn можно вообще не заметить. QМNC и Qnnn: расширенные очереди П роцесс QMNC играет для табли ц AQ ту же роль, которую процесс C J O O и грает д11я таблицы заданий. Он отслеживает расширенные очереди и оповещает процессы извлечения из очереди, ожидающие сообщения, о том , что сообщен ие стало доступ- 294 Глава 5 н ы м . П роцессы QMNC и Qnnn отвечают также за распространение в очереди - т.е. возможность перемеще н ия сообщен ия , которое бьшо добавлено в очередь в одной базе дан н ых, в очередь в другой базе данн ых для его последующего извлечения . П роцессы Qnnn и грают для процесса QMNC ту же роль, которую процессы Jnnn и грают для процесса C JQ O . П роцесс QMNC уведомляет их о работе , которая должна быть выпол нена, и они занимаются этой работой. П роцессы QMNC и Qnnn представляют собой необязательные фоновые процессы. П араметр AQ_тм_PROC E S S E S указы вает создание до 40 таких процессов с именами Qnnn ( где nn - ч исло 0 .. 1 5 или буква a .. z) и одиночного процесса QMNC. В отличие от процессов Jnnn, приме няемых очередями заданий, процессы Qnnn явля ются постоянными. Если вы установите п араметр AQ_TM_PROCE S S E S в 1 0 , то увидите десять процессов QOnn и процесс QMNC при запуске базы данных, а также на протяжен и и всего времени жизни экземпляра. СУБД Oracle автоматически корректирует количество процессов очередей и по этой причине вам редко придется устанавливать AQ_т м_ PROC E S S E S вручную. Если же все же установите этот параметр, то Oracle по-прежнему будет корректировать кол ичество порождаемых процессов и использовать значение AQ_тм PROC E S S E S в качестве минимального ч исла процессов, подлежащих созданию. _ На заметку! Начи ная с версии Oracle 1 2с, имеется процесс координатора процессов рас­ ш иренных очередей (Advanced Queue Process Coord inator AQ PC). Он п редназначен для создания и управлен и я гла в н ы м и процессами расш иренной очереди (запуск , останов и т.д. ) . Статистическую и нформаци ю , связанную с этим п роцессом , можно запросить из представления GV $AQ_BACKGROUND_ COORD I NATOR. - EМNn: процессы монитора событий П роцесс EMNn - это часть архитектуры AQ . Он служит для уведомления под­ писчиков очереди о сообщениях, в которых они могут быть заинтересованы. Такое уведомл е н ие производится аси нхрон но. Существуют фун кци и OCI (Oracle Call Interface - интерфейс уровня вызовов Oracle) , позволяющие зарегистрировать об­ ратны й вызов для уведомлен ия о сообщении. Обратны й вызов - это функция про­ граммы OC I , которая будет автоматически вызываться всяки й раз, когда и нтере­ сующее сообщение доступно в очереди. Фоновый процесс EMNn предназначен для уведомл е н ия подпи сч и ка. П роцесс EMNC запускается автоматически при выдаче первого уведомления для экземпляра. Затем приложение может выдать явную ко­ манду me s s a ge _ r e c e i ve ( dequeue ) , чтобы извлечь сообщение. ММАN: диспетчер памяти Этот процесс доступен в Oracle l Og и последующих версиях и применяется средс­ твом автоматической установки размера области SGA. Процесс ММАN координирует установку и изменение размеров компонентов разделяемой памяти (стандартного буферного пула, разделяемого пула, пула Java и большого пула) . ММОN, ММNL и Мnnn: мониторы управляемости Эти п роцессы испол ьзуются для заполнения автоматического хранил ища ин­ формации о рабочей нагрузке (Automatic Workload Repository - AWR) фун кци- П ро цессы Oracle 295 анального средства, которое доступно н ачиная с версии Oracle 1 0g. П роцесс MMN L сбрасывает статистические сведения из области SGA в таблицы базы данн ых на ос­ нове расписания . Процесс MMON служит для автоматического обнаружен ия проблем с производительностью базы данных и реализации новых функци й самонастройки . Процессы Mnnn аналогичны процессам Jnnn или Qnnn применительно к очередям заданий; процесс MMON будет запрашивать у этих подчиненных процессов выполне­ ния работы от его име н и . П о своей природе процессы Mnnn я вляются временны­ ми - они будут появляться и исчезать по мере надобности. CТWR: процесс отслеживания изменений Это необязательный процесс в Oracle 1 Og и последующих версиях. Он отвечает за поддержку файла отслеживания изменени й , как бьuю описано в главе 3 . R VW.R: процесс записи данных восстановления Этот процесс (доступ н ы й в Oracle 1 Og и последующих версиях) обеспечи ва­ ет сопровожде ние предшествующих образов блоков в области быстрого восстанов­ ле ния ( Fast Recovery Area) , оп исанной в главе 3, которая используется командой FLAS HBACK DATABAS E. DМnn/DWrш.: главныеjрабочие процессы Data Pump Data Pump - это средство, добавленное в верси и Oracle ! Og Release 1 . Оно было спроектировано как полная замена унаследованных процессов экспорта/импорта. Data Pump выполняется целиком на сервере и АРI - интерфейсом для взаимодейс­ твия с ним служит PL/SQL. П оскольку Data Pump выпол няется на сервере , была добавлена поддержка выполнения разнообразных операций Data Pump. Главный процесс Data Pump ( DMnn ) собирает весь ввод от клиентских процессов (получаю­ щих ввод через АРI-интерфейс) и затем координ ирует рабочие процессы ( DWnn ) , ко­ торые делают фактическую работу - процессы DMnn осуществляют действительную обработку метаданных и данных. ТМОN/ тто о: процесс монитора первмещения и подчиненный процесс первмещения данных отмены Начиная с версии Oracle 1 2с, во время старта экземпляра автоматически запуска­ ются два процесса, связс;iнные с Data Guard: процесс монитора перемещения (trans­ port monitor process - TMON ) и подчиненный процесс перемещения данных отмены (redo transport slave - Т Т О О ) . П роцесс TMON запускается и следит за нескольким и процессами т т о о . П роцессы т т о о применяются дл я информирования процесса LGWR о необходимости генерации такта данных отмены (heartbeat redo) . Вы можете видеть эти процессы запущенными, даже если вообще не внедряли Data Guard. Н е пережи вайте по их поводу, просто помните о том , что они существуют и будут ис­ пользоваться , если вы развернете средство Data Guard. Если же средство Data Guard внедрено, будет запущено несколько дополнитель­ ных процессов, предназначенных для упрощения доставки информаци и отмены из одной базы дан ных в другую и для ее применения . За подробными сведениями об­ ращайтесь в руководство Data Guard Concepts and Administration ( Концепции и адми ­ нистрирование Data Guard), предлагаемое Oracle. 296 Глава 5 Остальные служебные фоновые процессы Итак, я вляется ли приведенный список исчерпывающим? Нет, никоим образом. Существует много других процессов подобного рода, зависящих о того, какие фун­ кциональные средства реализованы . Н апример, есть также процессы применения и перехвата потоков Streams, которые присутствуют в случае внедрен ия таких про­ дуктов, как Oracle GoldenGate , Oracle XStream, Oracle Streams и т.д. Тем не менее, приведенный перечень охватывает большинство наиболее часто встречающихся фо­ новых процессов. Подчи ненные процессы Теперь можно приступить к рассмотрению последнего класса процессов Oracle подчиненных процессов. Различают два типа подчиненных процессов Oracle: подчи­ ненные процессы ввода-вывода и подчиненные процессы параллельных запросов. - П одчиненные п р оцессы ввода - вывода П одчиненные процессы ввода-вывода используются для эмуляции асинхронного ввода-вы вода в системах или устройствах, которые его не поддерживают. Например, лентопротяжные устройства (общеизвестно медлен н ые) не поддержи вают аси нх­ рон н ы й ввод- вы вод. За счет применения подчиненных процессов ввода-вывода для лентопротяжн ых устройств можно имитировать то, что операционная система обычно предлагает для дисководов. Как и при настоя щем аси нхронном вводе-вы­ воде , процесс, производящий запись на устройстве, помещает большой объем дан­ н ых в пакет и передает его для записи . П осле успеш ного завершения записи дан­ н ых записывающий процесс (в этом случае подчиненный процесс ввода-вывода, а не операцион н ая система) выдает сигнал процессу, и н и циировавшему запись, ко­ торы й удаляет этот пакет из своего списка данн ых, предназначенных для записи . Такой подход позволяет значительно увеличить пропускную способность, поскольку подчиненные процессы ввода-вы вода ожидают завершения работы медленного ус­ тройства, а в это время вызывающий их процесс выполняет другую важную работу по сбору дан ных для следующей зап иси . П одчиненные процессы ввода-вывода испол ьзуются в паре мест базы данных Oracle. П роцессы DBWn и LGWR могут их применять для эмуляции асинхронного вво­ да-вывода, а процесс RМAN будет их использовать при записи на магнитную ленту. Для управления применением подчиненных процессов ввода-вывода служат два параметра. • BACKUP_ТАРЕ I O_ S LAVE S . Этот параметр указывает, будет ли процесс RМAN использовать подчиненные процессы ввода-вывода для резервирования, копи­ рования или восстановления данн ых с магнитной ленты . Поскольку параметр BACKUP_ТАРЕ_ IO_S LAVES предназначен для работы с ленточными устройства­ ми, а такие устройства могут быть доступны только одному процессу в каждый момент време н и , его значение является булевски м , а не числовым , равным количеству применяемых подчиненных процессов, как можно было бы пред­ положить. Процесс RMAN запустит столько подчиненных процессов, сколько требуется для кон кретного количества используемых физических устройств. Когда п араметр BAC K U P ТАРЕ IO S LAVE S установлен в T RU E , для записи П р о цессы Oracle 297 или чтения с ленточного устройства используется подчиненный процесс вво­ да-вывода. Если же он установлен в FALS E (по умолчани ю ) , то подчиненные процессы ввода-вывода при резервном коп ировании не применяются . Вместо этого к ленточному накопителю будет обращаться процесс вьщеленного серве­ ра, задействованный в резервном коп ировани и . • DBWR_ IO_SLAVES . Этот параметр указывает количество подчиненных процессов ввода-вывода, используемых процессом DBWO . Процесс DBWO и его подчиненные процессы всегда выполняют зап ись на диск грязных блоков буферного кеша. По умолчанию значением DBWR_ IO_ S LAVE S является О и подчиненные процессы ввода-вывода не применяются . Обратите внимание, что если вы установите этот параметр в неиулевое значение, то процессы LGWR и ARCn будут использовать также собственные подчиненные процессы ввода-вывода - для LGWR и ARC n разрешено иметь до четырех подчиненных процессов ввода-вывода. Подчиненные процессы ввода-вывода процесса DBWn отображаются с именем I l nn, а подч иненные процессы ввода-вывода процесса LGWR - с именем I 2 nn. Pnnn : серверы выполнения параллельного запроса В верс и и O racle 7 . 1 . 6 была введе н а возмож ность п аралл е л ь н о го зап роса базы дан н ых. Она п озволяет создавать для S Q L-oпepaтopa, такого как S E L E C T , CREAT E TABLE, CREATE I N DEX, U P DATE И т.д. , план выполнения, СОСТОЯЩИ Й И З мно­ жества планов выполнен ия , которые могут быть сделаны одновременно. Результаты выполнения всех этих планов объединяются в оди н результат большего размера. Цель заключается в сокращен и и времени выполнения операции по сравнению с ее последовательным выполнением. Н апример, предположи м , что существует действи­ тельно большая таблица, распределенн ая по десяти разным файлам . В нашем рас­ поряжении имеется 1 6 процессорав и требуется выпол н ить произвольный запрос к этой таблице . Полезно разбить план выполнен ия на 32 небольших фрагмента и действительно в полной мере задействовать вычислительные возможности комп ью­ тера, вместо того чтобы применять только оди н процесс для последовательного чте­ ния и обработки всех дан ных. Когда испол ьзуется параллел ьн ы й запрос, в ы увидите процессы с и менами Pnnn - это собственно серверы выполнения параллельного запроса. Во время обра­ ботки параллельного оператора ваш серверный процесс будет известен как коорди­ натор параллельного запроса. На уровне операционной системы его название не ме­ няется , но если вы встретите в документации по паралл ельным запросам ссылки на процесс координатора, то знайте, что это просто ваш исходный серверный процесс. До выхода Orac1e 1 2с стандартное количество запускаемых серверов п араллел ь­ нога выполнения было нулевым. Это поведение можно было изменить, указы вая неиулевое значение для параметра PARALLEL_M I N_S E RVERS. Н ач иная с Orac1e 1 2с, ваш экземпляр будет автоматически создавать н есколько серверов параллельного выполнения . Причина в том, что параметр PARALLEL_MIN_SERVERS установлен в иенулевое зна­ чение (выведенное из выражен ия CPU _COUNT * PARALLEL_THREADS _PER_C P U * 2 ) . Например, н а моем двухпроцессорном компьютере ( параметр C P U_COUNT равен 2 и параметр PARALL E L_THREADS_P E R_C PU также равен 2) можно наблюдать следую­ щие восемь функционирующих серверов параллельного выполнения: 298 Глава 5 $ ps - e f 1 g rep o ra_p O O oracle oracle oracle o racle o racle o racle oracle orac1e 31086 31088 31104 31106 31108 31110 31112 31114 1 1 1 1 1 1 1 1 1 g rep -v g rep О Ap r0 6 ? О Apr 0 6 ? О Apr0 6 ? О Apr 0 6 ? О Apr 0 6 ? О Ap r 0 6 ? О Ap r 0 6 ? О Apr 0 6 ? 0 0 : 0 0 : 0 3 o ra_p O O O_ORA1 2CR1 0 0 : 0 0 : 0 5 o ra_p 0 0 1_0RA12CR1 0 0 : 0 0 : 0 2 ora_p 0 0 2_0RA1 2CR1 0 0 : 0 0 : 0 2 ora_p 0 0 3_0RA1 2CR1 0 0 : 0 0 : 0 2 ora_p 0 0 4_0RA1 2CR1 0 0 : 0 0 : 0 2 o ra_p 0 0 5_0RA12CR1 0 0 : 0 0 : 0 2 ora_p 0 0 6_0RA1 2CR1 0 0 : 0 0 : 0 2 o ra_p 0 0 7_0RA1 2CR1 Совет. Параллельная обработка подробно рассматривается в главе 1 4. Р ез ю ме В этой главе были раскрыты файлы, применяемые Oracle, начиная с простого, но важного файла параметров и заканчивая файлами данн ых, файлами журналов пов­ торен ия и т.д. Мы взглянул и на структуры памяти , используемые Oracle как в сер­ верн ых процессах, так и в области SGA. Мы показали , что разные серверные конфи­ гураци и , такие как подкл ючения в режимах выделенного и разделяемого серверов, оказывают сильное влияние на то, как память применяется системой . Наконец, мы рассмотрели процессы ( ил и потоки - в зависимости от операционной системы), которые позволяют СУБД Oracle делать то, что она делает. Теперь можно приступать к исследовани ю реал изации ряда других функциональных средств Oracle , таких как блокировка, управление параллельным доступом и транзакции. ГЛ А В А 6 Бл о кир ов ка и за щ е лкив ан ие д аННЬIХ о дна из основных проблем при разработке многопользовательских приложений, управляемых базами данн ых, связана с доведением до максимума степени па­ раллельного доступа с одновременным обеспечением для каждого пользователя воз­ можностей читать и модифи цировать данные в согласованной манере. Механизмы блокировки , которые позволяют добиться этого, являются ключевыми средствам и любой базы данн ых, и СУБД Oracle лучшая в плане их предоставления . Тем не ме­ нее, реализация Oracle этих функциональных средств специфична для Oracle - по­ добно тому, как реализация SQL Server характерна именно для SQL Server - и задача обеспечения того, что приложение правильно испол ьзует эти механизмы при мани­ пулировании дан ными, цели ком возлагается на разработчи ка. Есл и вы проигнори­ руете это, то приложение будет вести себя непредсказуемым образом , что неизбежно приведет к нарушению целостности данных (как демонстрировалось в главе 1 ) . В этой главе м ы подробно рассмотрим, как Oracle блокирует данные (например, строки в таблицах) и разделяемые структуры данных (такие как компоненты SGA) . Мы исследуем уровень детализации , до которого Oracle блокирует данные, и что это означает для разработчика. Когда это уместно, я буду сравни вать схему блокиров­ ки Oracle с другими популярными реализациям и , главным образом , чтобы развеять миф о том, что блокировка на уровне строк увеличивает накладные расходы ; в дейс­ твительности накладные расходы добавляются , только если это делает реал изация. В следующей главе мы продолжи м обсуждение этой тем ы и исследуем технологии многоверсионности , а также взаимодействие с ними стратегий блокировки. По нятие блокировки Блокировка (lock) - это механизм, применяемый для регулирования паралл ель­ нога доступа к разделяемому ресурсу. Обратите внимание на испол ьзование термина "разделяемый ресурс" , а не "строка базы данных". Действительно, Oracle блокирует данные таблиц на уровне строк, но также применяет блокировки на многих других уровнях для предоставления параллельного доступа к разнообразным ресурсам. 300 Гл ава 6 Например, пока хранимая процедура выполняется , она сама блокируется в режиме, который позволяет другим запускать ее, но не разрешает другому пользователю каким­ либо образом изменять экземпляр этой хранимой процедуры. Блокировки использу­ ются в базе данных для обеспечения параллельного доступа к таким разделяемым ре­ сурсам, в то же самое время поддерживая целостность и согласованность данных. В базе дан н ых с еди нственным пользователем применение блокировок не обяза­ тельно. По определению есть только оди н пользователь, изменяющий информацию. Н о когда несколько пользователей получают доступ и модифицируют данные или структуры данных, критически важно располагать механизмом , предотвращающим одновременное изменение одного и того же фрагмента и нформации . И менно этой цели и служит блокировка. Очень важно понимать, что способов реализации блокировок доступно столько же, сколько существует баз данных. Наличие опыта работы с моделью блокировки в одной системе управления реляционными базами данных (СУРБД) вовсе не озна­ чает, что вы знаете о блокировке абсолютно все. Н апример, прежде чем вплотную заняться Oracle, я использовал другие СУРБД, в том числе Sybase , Microsoft SQL Server и Informix. Все упомянутые СУР БД предоставляют механизмы блокировки для управлен ия параллельной обработкой, но реал изация блокировки в каждой из них характеризуется глубокими и фундаментальными отличиям и . Чтобы проиллюстрировать сказанное, я кратко опишу свое продвижение от раз­ работчи ка SQL Server до пользователя I nformix и , наконец, до разработчика Oracle. Это происходило много лет назад, и стой кие приверженцы SQL Server скажут: " Н о теперь м ы располагаем блокировкой на уровне строк" . Это действительно так: в на­ стоящее время SQL Server допускает применение блокировки на уровне строк, но способ ее реализации совершенно отличается от способа, как это сделано в Oracle. Сравнивать их - все равно, что сравн ивать яблоки с апельсинам и , и это является ключевым моментом . Мне, как программисту SQL Server, вряд ли пришло бы в голову учитывать воз­ можность одновременной вставки данн ых табл ицу сразу несколькими пользовате­ лям и . Такая с итуация редко происходила в этой базе данных. В те времена база дан ­ ных SQL Server предоставляла только блокировку на уровне страниц, и поскольку все данные, как правило, должны были вставляться в последнюю страницу неклас­ теризованных таблиц, параллельная вставка дан н ых двумя пользователями просто не должна была происходить. Н а заметку! Кластеризованная табли ца SQL Server (табли ца, которая имеет кластеризован­ ный и ндекс) в оп ределенном отношении похожа, но существенно отличается от класте­ ра Oracle. В SQL Server обычно поддерживалась тол ько блоки ровка на уровне страниц ( блоков ) , и есл и бы каждая вставляемая строка помещалась в " конец" таблицы , то в этой базе данных никогда не возни кали бы ситуации параллельных вставок или параллельных транзакци й . В SQL Server кластеризованный индекс применялея для вставки строк во всех местах табл ицы , в порядке сорти ровки , определенном ключом кластера, что в результате улуч шало степень параллелизма в базе данных. Те же самые проблемы возни кали при параллельных обновлен иях (из-за того, что в действител ьности операция U P DATE представляла собой последовательно вы­ пол няемые операции DELETE и I N S E RT ) . Вероятно, именно по этой причине SQL Б л окировка и за щ елкивани е дан н ых 301 Server п о умолчан ию производит фиксацию или откат немедленно после выполне­ ния каждого отдельного оператора, жертвуя целостностью транзакци й в попытке достижен ия более высокой степени параллельной обработки . Таким образом , в больши нстве случаев из-за блокировки на уровне страниц не­ сколько пользователей не могли одновременно модифицировать одну и ту же таб­ лицу. Ситуация усугублялась тем фактом , что во время изменения таблицы м ногие запросы к ней также блокировалась. Попытка запросить таблицу и получить доступ к странице, заблокирован ной операцией обновлен и я , приводила к длительному ожиданию. Механ изм блокировки был настолько несовершен н ы м , что предостав­ ление поддержки для транзакций, вы полняющихся дольше одной секунды , было чрезвычайно опасным - вся база дан н ых оказывалась замороженной. В результате я обзавелся массой скверных привычек. Я усвоил , что транзакции - это " плохо " , и и х следует фиксировать как можно скорее , н икогда не удерживая блокировки на дан ных. За параллельную обработку приходилось платить снижением целостности данных. Можно было обеспечить либо их корректность, либо скорость получения. Я пришел к заключению, что добиться того и другого было нельзя . Когда я перешел на l nformix, ситуация улучш илась, но не намного. Если я не забывал создавать таблицу с включен ной блокировкой на уровне строк, то два поль­ зователя действительно п олучали возможность одновременной вставки дан н ых в эту табли цу. К сожалени ю , за такой параллелизм приходилось платить высокую цену. Реализация блокировок на уровне строк в lnformix требовала больших затрат как времени, так и памяти . Их установка и снятие (освобожде н ие) занимало зна­ чительное время, и каждая блокировка потребляла реальную память. Кроме того , общее количество доступн ых в системе блокировок должно б ыло вычисляться до запуска базы данных. Есл и вы превышали это кол ичество, значит, вам не повезло. Вследствие этого большинство таблиц в любом случае создавались с блокировкой на уровне страниц и подобно SQL Server блокировки на уровне строк и страниц стопо­ рили прохождение запросов. В результате я в очередной раз обнаружил, что хочу выпол нять фиксацию как можно быстрее. Плохие привычки , которые я приобрел при использовании SQL Server, просто укреп ились, к тому же я научился считать блокировку очень дефи цитны м ресурсом - чем-то особо желанным. Я усвоил, что во избежание установки сли ш ком большого числа блокировок и затормаживания системы - что случалось многократно - необходимо вручную повышать блокиров­ ки с уровня строк до уровня таблиц. Когда я начал работать с Oracle, то не слишком утруждал себя чтением руководс­ тва для выяснения особенностей работы блокировки в этой конкретной базе дан ­ ных. В конце кон цов, я уже довольно долго работал с базам и данных и считался экспертом в этой области ( в дополнение к Sybase, SQL Server и l nformix я применял l ngress, DB2, Gupta SQLBase и ряд других СУБД) . Я попал в ловушку, будучи уве­ ренным, что коль скоро мне известно, как должны работать различные функции , то, конечно же, именно так они и будут работать. Я крупно ошибался . Степень своего заблужден ия я выяснил во время выполнения сравнител ьн ых тестов. На заре развития СУБД (в 1 992/ 1 993 году) перед действительно круп н ы м и Приобретениями обычно проводилось сравнительное тестирование программною обеспечения, предлагаемого разными поставщикам и , чтобы выяснить, какое из них способно решать задачи быстрее и проще, предлагая при этом более широкую фун­ кциональность. 302 Глава 6 М ы сравнивали работу Informix, Sybase , SQL Server и Oracle. Первой испытыва­ лась СУБД Oracle. Специалисты из Oracle прибьши в наш офис, прочли специфика­ ции тестов и начал и подготовку. П ервым делом я заметил, что специалисты из Oracle собирались испол ьзовать табли цу базы данн ых для фиксации показателей времени, хотя м ы были намерены применять при работе десятки подключен и й , каждому из которы х предстояло часто выпол нять вставку и обновление дан н ых в этой жур­ нальной таблице. Более того, во время тестирования они собирались также читать журнальную табли цу! Будучи тактичн ы м , я отозвал одного специалиста из Oracle в сторону, чтобы поинтересоваться , не сошли ли они с ума - зачем им лонадобилось сознательно вводить в систему еще одну точку конкуренции? Разве тестовые про­ цессы не будут стремиться выпол нять свои операции с этой еди нственной таблицей последовательно? Разве результаты сравнительного тестирования не окажутся иска­ женн ым и из-за попыток чтен ия из этой таблицы, в то время как другие процессы будут и нтенсивно ее изменять? Зачем нужно привносить все эти дополнительные бло ки ровки , которы м и п ридется управлять? У меня возникл и десятки вопросов вроде: " Почему вы вообще подумали об этом?" Специалисты из Oracle реш или, что я немного не в себе. Они оставались в таком убежден и и до момента, когда я открыл окно в SQL Server или I nformix и продемонстрировал последствия вставки данных в табли цу двумя пользователями или попытки запроса таблицы в то время , когда кто­ то другой вставлял в нее строки (запрос вообще не возвращал строк) . Отличия меж­ ду технологиям и , которые испол ьзуются в Oracle и практически во всех остальных базах данн ых , были разительными - они отличались буквально как ден ь и ночь. Не стоит и говорить, что ни специалисты Informix, н и специалисты SQL Server не особо стремились применять подход с журнальной таблицей базы данных при про­ ведении своих тестов. Они предпочли записывать полученные показатели времени в плоские файлы , поддержи ваемые операционной системой . Специалисты Oracle по­ кинул и наш офис, вооруженные знанием того, как преуспеть в конкуренции с SyЬase, SQL Server и I nformix. Нужно просто поинтересоваться : "Сколько строк в секунду возвращает используемая вами база данн ых, когда данные заблокированы?" - и этого будет достаточно. Мораль этой истори и двояка. Во-первых, все базы данных являют­ ся фундаментально разными. Во-вторых, при проектировании приложения для новой платформы базы дан н ых не должны делаться какие-либо предположения о том , как эта база дан н ых работает. К каждой новой СУБД нужно относиться так, словно ранее вы вообще не имели дело с базами данных. Действия, выполняемые в одной базе данных, окажутся либо необязательными, либо неприемлемыми в другой базе данных. П рименяя Oracle, вы усвоите следующие моменты . • Транзакции - это то, для чего предназначен ы базы данных. Они явля ются по­ ложительным аспектом. • Фиксация должна быть отложена до подходящего момента. Ее не следует вы­ пол нять быстро, чтобы избежать перегрузки системы, т. к. дл ител ьные ил и крупные транзакции вовсе ее не перегружают. П равило предусматривает вы­ полнение фиксации тогда, когда она должна быть сделана, но не раньше. Размер транзакци й должен ди ктоваться бизнес-логикой . ( И нтересное стороннее заме­ чание: сегодня утром я сформул ировал это правило фиксаци и - выполнять фиксац и ю тогда, когда она должна быть сделана, но не раньше - на сайте h t t p : 1 / a s k t om . o r a c l e . с от вероятно в миллионный раз. Кое-что в этом мире н икогда не меняется . ) Б л окировка и за щ ел ки ван и е дан ных 303 • Блокировки данных должны удерживаться столько, сколько необходимо. Они я вля ются инструментами , предназначенными для испол ьзования , а н е тем , чего следует избегать. Блокировки - н е дефицитны й ресурс. Напротив, дан ­ н ы е следует блокировать настолько долго, н асколько это нужно. Н е являясь дефицитными, блокировки могут предотвратить изменение и нформации дру­ гими сеансами . • С блокировкой на уровне строк в Oracle не связаны какие-либо накладные расходы - вообще . Независимо от того, сколько есть блокировок строк, 1 или 1 000 000 , объем ресурсов, выделенных для блокирования этой и нформации , будет тем же самым. Конечно, вам придется проделы вать намного больше ра­ боты , модифицируя 1 000 000 строк вместо 1 строки , но коли чество ресурсов, необходимых для блокировки 1 000 000 строк, будет таким же, как при блоки­ ровке 1 строки ; это фиксированная константа. • Ранг блокировки никогда не должен повышаться (примером может быть при­ менение блокировки таблицы вместо блокировки строк) из-за того, что так было бы "луч ше для системы " . В Oracle это не будет лучше для систем ы ­ никакие ресурсы не экономятся . Существуют ситуаци и для испол ьзован ия блокировок таблиц, такие как п акетны й процесс, при выполнении которого хорошо известно, что будет обновляться вся табли ца и нежелательно, чтобы другие сеансы блокировали отдельные строки в ней. Н о не следует применять блокировку таблицы лишь для того, чтобы облегчить системе работу путем ус­ транения необходимости в выделени и блокировок строк; блокировка таблицы используется для обеспечения доступа ко всем ресурсам , в которых нуждается пакетная программа. • П араллел изма и согласован ности можно достигнуть одновременно. В любой момент времени дан ные можно извлечь быстро и точно. П роцессы чте н ия данных не блокируются процессами записи дан н ых. П роцессы записи дан н ых не блокируются процессами чте н ия дан н ых. В этом состоит одно из фунда­ ментальных отличий между Oracle и большинством других реляцион н ых баз данных. По мере изложения материала в этой и следующей главах, я подкрепл ю эти ут­ верждения дополнительными аргументами . П р облем ы бл о ки р о вки Прежде чем мы обсудим разнообразные типы блокировок, применяемые в Orac1e, полезно взглянуть на определенные проблем ы блокировки , м ногие из которых яв­ ляются результатом плохо спроектированн ых приложений, неправильно использую­ щих (или вообще не использующих) механизмы блокировки базы дан н ых. П отерянные обновления Потеря н ное обновле ние (lost update) - классическая проблема базы данных. Действительно, эта проблема возникает во всех м ногопользовательских ком пьютер­ ных средах. Выражаясь просто, потерян ное обновление происходит, когда происхо­ дят следующие события в приведеином здесь порядке . 304 Глава 6 1 . Транзакция в сеансе Session l извлекает (запрашивает) строку данных в локаль­ ную п амять и отображает ее конечному пользователю, User l . 2 . Друrая транзакция в сеансе Session2 извлекает ту же самую строку, но отобра­ жает данные другому конечному пользователю, User2. 3 . С помощью своего приложения пользователь Userl изменяет эту строку и вы­ нуждает приложение обновить базу данн ых и произвести фиксацию. На этом транзакция сеанса Session 1 завершается . 4. П ользователь User2 также модифицирует эту строку и вынуждает приложение обновить базу данн ых и выполнить фиксацию. Транзакция сеанса Session2 за­ вершена. Описан н ы й сценарий называют потерянным обновлением, потому что все изме­ нения, сделанные н а шаге 3, будут утеряны. Н апример, рассмотрим экран обнов­ ления с веде н и й о сотрудни ках, который позволяет пользователю изменять адрес, номер рабочего телефона и т.д. Само приложение является очен ь простым : неболь­ шой экран поиска, которы й генерирует список сотрудников, а затем предоставляет возможность вывода п одробн ых сведе н и й о каждом из них. Выглядит пустячн ы м делом. Таким образом, м ы создаем приложение безо всякой блокировки с о своей стороны , которое выпол няет только простые команды SELECT и UPDATE . Затем конечн ы й пользователь ( Userl ) переходит н а экран подробных сведений, изменяет адрес, щелкает на кнопке сохранения и получает сообщение о том , что об­ новление было успешно выполнено. Все прекрасно за исключением того, что когда на следующий день пользователь Use r l проверяет запись, чтобы отправить деклара­ цию о доходах, в ней по-прежнему указан старый адрес. Как такое могло произой­ ти? К сожален и ю , подобная ситуация может возникнуть очень легко. В этом слу­ чае другой конечн ы й пользователь (User2) запросил ту же самую запись сразу после пользователя Userl после того, как пользователь Userl прочитал данные, но перед тем , как он их изменил. Затем, после запроса пользователем User2 данных пользо­ ватель Userl произвел обновление , получил подтверждение и даже повторил запрос, чтобы удостовериться в успешном обновлен и и данн ых. Однако затем пользователь Use r2 обновил поле номера рабочего телефона и щелкнул на кнопке сохранения, совершенно не подозревая о том , что он перезаписал старыми данными измененное пользователем Userl поле адреса! Причина возни кновения такой проблемы в этом случае связана с тем , что разработчи к реал изовал свое приложен ие так, что при об­ новлен и и какого-то одного поля все поля дан ной записи также обновляются (всего лишь потому, что проще обновить все столбцы , чем выяснять, какие столбцы изме­ нились, и обновлять только их). Обратите внимание, что для п оявления описанной ситуации даже не требуется , чтобы пользователи Use r l и User2 работали с зап исью в точ ности одновременно. Нужно чтобы они работали с записью приблизительно в одно и то же время. Мне неоднократно приходилось н аблюдать эту проблему, когда программисты , зани мающиеся созданием графических пол ьзовательских и нтерфейсов, которые имели лишь небольшой опыт работы с базам и данн ых или вообще не имели его, по­ лучали задание написать приложение базы данн ых. Они бегло знакомились с опера­ циями SELECT, INS E RT , U P DAT E и DELETE и принимались за создание приложения. Когда результирующее приложение ведет себя описанным образом, оно полностью подрывает доверие пользователя к себе , особенно с учетом того, что этот недостаток - Блокировка и за щ ел кивание данн ых 305 проявляется случайно, непредсказуемо и совершенно н е поддается воспроизведе­ нию в контролируемой среде (вырабатывая у разработчика уверен ность в том , что это должна быть ошибка пользователя) . Многие инструменты , подобные Oracle Fonns и АРЕХ (Application Express - инс­ трумент, который применялея для создания веб-сайта AskTom) , прозрачным обра­ зом предотвращают такое поведение, гарантируя невозможность изменения зап иси с момента ее запроса и блокируя ее вплоть до внесения всех необходимых измене­ ний (оптимистическая блокировка) . Н о многие другие ( вроде написанных вручную программ на Visual Basic или Java) этого не делают. Обеспечение защиты данных ка­ кими-то средствами , работающими "за кул исам и " , или же самими разработчи ками сводится к использованию одного из двух типов блокировки : пессимистической или оптимистической. П ессимистическая блокировка Метод пессимистической блокировки будет вступать в действие непосредственно перед тем , как пользователь изменяет значение н а экране. Напри мер, блокировка строки будет установлена, как только пользователь сообщит о своем намерении об­ новить конкретную строку, которая выбрана им и отображается на экране (скажем , щелчком н а какой-нибудь кнопке). Эта блокировка строки будет постоянной до тех пор, пока приложение не применит изменения, внесенные пользователям и , к соот­ ветствующей строке и не выполнит фиксацию. Пессимистическая блокировка приемлема только в среде с сохранением состоя­ ния или подключенной среде - т.е. среде, в которой приложение имеет постоян ное подключение к базе данн ых и только один пользователь использует это п одключе­ ние, по крайней мере , в течение времени существования транзакции. В начале и середине 1 990-х годов, когда широкое распространение получили клиент-серверные приложения , этот способ блокировки был преобладающ и м . Каждое приложение должно было получать прямое подключение к базе данн ых, применяемое исключи­ тельно этим экземпляром приложения. В настоящее время такой метод подключе­ н ия с сохранением состояния стал менее распространенным (хотя и не исчез пол­ ностью) , особенно после появления серверов приложе н и й ближе к кон цу 1 990-х годов. Предполагая , что используется подключен ие с сохранением состоян и я , можно иметь приложение, которое запрашивает данные безо всякой блокировки : SCOTT@ORA12CR1> se lect empno , ename , sal from emp whe re deptno = 1 0 ; EMPNO ЕNАМЕ SAL 7 7 8 2 CLARK 7 8 3 9 KING 7 9 34 MI LLER 2450 5000 1300 В конце концов , пол ьзовател ь выбирает строку, которую желает обновить. Представим , что в рассматриваемом случае он решил обновить строку M I L L E R . В этот момент (перед тем , как пользователь внесет любые изменения н а экране, н о после того, как строка извлечена из базы данных на некоторое время ) приложение привяжет выбранные пользователем значен ия так, что м ы можем запросить базу данных и удостовериться в том , что данные пока не были изменены . 306 Глава 6 В среде SQL* Plus для эмуляции операци й привязки, которые должно выполнить приложение, можно выдать следующий запрос: SCOTT@ORA12CR1> variaЬle empno numЬer SCOTT @ORA1 2CR1> variaЬle ename va rchar2 ( 2 0 ) SCOTT @ORA1 2 CR1 > variaЫe sal numЬer SCOTT@ORA12CR1> ехес : empno : = 7 9 3 4 ; : ename . - ' MI LLER ' ; : sa l · = 1 3 0 0 ; PL/ SQL procedure succe s s ful l y completed . Процедура PL/SQL успешно завершена . Теперь в дополнение к простому запросу значений и проверки того, что они не был и изменены , мы собираемся заблокировать строку с применением FOR UPDATE NOWAI T . Приложеине выполнит такой запрос: SCOTT@ORA1 2CR1 > select empno , ename , sal 2 from emp 3 where empno = : empno 4 and decode ( ename , : ename , 1 ) 1 5 and decode ( sal , : sa l , 1 ) = 1 6 for update nowa it 7 1 EMPNO ЕNАМЕ SAL 7 9 3 4 MI LLER 1300 Н а заметку! Почему м ы использовали конструкци ю de code ( с т ол б е ц , : п е р еме н н а я 1 ) = 1 ? Это просто сокращенный способ выражения where ( с т олбец = : п ереме н н а я _ прив я з ки ИЛИ ( с т о л б е ц я в л я е т с я NULL и : п ереме н н а я _ при в я з ки я в л я е т с я NULL ) . Вы можете выбрать любой вариант кода, но вызов decode ( ) в данном случае более ком пактен, и поскольку в SQL результат сравнения NULL = NULL никогда не является истинным ( и не ложным ! ) , оди н из этих двух подходов н еобходим , если любой из столбцов допускает значения NULL. п р и в я з ки , П р иложеине п редоставляет значения переменных привязки на основе дан ных, отображаемых н а экране ( 7 9 3 4 , M I LLER и 1 3 0 0 ) и запрашивает ту же строку из базы данн ых, на этот раз блокируя ее от обновлений другим и сеансами; вот почему такой подход н азывается пессимистической блокировкой. М ы блокируем строку до попыт­ ки ее обновления , т.к. сомневаемся - настроены пессимистически - в том, что ина­ че она останется неизмененной . П оскольку все таблицы должны иметь первич н ы й кл юч (предыдущий запрос S E LECT извлечет не более одной строки , потому что он содержит первичный ключ EMPNO ) , и первичные ключи должн ы быть неизменными (мы никогда не должны их обновлять) , мы получим из этого оператора один из трех результатов. • Если исходные данные не был и изменены, мы получим строку M I LLER, и эта строка будет заблокирована для обновлен ия (но не чтения) другими пользова­ телям и . • Есл и другой пол ьзователь н аходится в п роцессе изменения этой строки , мы получи м сообщение об ошибке ORA- 0 0 0 5 4 : r e s ource bu s y (ORA-00054: ре­ сурс занят) . Н ам придется ожидать, пока другой пользователь не завершит ра­ боту с этой строкой . Б локировка и за щ ел ки ван и е данн ых • 307 Если в промежутке между выбором данн ых и указанием о н амерен и и обновить их кто-то другой уже изменил строку, мы получи м обратно ноль строк. Это оз­ начает, что данные, отображенные на экране, устарели . Чтобы предотвратить ранее описанный сценарий потерянного обновле н ия , приложение должно за­ ново запросить данные и заблокировать их, перед тем как позвол ить конечному пользовател ю вносить изменения. Благодаря пессимистической блокировке , при попытке обновлен ия поля с телефонн ы м номером пользователем User2 приложение будет знать, что поле адреса было изменено и повторно запросит данные. Таким образом, пользователь User2 не перезапишет изменение, вне­ сенное пользователем User l , старыми данными этого поля . После того как мы успешно заблокировал и строку, приложение при вяжется к новым значен иям, выполнит обновление и зафиксирует изменения: SCOTT @ORA1 2CR1> update emp 2 set ename = : ename , s al = : sa l 3 whe re empno = : empno ; 1 row updated . 1 строка обновлена . SCOTT @ORA12CR1> commi t ; Commi t complete . Фиксация выполнена . Итак, мы изменили нужную строку весьма безопасным образом. При этом пере­ запись изменений какого-то другого пользователя оказывается невозможной , т.к. м ы проверили, что данные н е изменялись в течение периода между и х первоначальным считыванием и блокировкой. Эта проверка гарантирует, что никто не изменит данные раньше нас, а блокировка - что никто не изменит их, пока м ы с ними работаем . О птимистическая блокировка Второй метод, которы й называется оптимистической блокировко й , откладывает все действия по блокировке до момента, непосредственно предшествующего выпол­ нению обновления. Другим и словами , м ы будем изменять и нформацию н а экране, не прибегая к блокировке. М ы оптимистически предполагаем, что данные не будут изменены каким-то другим пользователем, поэтому проверка того, верно л и такое предположение, откладывается до самого последнего момента. Этот метод блокировки работает во всех средах, но увеличивает вероятность по­ тери обновления, выполняемого пользователем. То есть, когда пользователь собира­ ется обновить строку, он обнаруживает, что данные были модифицированы, и при­ дется начинать все сначала. Одна из популярных реализаций оптимистической блокировки предусматривает хранение в приложении старых и новых значен и й и применение для обновле ния данных запроса, подобного показанному н иже: Update таблица Set столбецl = : новый_столбецl , столбец2 = : новый_столбец2 , Where первичный_ключ = : первичный_ключ And столбецl = : старый_столбецl And столбец2 = : старый_столбец2 308 Глава 6 Здесь мы оптимистически предполагаем , что данные не были изменены. В таком случае , если система сообщит об обновлении одной строки , нам повезло: данные не изменялись в промежутке между моментом их чтения и моментом , когда мы отправ­ ляем обновление. Если мы обновили ноль строк, произошла потеря : кто-то другой изменил данные, и теперь предстоит решить, каким образом продолжать работу в приложе нии. Должны ли мы дать конечному пользователю возможность повторе­ ния транзакции после запроса новых значен и й для строки ( потенциально вызывая разочарование у пользователя , т.к. есть шанс, что строка снова изменится )? Или мы должн ы попытаться объединить значения двух обновлений, устраняя конфликт об­ новления на основе бизнес-правил (большой объем кода)? Предыдущи й оператор U P DAT E фактически избегает потерян ного обновления, но остается возможность его блокирования - оператору придется дожидаться за­ вершения обновления этой строки другим сеансом. Если все ваши приложения ис­ пользуют оптимистическую блокировку, то применен ие простого оператора U P DAT E в основном приемлемо, потому что строки блокируются на очень короткий пери­ од времен и , пока обновлен ия применя ются и фи ксируются . Тем не менее, если в некоторых приложениях используется пессимистическая блокировка, при которой блокировки будут удержи ваться на строках в течение относительно долгих перио­ дов времен и , или есл и есть приложение (вроде пакетного процесса) , которое может блокировать строки на длительный период (длительны м периодом считается более одной или двух секунд), то вы должны подумать о применении оператора S E LECT FOR U P DATE NOWAIT вместо выполнения проверки того, что строка не изменялась, и блокировании строки непосредственно перед выдачей операции UPDAT E, избегая ее блокировки другим сеансом. Существует много методов реализации оптимистического управления параллель­ ной обработкой. Мы рассмотрели оди н из них, при котором все исходные образы строки будут храниться в самом приложении. В последующих разделах мы исследу­ ем еще два метода: • использование специал ьного столбца, поддерживаемого триггером базы дан­ ных или кодом приложения, который сообщает " верси ю" записи; • применение контрольной суммы или хеш-значения, вычисленного с исполь­ зованием исходных данн ых. Оптимистическая блокировка с использованием столбца версии Это простая реализация , предусматри вающая добавление по одному столбцу в каждую табли цу базы данн ых, которую нужно защитить от потерянных обновлений. Обычно такой столбец и меет тип NUMBER или DAT E / T I ME S TAМ P . Как правило, он поддерживается через триггер строки самой таблицы, который отвечает за инкре­ ментираванне значен ия столбца NUMBER или обновление столбца DAT E / T IMESTAМ P при каждом изменении строки . На заметку! Я указал , что столбец версии обычно поддержи вается через триггер строки . Однако я не утверждал, что это лучший и л и самы й правильный способ. Лично я предпо­ ч итаю, чтобы этот столбец обрабатывался сами м оператором U P DATE , а не посредством триггера, потому что триггеров, не являющихся абсолютно необходимыми (а этот триггер обязательным назвать нельзя ) , следует избегать. Б л окировка и за щ ел ки вани е дан н ых 309 На заметку! П редпосылки и п р и ч и н ы , по котором я избегаю триггеров, изложены в моей статье "TrouЫe with Triggers" ( " Проблемы с три ггера м и " ) в журнале Oracfe Magazine , ко­ торую можно найти в Oracle Technology Network по адресу h t t p : 1 /www . o r a c l e . сот / technetwo r k / i s s ue-a rchive / 2 0 0 8 / 0 8 - s e p / o 5 8 a s ktom- 1 0 1 0 5 5 . html . Приложен ие, в котором вы хотите реализовать оптим и стическое управл е ­ н и е параллельной обработкой , должно будет сохранять только значение этого до­ полнительного столбца, а не все предварител ьн ые образы остальных столбцов. Приложению придется проверять лишь то, что значение в этом столбце в момент запроса обновлен ия соответствует первоначально прочитанному значению. Если эти значения совпадают, то строка не была обновлена. Давайте взглянем на реализацию оптимистической блокировки с применением копи и таблицы sсотт . DE PT. Дл я создания таблицы можно воспользоваться следу­ ющим кодом DDL ( Data Definition Language - язык определения данн ых) : EODA@ORA12CR 1 > create taЬle dept 2 ( deptno numЬer ( 2 ) , dname va rchar2 ( 1 4 ) , 3 va rchar2 ( 1 3 ) , loc 4 5 б 7 last mod timestamp wi th time zone defaul t systimestamp not null , 8 constraint dept_p k prima ry key ( deptno ) 9 ) 10 1 ТаЬlе created . Таблица создана . Теперь вставим в эту таблицу копию данных таблицы DEPT: EODA@ORA12CR1> insert into dept ( deptno , dname , loc ) 2 select deptno , dname , loc from s cott . dept ; 3 4 rows created . 4 строки создано . EODA@ORA12CR 1 > commi t ; Commit complete . Фиксация выполнена . Этот код воссоздает табли цу DE P T , но с дополн ительным столбцом LAS T MOD, имеющим тип данных T IMESTAМP W I T H T I ME ZONE. М ы определили этот столбец как NOT NULL, так что он должен быть заполнен , и е го стандартным значением яв­ ляется текущее время в системе. Тип данных T I M E S TAM P поддерживает очень высокую точность в Oracle, обыч­ но вплоть до микросекунды . Для приложений, учитывающих время размышлений пользователя , такой уровен ь точности типа T I M E S TAM P более чем достаточе н , и весьма маловероятно, что nроцесс базы данн ых, и звлекающи й строку, и процесс пользователя, которы й ее просматривает, модифицирует и выдает команду обнов­ ления, могут пересечься в рамках доли секунды . И действительно, вероятность того, что два пользователя будут читать и изменять одну и ту же строку в течение одной и той же доли секунды, крайне н изка. 31 0 Глава 6 Теперь нам требуется метод поддержания этого значения. Существуют две воз­ можности : поддержка столбца LAS T _моо может выполняться либо приложением путем установки его значен ия в SYST I MESTAМP при обновлении записи , либо триг­ гером или хранимой процедурой . Поддержка этого столбца приложением я вляется определенно более производительным подходом , чем прием на основе триггера, т.к. триггер добавит допол нительную обработку сверх той , что уже делается Огасlе . Однако это означает, что все приложения должн ы поддерживать столбец LAST_MOD в согласованном состоян и и во всех местах, где они модифицируют дан ную табли­ цу. Таким образом , если каждое приложение несет ответственность за поддержание столбца LAS T _моо, то оно должно постоянно выполнять проверку на предмет от­ сутствия в нем изменен и й и устанавл ивать его в текущее значение S Y S T I MESTAМ P . Например, если приложение запраш ивает строку с DEPTNO= l O : EODA@ORA1 2 CR1 > variaЬle deptno numЬer EODA@ORA 1 2 CR1 > variaЬle dname varchar2 ( 1 4 ) EODA@ORA 1 2 CR1 > va riaЬle loc va rchar2 ( 1 3 ) EODA@ORA12 CR1 > variaЬle last mod varchar2 ( 5 0 ) EODA@ORA12 CR1 > EODA@ORA 1 2 CR1 > begin 2 : deptno : = 1 0 ; 3 select dname , loc, to_char ( last_mod, ' DD- MON - YYYY HH . MI . SSXFF АМ TZR ' ) into : dname , : l oc , : las t_mod 4 from dept 5 б whe re deptno = : deptno ; 7 end ; 8 1 PL/SQL p rocedure succe s s fu l l y comp leted . Процелура PL/SQL успешно завершена . которая в текущий момент выглядит так: EODA@ORA 1 2 CR1 > s e lect : deptno dno , : dname dname , : loc loc , : last mod lm 2 f rom dual ; DNO DNAМE LOC LM 10 ACCOUNT ING NEW УОRК 1 5-APR- 2 0 1 4 0 7 . 0 4 . 0 1 . 1 4 7 0 9 4 РМ - 0 6 : 0 0 то для изменения и нформации будет использоваться при веденный ниже опера­ тор обновления. П оследняя строка делает очень важную проверку, чтобы удостове­ риться в том, что метка времен и не измен илась, и применяет встроен ную функцию то_T IMESTAМP_т z ( T Z - это аббревиатура от "time zone " (часовой пояс)) для пре­ образования строки , сохраненной оператором SELECT, в подходящий тип данных. Вдобавок строка 3 оператора U P DATE обновляет столбец LAST _MOD текущим време­ нем, если подлежащая обновлен и ю строка найдена: EODA@ORA12CR1> update dept 2 set dname = ini tcap ( : dname ) , 3 l a s t_mod = s y s t imes tamp 4 where deptno = : deptno 5 and last_mod to_timestamp_tz ( : last_mod, ' DD-MON -YYYY НН . MI . SSXFF АМ TZR ' ) ; = 1 row updated . 1 строка обновлена . Б локировка и за щ ел ки ван и е данных 31 1 Как видите , была обновлена одна строка - строка, которая н ас интересовала. М ы обновили строку по первич ному кл ючу ( DE P T N O ) и проверил и , что столбец LAS T_MOD не был изменен каким-то другим сеансом в промежутке между моментом первоначального считывания и моментом выполнения обновления. Если бы мы по­ пытались снова обновить эту же строку, используя ту же самую логику, но без извле­ чения нового значен ия LAS T_MOD, результат был бы следующим: EODA@ORA1 2CR1 > update dept 2 set dnarne = upper ( : dname ) , las t_mod = systime starnp 3 4 whe re deptno = : deptno 5 and las t_mod = t o_t ime s t amp_t z ( : las t_mod , ' DD-MON-YYYY HH . M I . S SXFF АМ TZR ' ) ; О rows updated . О строк обновлено . Обратите вн имание, что на этот раз сообщается об обновлен и и О строк, т.к. пре­ ди кат на LAS T_мо о не бьшо удовлетворе н . Хотя строка со значением 1 О в столбце DE PTNO по-прежнему существует, значение на момент времени, когда мы пожелали выполн ить обновление, больше не совпадает со значением метки врем е н и на мо­ мент запроса строки . Таким образом, основываясь на том факте, что строки не бьши модифи цированы, приложение знает об изменении дан ных в базе дан н ых и теперь должно принять решение о своих последующих действиях. По ряду причин поддержку этого поля нежелательно возлагать на каждое при­ ложение. Прежде всего, это ведет к увел ичени ю объема кода приложе н ия , причем дополнительный код требует повторения и корректной реализаци и везде, где данная таблица изменяется . В крупном приложении таких мест может быть много. Более того, каждое приложение, которое будет разработано в будущем, должно соответс­ твовать этим же правилам . Высока вероятность упустить из виду такой фрагмент кода в каком-то приложе н и и , в результате чего это поле будет использоваться не­ правил ьно. Следовател ьно, есл и сам код приложе н ия не несет ответствен ность за поддержание поля LAS T MO D , то, по моему убежде н и ю , приложе н ие не должно отвечать за проверку этого поля (если оно может делать проверку, то определенно способно выполнять и обновление). Таким образом , в этом случае я предлагаю ин­ капсулировать логику обновления в хранимую процедуру и вообще не разрешать при­ ложению обновлять табли цу напрямую. Если приложен и ю нельзя доверить подде­ ржание значен ия этого поля , то ему нел ьзя доверять и проверку. И так, храни мая процедура будет прини мать в качестве входных данных переменные привязки , ко­ торые мы применяли в предыдущих обновлениях, и выпол нять точно такое же об­ новление. В случае обнаружения , что обновлено О строк, хранимая процедура могла бы генерировать исключение, ставя кл иента в известность о том , что фактически обновлен ие не было произведено. Альтернативная реализация предусматривает использование три ггера для подде­ ржания поля LAST _MO D , но для таких простых задач я рекомендую избегать триг­ гера и позволить позаботиться обо всем храни мой процедуре D M L. Три ггеры при­ вносят умеренный объем накладных расходов , и в этом случае они необязательн ы . Вдобавок триггер н е и меет возможности подтвердить, что строка не бьша модифи­ цирована (он способен только предоставить значение для столбца LAST _MOD , но не проверять ero во время обновления ) , следовательно, приложение должно быть осве- 31 2 Глава б домлен о об этом столбце и о корректной работе с ним. Таким образом, одного лишь триггера оказывается недостаточно. Оптимистиче ская блокировка с использованием контрольной суммы Этот метод очен ь похож на предыдущий метод со столбцом версии, но в нем применяются данные самой базы для вычисления " виртуального" столбца версии. Ч тобы помочь в прояснен и и цели и конце п ци й , лежащих в основе контрольной суммы или хеш -функции , н иже приведена выдержка из справочного руководства по пакетам и типам PL/SQL (Oracle Database PL/SQL Packages апd Types Refereпce). Однонаправленная хеш-функция принимает входную строку переменной дли ­ н ы (данные) и преобразует е е в выходную строку фиксированной длины (обычно меньшую по размеру), которая называется хеш-значением. Хеш-значение служит уникальным идентификатором (подобным отпечатку пальца) входных данных. Это хеш-значение можно использовать для проверки, изменялись ли данные. Обратите внимание, что однонаправленная хеш-функция - это хеш-функция, которую обратить нелегко. Вычислить хеш-значение на основе входных данных очень просто, но сгенерировать данные, приводящие к получению конкретного хеш-значения, довольно трудно. С готовыми хеш -значениями или контрольными суммами можно работать в той же манере , как и со столбцом верс и и . М ы просто сравни ваем хеш-значение или контрольную сумму, полученную при чтении данных из базы , со значением, вычис­ ленн ы м перед модификацией данных. Если кто-то изменил значения строки после того, как мы их прочитал и , но перед тем , как их обновил и , то хеш-значение или контрольная сумма почти наверняка будет отл ичаться . Существует м ного способов вычисления хеш-значения или контрольной суммы. Н иже перечислено несколько способов, а далее в разделе приведена демонстрация одного из н их. Все эти методы основаны на предоставляемой фун кциональности базы дан н ых. • OWA_ОРТ_LOCK . CHECKSUМ. Этот метод доступен в Orac1e8i версии 8 . 1 . 5 и выше. И меется фун кция , которая возвращает 1 6-битную контрольную сумму для пе­ реданной ей строки , и функция, которая вычисляет 1 6-битную контрол ьную сумму мя предоставленного идентификатора строки ( ROWI D) и одновремен­ но блокирует эту строку. Вероятность конфл икта составляет 1 к 65 536 строкам (наибольший шанс ложного совпадения значений). • DBMS OBFUSCAT I ON_TOOLKIT . MDS . Этот метод доступен в 0racle8i версии 8. 1 .7 и вы ше. Он вычисляет 1 28-битный дайджест сообщения. Вероятность возник­ новения конфликта составляет около 1 к 3 ,4028Е+38 (очень низкая). • овмs CRYPTO . НАS Н . Этот метод доступен в Oracle 1 Og Release 1 и последую­ щих версиях. Он способен вычислять дайджесты сообщений по ал горитмам SHA- 1 (Secure Hash Algorithm 1 - безопасный алгоритм вычисления хеш-зна­ чения ) или M D4/M D5. Рекомендуется применять алгоритм SHA- 1 . • овмs SQLНAS H . GETНASH. Этот метод доступен в Oracle 1 Og Re1ease 2 и после­ дующих версиях. Он поддержи вает хеш-алгоритмы SHA- 1 , M D4 и M D5 . Как привилегированн ы й пользователь SYS DBA, вы должн ы вьщать право на выпал- _ _ _ Бл окировка и за щ ел ки ван и е данн ых 313 нение этого пакета пользователю, преЖде чем он сможет обратиться к нему. П акет документирован в руководстве по безопасности базы дан н ых Oracle (Oracle Database Security Guide) . • STAN DARD_HAS H. Этот метод доступен в Oracle 1 2с Release 1 и последующих версиях. Он предстаR/IЯет собой встроен ную функцию SQL, которая вычисля­ ет хеш-значение для выраже н ия с испол ьзованием стандартных хеш-ал горит­ мов, таких как S HA- 1 (по умолчан и ю) , S HA-256, S HA-3 84, SHA- 5 1 2 и M D5. Возвращаемое значение и меет тип данн ых RAW. • ORA_ HAS H . Дан н ы й метод доступен в Oracle I Og Release 1 и последующих версиях. Это встроен н ая фун кция SQL, п р и н и м аю щая н а входе значен и е VARCHAR2 и (необязательно) еще два параметра, которые управляют возвра­ щаемым значением. Возвращаемым значением я RIIЯ ется ч исло, по умолчанию находящееся в пределах от О до 4 294 967 295 . Н а заметку! Массив функций вычисления хеш-значени й и контрольных сумм доступен в о многих языках программирования, поэтому в вашем распоряжении могут быть и другие функции , реал изованные за рамками базы данных. Тем не менее, применяя встроенные возможности базы данных, вы увеличиваете степень переносимости (на новые языки и новые подходы ) в будущем . В следующем п р имере показа н о , к а к и с п ол ьзовать встроен ну ю фун кци ю DBMS _CRYPTO в Oracle I Og и последующих версиях для вычисления хеш -значений/ контрольных сум м . Такой прием также примен и м к остальным перечисл е н н ы м подходам; логика будет отличаться не сильно, но вызываемые АРI-интерфейсы ока­ зываются очень разн ы м и . Мы начнем с того, что избавимся от столбца, который использовался в предыдущем примере: EODA@ORA12CR1> alter taЬle dept drop column las t_mod ; ТаЬlе altered . Таблица изменена . Затем приложение должно запросить и отобразить и нформацию об отделе с но­ мером 1 0. Обратите внимание, что при запрашивани и и нформации мы вычисляем хеш-значение с помощью встроенной функции DBMS_CRY PTO. Это информация о версии , которая сохраняется в приложении. Следующий код выдает запрос и отоб­ ражает информацию: EODA@ORA12CR1> va riaЬle deptno nurnЬer EODA@ ORA12CR1 > va riaЬle dname varchar2 ( 1 4 ) EODA@ORA12CR1> va riaЬle loc varchar2 ( 1 3 ) EODA@ORA1 2CR1> va riaЬle hash nurnЬer EODA@ORA12CR1> begin 2 select deptno , dname , loc, o ra_hash ( dname 1 1 ' 1 ' 1 1 loc ) hash 3 into : deptno , : dname , : l oc , : hash 4 from dept 5 б where deptno = 1 0 ; 7 end ; 8 1 314 Глава 6 PL/ SQL p rocedure succe s s ful l y completed . Процедура PL/SQL успешно завершена . EODA@ ORA1 2CR1 > select : deptno , : dname , : l oc , : hash from dual ; 2 : DE PTNO 10 : DNAМE : НАSН : LOC 2 7 2 1 97 2 0 2 0 Accounting NEW УОRК Как видите , хеш-значен ие - это просто некоторое ч исло. И менно его мы хо­ тим применять перед обновлением. Чтобы обновить строку, понадобится заблоки­ ровать строку в базе дан н ых в текущем состоянии и затем сравнить хеш-значение этой строки с хеш-значением, которое было вычислено при чтении данных из базы. Логика приложе н ия может выглядеть примерно так: EODA@ ORA12CR1> ехес : dname : = l ower ( : dname ) ; PL/ SQL p rocedure succe s s fu 1 l y compl eted . Процедура PL/SQL успешно завершена . EODA@ORA 1 2 CR1 > update dept 2 set dname = : dname 3 whe re deptno = : deptno 4 and ora_hash ( dname 1 1 5 1 1 row updated . 1 строка обновлена . '1' EODA@ORA 1 2 CR1 > s e lect dept . * , 2 ora_hash ( dname 1 1 ' 1 ' 3 from dept 4 where deptno = : deptno ; DE PTNO DNAМE : hash 1 1 loc ) 1 1 loc ) ha sh HASH LOC 2 8 1 8 8 5582 9 1 0 accounting NEW YORK При повторном запросе этих же данн ых и вычислен и и хеш-значения заново пос­ ле обновления можно заметить, что хеш -значение отличается . Если кто-то модифи­ цировал строку до н ас , то хеш -значения не совпадали бы. Мы можем увидеть это, попытавшись снова вы пол н ить наше обновление с использованием старого хеш ­ значен ия, которое бьmо вычислено п р и чтении дан н ых в первый раз: EODA@ ORA1 2CR1 > update dept 2 set dname = : dname 3 where deptno = : deptno and ora_ha s h ( dname 1 1 ' / ' 4 5 1 1 1 loc ) : hash О rows updated . О строк обновлено . Как видите , было обновлено О строк, потому что хеш -значение не соответствует данным, находящимся в текуший момент в базе . Для корректной работы этого подхода на основе хеш-значений мы должны обес­ печить, чтобы в каждом приложении применялея один и тот же способ вычисления хе ша, а именно - конкатенаци и dname с символом 1 и l o c, причем в указанном Б локи ровка и з а щ ел ки вани е данных 31 5 порядке . Чтобы сделать этот подход универсальны м , я бы посоветовал добавить к таблице виртуальный столбец (в Oracle l lg Release 1 и последующих версиях) либо использовать для добавления столбца представление, скрыв эту функцию от самого приложения. Вот как выглядит добавление столбца в Oracle Database l lg Release 1 и последующих версиях: EODA@ORA12CR1 > a1ter taЬle dept 2 add hash as 3 ( ora_hash ( dname 1 1 / 1 1 loc ) ) ; ТаЬlе altered . Таблица изменена . ' ' EODA@ORA12CR1 > select * from dept 2 3 where deptno = : deptno ; DE PTNO DNAМE LOC 1 0 accounting NEW УОRК HAS H 2818855829 Добавленный столбец я вляется виртуальным, и как таковой не влечет за собой накладные расходы по хранению. Его значение не вычисляется заранее для сохране­ ния на диске. Вместо этого оно вычисляется при извлечен и и данных из базы. В при ведеином примере продемонстрирована реализация оптимистической бло­ кировки с применением хеш-значен и я или контрол ьной сум м ы . Следует и меть в виду, что вычисление хеш-значения или контрольной суммы - операция, требую­ щая значительной загрузки процессора. Это следует учитывать в тех системах, где процессорное время я вляется дефицитны м ресурсом . Однако такой подход значи­ тельно более дружествен по отношению к сети, потому что передача через сеть срав­ нительно небольшага хеш -значения вместо начального и конечного образа строки (для выполнения сравнения по столбцам) требует значительно меньшего объема се­ тевых ресурсов. Выбор между оптимистической и пессимистической блокировкой Так какой же метод лучше? Согласно моему опыту, пессимистическая блокиров­ ка очень хорошо работает в Oracle (но, возможно, не так хорошо в других СУБД) и обладает многими преимуществами по сравнению с оптимистической блокировкой . Тем не менее, она требует подкл ючения к базе данных с сохранением состоя н ия , подобного клиент-серверному подключен и ю . Причина в том , что блокировки не удержи ваются между подключениями. Этот простой факт делает пессимистическую блокировку нереальной в наши дни . В прошлом , когда приходилось и меть дело с клиент-серверными приложениями и парой десятков или сотен пользователей , пес­ симистическая блокировка была бы моим первым и последни м вариантом . Однако в настоящее время для большинства приложений я рекомендую использовать опти­ мистическое управление параллельной обработкой . Н аличие подключения на про­ тяжении всей транзакции - просто чересчур высокая цена. А что можно сказать о доступных методах? Л ично я предпочитаю применять под­ ход со столбцом версии в форме метки времен и . Это предоставляет допол нительную информацию об обновлении в долгосрочном смысле . К тому же этот метод требует меньшего объема вычислен и й , чем использование хеш-значен ия или контрол ьной 31 6 Глава б суммы, и не создает потенциальных проблем , которые могут возникать при вычис­ лени и хеш -значения или контрольной сум м ы для дан н ых типа LONG, LONG ROW , CLOB, BLOB и других очен ь больших столбцов (тип ы LONG и LONG RAW устарели ; я упоминаю их здесь потому, что они по-прежнему часто применяются в словаре дан­ н ых Oracle). Есл и бы м н е лонадобилось добавить средства опти мистического управления параллельной обработкой в табли цу, которая должна применяться в схеме песси­ мистической блокировки (например, таблицу, к которой происходит обращение из клиент-серверных приложений и веб- приложений), то я бы остановил свой выбор на подходе с ORA_HAS H. Это связано с тем , что существующие унаследован ные при ­ ложен ия могут не воспринять положительно появление нового столбца. Даже если предпринять меры для сокрытия этого дополнительного столбца, приложение может пострадать от накладных расходов, вызванных обязательным в таком случае тригге­ ром . В этом отношении прием с ORA_HAS H является ненавязчивым и легковесным. П одход с хешированием/контрольной суммой может быть в значительной степени независимым от базы данных, особенно если хеш-значения или контрольные сум­ мы вычисляются вне базы данн ых. Тем не менее, выполнение вычислен и й в про­ межуточн ом звене, а не в базе данных, ведет к значительному увел ичению объема используемых ресурсов процессара и пропускной способности сети . Блокирование Блокирование (Ьlocking) происходит, когда оди н сеанс удержи вает блокировку (lock) на ресурсе , которы й запраши вается другим сеансом . В результате запрашива­ ющий сеанс окажется заблокированным - он зависнет до тех пор, пока удерживаю­ щий блокировку сеанс не освободит заблокированный ресурс. Блокирования почти всегда можно избежать. Фактически , есл и оказывается , что сеанс заблокирован в и нтерактивном приложе н и и , то вполне вероятно, что приложение содержит также ошибку потерянного обновления, возможно, даже не подозревая об этом . То есть, логика приложения содержит изъя н и в этом заключается причина блокирования. Пятью распространен н ы м и операторами D M L, которые будут вызывать блоки ­ рование В базе данн ых, я вляются I N S ERT , U P DAT E , DELET E , MERGE И S ELECT FOR U P DAT E. Решение для заблокирован ного оператора SELECT FOR U P DATE три виально: нужно просто добавить к нему конструкцию NOWAIT и больше он блокироваться не будет. Взамен приложение будет возвращать конечному пользователю сообщение о том , что строка уже заблокирована. Остальные четыре оператора D M L более инте­ ресны. Мы рассмотрим каждый из них и выясним, когда они не должны приводить к блокированию, и как исправить ситуацию, если это все же происходит. Заблокированные вставки Существует несколько ситуаций , когда оператор I N S ERT будет вызывать блоки­ рование. Наиболее распространен н ы й сценари й предусматривает наличие таблицы с первичным ключом или помещенным на нее уникальн ым ограничением и двух се­ ансов, п ытающихся вставить строку с одн им и тем же значением . Оди н сеанс будет заблокирован до тех пор, пока второй не выполнит либо фиксацию (в этом случае заблоки рованн ы й сеанс получит сообщение о наличии дублированного значения), либо откат ( в таком случае заблокированн ы й сеанс успешно завершит свою опера­ цию). Еще одна ситуация касается таблиц, связанных друг с другом ограничениями Б л окировка и за щ ел ки вани е дан ных 31 7 ссылочной целостности . Вставка строки в дочернюю табли цу может оказаться за­ блокированной, если строка, от которой она зависит, создается или удаляется . Обычно заблокированные вставки появляются в приложен иях, которые позволя­ ют конечному пользователю генерировать значение первичного кл юча/уни кального столбца. Предотвратить возни кновение такой ситуации легче всего, применя я для генераци и значен и й первичного ключа/уникального столбца последовательность или встроенную функцию S Y S _GU I D ( ) П оследовательности и S YS _ GU I D ( ) были разработаны в качестве методов генерации ключей с высокой степенью параллелиз­ ма в многопользовательской среде . В случае есл и вы не можете использовать оди н и з этих методов, и должны разреш ить конечному пользователю генерировать клю­ чи, которые могут дублироваться , можете применить описан н ы й н иже прием, кото­ рый устраняет проблему посредством устанавливаемых вручную блокировок, реали ­ зованных с помощью встроен ного пакета DBMS _LОСК. . На заметку! В следующем примере показано, как предотвратить блокирование сеансом опе­ ратора вставки из-за наличия ограничения первичного ключа или ограничения уни кальнос­ ти . Необходимо подчеркнуть, что демонстрируемый здесь способ устранения проблемы должен рассматриваться как кратковременное решение на период, пока инспектируется сама архитектура приложения. Этот подход добавляет очевидные накладные расходы и требует серьезного отношения к своей реализаци и . В правильно спроектированном при­ ложении проблема подобного рода возникать не будет (например, в параллельной среде не должны выпол няться транзакции , продолжающиеся часами ) . Такой прием следует счи­ тать последним средством и определенно не чем-то таким , что нужно делать в отношении каждой таблицы приложения просто "на всякий случай " . При выполнении операций вставки не существует строк, которые можно было бы выбрать и заблокировать; н ет н икакого способа предотвратить встав ку стро­ ки с таким же значением другими пользователям и , что заблокирует наш сеанс и вызовет ожидание на неопределенное время . И менно здесь в игру вступает пакет DBMS LOCK. Для демонстрации этого подхода м ы создадим табли цу с перви ч н ы м ключом и триггером , который будет препятствовать одновременной вставке одн их и тех же значений двумя (и более) сеансами . Три ггер будет испол ьзовать функцию DBMS_ UT I L I TY . GET HAS H_VALUE для хеширования первичного кл юча в некоторое число между О и 1 073 74 1 823 (разрешенный для применения диапазон значен и й идентифи катора блокировки в Orac1e ) . В этом примере я выбрал хеш-табл и цу с размером 1 024, т. е. мы будем хеш ировать первичные ключи в один из 1 024 разных идентификаторов блокировок. Затем с помощью функци и овмs_ LOCK . REQUE S T м ы установим монопольную блокировку н а основе этого идентификатора. В каждый момент времени это может делать только оди н сеанс, так что если другой пользо­ ватель попытается вставить в нашу табли цу строку с тем же первичным кл ючом , то выдан ный им запрос на блокировку потерпит неудачу (с сообщением о занятости ресурса). __ Н а заметку! Для усп е ш н о й ко м п иляции этого три гге ра п р и в илегия на в ы п ол н е н ие DBMS _LOCK должна быть выдана непосредственно схеме. П ривилегия на выполнение па­ кета DBMS _LOCK может не поступить из назначенной роли. 318 Глава б SCOT T @ ORA 1 2 CR1 > create t aЬ l e demo ( х int p r ima r y key ) ; ТаЬlе created . Та блица создана . SCOTT@ORA12CR1> create or rep1ace t r i gger demo_bi fer 2 before i n s e r t on demo 3 for each row 4 dec1are 5 1 1 o c k id nurnЬe r ; б resource _bu s y exception ; 7 pragma excepti on_i n i t ( r e s ou rce_bu s y , - 5 4 ) ; 8 begin 9 1 1 o c k id : = 10 dЬms_ut i 1 i ty . get_hash va 1 ue ( to char ( : new . x ) , О , 1 0 2 4 ) ; 11 i f ( dЬms_1 o c k . reque s t 12 ( id => 1_1 oc k_id , 13 1 o c kmode = > dЬms 1 o c k . x_mode , 14 t imeout => О , 15 r e 1 e a s e o n commit = > TRUE ) not i n ( 0 , 4 ) 1б then 17 r a i s e r e s o u r ce_bu s y ; 18 end i f ; 1 9 end; 20 1 Trigger created . Триггер созда н . SCOTT@ORA 1 2 C R 1 > i n s e r t into demo ( x ) va1ues ( 1 ) ; 1 row created . Теперь для иллюстрац и и перехвата этой п роблем ы блокирующей операции I N S ERT В одиноч ном сеансе М Ы используем AUTONOMOUS_TRANSACT ION , чтобы это выглядело, как если бы следующий блок кода выполнялся в другом сеансе SQL*Plus. На самом деле, если применить другой сеанс, поведение будет таким же. Вот что мы сделаем: SCOT T @ORA 1 2 C R 1 > de c 1 a r e pragшa autonoшous_transaction ; 2 3 4 5 б begin i n s e r t i n t o demo ( x ) va 1 u e s 7 1 (1) ; commi t ; end; de c 1 a r e * ERROR at 1 i ne 1 : ORA- 0 0 0 54 : resource busy and acquire with NOWAIT specified or timeout expi red ОRА- О б 5 1 2 : at " SCOTT . DEMO_B I FER" , 1 i ne 1 4 ORA- 0 4 0 8 8 : error during execut ion o f t r i gger ' SCOTT . DEMO BI FER ' ОRА- 0 б 5 1 2 : at 1 i ne 4 ОIJМБКА в строке 1 : ORA - 0 0 05 4 : ресурс занят и запрошен с указанием NOWAIT либо истек тайм - аут ORA - 0 65 1 2 : в SCOTT. DEMO_ BIFER , строка 1 4 ORA - 0 4 08 8 : ошибка в о время выполнения триггера SCOTT . DEMO BIFER ORA - 0 65 1 2 : в строке 4 Б л окировка и за щ ел ки вание дан н ых 319 Концепция заключается в извлечен и и переданного значен ия первичного ключа из таблицы, защищенной три ггером, и помеще н и и его в символьную строку. Затем с помощью функции DBMS _UT I L I T Y . GET _HAS H_VALUE для строки МОЖНО получить по большей части уникальное хеш-значение. До тех пор, пока размер хеш -таблицы меньше 1 073 74 1 823 , это значение можно блокировать в монопол ьном режиме с использованием пакета DBMS LОСК. После хеширован ия мы берем это значен ие и применяем пакет DBMS _ LOCK для запроса монопольной блокировки этого идентификатора блокировки с тайм-аутом ZERO (что обеспечивает немеменный возврат, если кто-то другой заблокировал дан ­ ное значен ие). При истечен и и тайм-аута и л и неудаче по любой причине возвраща­ ется сообщение об ошибке ORA- 0 0 0 5 4 : r e s ourc e b u s y (ORA-00054: ресурс занят) . В противном случае ничего не делается : вставка прошла успешно и блокировка не требуется . После выполнения фиксаци и нашей транзакции все блокировки , вклю­ чая размещенные этим вызовом DBMS _LOCK, будут освобожден ы . Разумеется , есл и первичный ключ таблицы имеет т и п I NT E GER, а его значение не превышает 1 миллиард, то можно не прибегать к хешировани ю и просто исполь­ зовать ч исло в качестве идентифи катора блокировки . Во избежание искусственной генерации сообщен и й о занятости ресурса из-за хе­ ширования различных строк в одно и то же ч исло придется поэкспериментировать с размером хеш-таблицы ( 1 024 в этом примере). Размер хеш -таблицы будет зависеть от приложения (дан ных) , и на него оказывает влиян ие также количество одновре­ менно выпол няемых вставок. Можно также добавить к триггеру флаг, чтобы позво­ лить пользователям включать и отключать проверку. Н апример, если м ы собираемся вставлять сотн и ил и тысячи записей, то проверку имеет смысл отключить. Блокированные слияния, обновления и удаления В интерактивном приложении - приложе н и и , которое запрашивает какие-либо данные из базы , предоставляет конечному пользователю возможность манипулиро­ ван ия ими и затем помещает их обратно в базу - блокирован н ы й запрос U P DAT E или DELETE указывает на то, что в коде , вероятно, присутствует проблема потеря н­ ного обновления . ( Если хотите , я буду называть это ошибкой в коде. ) В ы п ытаетесь выполнить операци ю U P DAT E мя строки , которую уже кто-то обновляет (другим и словами , м я строки , которую кто-то другой заблокировал ) . Проблемы бло ки рова­ ния можно избежать, применяя запрос S ELECT FOR U P DAT E NOWA I T , чтобы: • удостовериться в том , что данные не были изменены с момента их запроса ( предотвращая потерян ные обновлен ия) ; • заблокировать строку ( предотвращая блокирова н и е запроса U P DAT E ил и DELETE ) . Как обсуждалось ранее, это можно делать независимо от принятого метода бло­ кировки . И пессимистическая , и оптимистическая блокировки могут использовать запрос S E LECT FOR U P DAT E NOWA I T для Проверки отсутствия изменений В стро­ ке . Пессим истическая блокировка будет приме нять оператор S E LECT FOR U P DAT E NOWAI T немеменно после того, как пользователь сообщит о своем намерении моди­ фицировать данные. Оптимистическая блокировка будет использовать этот оператор непосредственно перед обновлением дан н ых в базе . Это не только решит проблему блокирован ия в приложении, но и устранит проблему целостности данных. 320 Глава б Поскольку запрос MERGE является просто сочетанием INSERT и U P DATE (в Oracle l Og и последующих версиях поддержи вается расшире н н ы й синтаксис оператора MERGE, включающий также DELETE), оба приема будут применяться одновременно. В заимоблокировки Взаимоблокировка (deadlock) возникает при налич и и двух сеансов, каждый из ко­ торых блокирует ресурс, требуемый другому сеансу. Н апример, взаимоблокировку легко продемонстрировать, и мея две табли цы А и В , которые содержат по одной строке . Для этого достаточ но открыть два сеанса (скажем, два сеанса SQL*Plus) . В сеансе А м ы будем обновлять табли цу А, а в сеансе В табл ицу В. Теперь при попытке обновления таблицы А в сеансе В этот сеанс окажется заблокирован ным. Сеанс А уже заблокировал данную строку. Это еще не взаимоблокировка, а про­ стая блокировка. Ситуация взаимоблокировки пока не возникла, т. к. есть шанс, что сеанс А выпол н ит фиксацию или откат и сеанс В просто п родолжит работу с этой точки . Если теперь вернуться в сеанс А и попробовать обновить таблицу В, возникнет взаимоблокировка. Оди н из двух сеансов будет выбран в качестве жертвы и вынуж­ ден будет произвести откат своего оператора. Н апример, попытка сеанса В обновить таблицу А может быть отменена с выводом сообщения об ош ибке , подобного сле­ дующему: - update а set х = х + 1 * ERROR at l i ne 1 : ORA- 0 0 0 6 0 : deadlock detected whi le wa iting for resource ОПМБКА в строке 1 : ORA - 00 0 60 : обнаружена взаимоблокировка во время ожидания ресурса Попытка обновлен ия таблицы В в сеансе А остается заблокирован ной - Oracle не будет производить откат всей транзакц и и . Откатывается только оди н из опера­ торов, участвующих во взаимоблокировке. Сеанс В по-прежнему блокирует строку в табли це В, а сеанс А терпели во дожидается освобождения этой строки . После по­ лучения сообщения о взаи моблокировке сеанс В должен принять решение о том , что делать: зафиксировать ожидающую работу в таблице В, произвести ее откат или продолжить дви гаться альтернати вным путем и выпол н ить фиксацию позже . Как только этот сеанс сделает фиксацию или откат, другой заблокированный сеанс про­ должит работу, будто бы н ичего не происходило. СУБД O racle считает взаимоблокировки настолько редки ми и необыч н ы м и , что создает трассировочн ы й файл на сервере каждый раз , когда они возн и кают. Содержимое этого трассировочного файла может выглядеть следующим образом : * * * 2 0 1 4 - 0 4 - 1 6 1 8 : 5 8 : 2 6 . 60 2 * * * SESS I ON I D : ( 3 1 . 1 8 32 1 } 2 0 1 4 - 0 4 - 1 6 1 8 : 5 8 : 2 6 . 6 0 3 * * * CLI ENT I D : ( } 2 0 1 4 - 0 4 - 1 6 1 8 : 5 8 : 2 6 . 60 3 * * * SERV I CE NАМЕ : ( SYS$US ERS } 2 0 1 4 - 0 4 - 1 6 1 8 : 5 8 : 2 6 . 6 0 3 * * * MODULE NАМЕ : ( SQL* Plus } 2 0 1 4 - 0 4 - 1 6 1 8 : 5 8 : 2 6 . 6 0 3 * * * ACTI ON NАМЕ : ( } 2 0 1 4 - 0 4 - 1 6 1 8 : 5 8 : 2 6 . 6 0 3 *** 2014-04-16 18 : 58 : 2 6 . 603 DEADLOCK DETECTED ( ORA- 0 0 0 6 0 } [ Transaction Deadl o c k ] Бл окировка и за щел киван и е данных 32 1 The following deadlock i s not a n ORACLE error . I t i s а deadlock due to user e rror in the des ign o f an app l ication or from i s suing incorrect ad-hoc SQL . The fol l owing in formation may aid in determi ning the deadl oc k : ОБНАРУЖЕНА ВЗАИМОБЛОКИРОВКА ( ORA- 00 0 60 ) [Взаимоблокировка транзакций] Следующая взаимоблокировка не является ошибкой ORACLE . Она возникла из -за пользова тельской ошибки в проектном решении приложения или по причине выща чи некорректного оператора SQL . Приведенная ниже информация может помочь в определении условий взаимоблокировки : Очевидно, что Oracle трактует эти взаимоблокировки , возникающие в приложе­ нии, как ошибку в какой-то части приложения, и в большинстве случаев это действи­ тельно так. В отличие от многих других СУБД, взаимоблокировки в Orac1e случаются настолько редко, что практически их можно считать несуществующими . Обычно для их возни кновения требуются особые, совершенно искусствен н ые условия. Н а основе собствен ного опыта я полагаю, что главной причиной возни кновения взаимоблокировок в базе данных Oracle является наличие неиндексированных вне­ шних ключей. ( Вторая по значимости причина - испол ьзование битовых и ндексов в таблицах, подвергающихся одновреме нны м обновлениям - рассматри вается в главе 1 1 .) СУБД Orac1e поместит блокировку на всю дочернюю табли цу после моди­ фикации родительской таблицы в следующих трех сценариях. • При обновлении первичного кл юча родительской таблицы (очень редкая ситу­ ация , если соблюдается правило проектирования реляционных баз дан н ых, в соответствии с которы м первичные ключи должн ы быть неизменяемы м и ) до­ черняя таблица будет заблокирована в случае отсутствия индекса на внешнем ключе. • При удалении строки родительской таблицы вся дочерняя табли ца также будет заблокирована (при отсутствии индекса на внешнем кл юче). • При слиянии с родительской табл и цей вся дочерняя таблица также будет за­ блокирована (при отсутствии и ндекса на внешнем кл юче ) . Обратите внима­ ние , что это справедливо только в версиях Orac1e9i и Orac1e 1 Og, но больше не касается Oracle 1 1 g Release 1 и последующих версий . В Oracle9i и последующих версиях эти пол н ые блокировки табли ц действуют кратковременно - т.е . их следует принимать во внимание на протяжении выполне­ ния операции D M L, а не всей транзакции . Но даже при этом они могут приводить к крупным проблемам блокировки . В качестве иллюстрации первой из названн ых ситуаций рассмотрим пример. При наличии двух таблиц, созданн ых следующим об­ разом, вначале не происходит ничего экстраординарного: EODA@ORA12CR 1 > create taЬle р ( х int prima ry key ) ; ТаЬlе created . Та блица создана . EODA@ORA1 2CR1 > create taЬle с ( х references р ) ; ТаЬlе created . Та блица создана . 322 Глава 6 EODA@ORA1 2CR1> insert into р va lues ( 1 ) ; 1 row created . 1 строка создана . EODA@ ORA12CR1> insert into р va 1ues ( 2 ) ; 1 row created . 1 строка создана . EODA@ ORA1 2CR1> commi t ; Commit comp1ete . Фиксация выполнена . EODA@ ORA12CR1> insert into с values ( 2 ) ; 1 row created . 1 строка создана . Н о при переходе в другой сеанс и попытке удалить первую родительскую запись сеанс немед11е нно оказывается заблокированным: EODA@ORA 1 2 C R 1 > de lete f r om р where х = 1 ; Это попытка блокирования всей табл и цы с перед тем , как она выполнит уда­ ление. Теперь н и какой другой сеанс не может инициировать выполнение операций DELETE, I N S E RT или U P DAT E по отношению к любой строке таблицы с (уже запу­ щенные сеансы могут продолжаться , однако запустить новы й сеанс д1IЯ изменения таблицы С не удастся ). Такая блокировка будет п роисходить также при обновлении значения первич­ ного кл юча. П оскол ьку в реляционных базах дан н ых обновление первичного клю­ ча - совершенно недопустимая операция , в общем случае эта проблема не должна возникать при обновлен иях. Тем не менее, мне приходилось видеть, что обновление первичного ключа становится серьезной проблемой , когда разработчики при меняют инструменты автоматической генерации SQL-кoдa, и эти инструменты обновля ют каждый столбец независимо от того, действительно л и он был изменен конечным пользователем. Предположим, например, что м ы пользуемся Oracle Fonns и созда­ ем стандартны й макет д11 я редактирования л юбой таблицы. По умолчан ию Oracle Forms будет генерировать операц и ю обновления , которая модифици рует каждый столбец таблицы, выбранной для отображения. Есл и мы строи м стандартный макет д11я таблицы DEPT и включаем в него все три поля, то Oracle Fonns будет вы полнять следующую команду всякий раз, когда мы изменяем любой столбец таблицы DEPT: upda te dept set deptno= : 1 , dname= : 2 , loc= : З where rowid= : 4 В этом случае , если таблица ЕМР и меет внеш н и й ключ, ссылающийся на DEPT, а и ндекс на столбце DE PTNO таблицы ЕМР отсутствует, то вся таблица ЕМР будет за­ блокирована во время обновления DEPT . За ситуациями подобного рода необходимо внимательно следить, если вы и меете дело с любыми инструментами , которые гене­ рируют SQL-кoд автоматически . Несмотря на то что значение первичного ключа не изменяется , дочерняя табл ица ЕМР будет заблокирована после выполнения приве­ деиного ранее SQL-oпepaтopa. В случае применения Oracle Forms решение заклю­ чается в установке свойства U P DATE CHANGE D COLUMN S ONLY (обновлять только из­ мененные столбцы) этой таблицы в YES (да). Тогда Oracle Fonns будет генерировать оператор U P DAT E , которы й включает только измененные столбцы (но не первичный ключ) . Б локиров ка и за щел ки ван и е данн ы х 323 Проблем ы, вытекающие из удаления строки в родительской таблице, встречают­ ся нам ного чаще . Как уже демонстрировалось, при удален и и строки из таблицы Р дочерняя таблица с блокируется на период действия операции D M L, предотвращая другие обновления с в течен ие выполнения транзакци и ( конечно, п редполагается , что ни кто другой не изменял табли цу с; в такой ситуации операция удаления будет ожидать) . И менно здесь возн икают проблемы блоки рования и взаи моблокировки . Блокировка всей таблицы С значительно снижает п оказатель параллелизма базы данных - до точки , когда никто н ичего не сможет изменить в табли це с. Вдобавок увеличи вается вероятность воз н и кновения взаимоблокировки , т. к. оди н пол ьзова­ тель владеет огромн ы м объемом данных до тех пор, пока не вы полнит фиксацию. Теперь вероятность блоки рования на табли це с какого-то другого сеанса знач и ­ тельно в ы ш е ; любой сеанс, пытающийся модифицировать с , будет заблокирован . Следовательно, начинает появляться множество сеансов, удерживающих ряд сущес­ твующих блокировок на других ресурсах, которые оказываются заблокированными в базе данных. Если любой из этих заблокированных сеансов блокирует ресурс, так­ же требуемый текущему сеансу, возникает взаимоблокировка. В этом случае взаимо­ блокировка вызвана текущим сеансом, препятствуя доступу к значительно больше­ му числу ресурсов ( в рассматриваемой с итуации ко всем строкам одной таблицы), чем требуется в действител ьности. Когда кто-либо жалуется на взаимоблокировки в базе дан ных, я советую запустить сценарий, отыскивающий неиндексированные внешние ключ и ; в 99% случаев удается найти табли цу, которая н арушает работу. П ростая индексация внешнего ключа устраняет взаимоблоки ровки , равно как и массу других проблем конкуренции. В приведеином н иже примере п оказано, как использовать этот сценарий для нахождения неиндексированного внешнего ключа в таблице с: EODA@ORA12CR1 > column col wmns format а30 word_wrapped EODA@ORA1 2CR1> col wmn taЬle_naтe format а 1 5 word_wrapped EODA@ORA1 2CR1 > colwmn cons traint_name format a l 5 word_wrapped EODA@ ORA12CR1> select taЬle_naтe , constraint_name , cname 1 1 1 nvl 2 ( cname2 , 1 , 1 1 l cnaтe2 , nul l ) 1 1 2 nvl2 ( cnaтe3 , 1 , 1 l l cnaтe 3 , nul l ) 1 1 nvl2 ( cnaтe 4 , 1 , 1 l l cnaтe 4 , nul l ) 1 1 3 nvl2 ( сnате 5 , 1 , 1 1 1 сnате5 , nul l ) 1 1 nvl2 ( сnате б , 1 , ' 1 1 сnате б , nul l ) 1 1 4 nvl 2 ( cname7 , 1 , 1 1 l cnaтe 7 , null ) 1 1 nvl 2 ( cname 8 , ' , 1 1 l cnaтe8 , nul l ) 5 colwmns б 7 from ( select b . taЬl e_naтe , b . constraint_name , 8 9 max ( decode ( pos i tion , 1 , col wmn_name , null ) ) сnате 1 , max ( decode ( pos i t i o n , 2 , colwmn_name , null ) ) сnате2 , 10 max ( decode ( pos i t ion , 3 , col wmn_nате , null ) ) сnате 3 , 11 max ( decode ( pos i t i o n , 4 , col wmn_nате , null ) ) сnате 4 , 12 max ( decode ( pos i t i o n , 5 , col wmn_nате , nul l ) ) сnате5 , 13 max ( decode ( pos ition, б , col wmn_nате , null ) ) сnате б , 14 max ( decode ( pos ition, 7 , col wmn_nате , null ) ) сnате 7 , 15 max ( decode ( pos ition, 8 , colwmn_name , null ) ) cname 8 , 16 count ( * ) col cnt 17 from ( s elect s ubs tr ( taЫe_naтe , 1 , 3 0 ) taЬle_nате , 18 subs t r ( con s t raint_naтe , 1 , 3 0 ) con s t ra int_naтe , 19 substr ( colwmn_naтe , 1 , 3 0 ) col wmn_nате , 20 pos i t i on 21 324 Гл ава 6 22 from user_cons_columns ) а , 23 user con s t raints Ь 24 whe re a . con s t raint nате = b . constraint nате and b . constraint_type = ' R ' 25 26 group Ьу b . taЫ e_name , b . constraint name 27 cons 28 whe re col cnt > ALL 29 ( se lect count ( * ) f rom user i nd columns i , 30 ui user i ndexes 31 32 where i . taЫe name = cons . taЫe name and i . column name in ( cname l , cname2 , cname 3 , cname 4 , 33 cname 5 , cname 6 , cname7 , cname 8 ) 34 and i . column_pos ition <= cons . col_cnt 35 and ui . taЫe nате = i . taЫe name 36 and ui . i ndex nате = i . index name 37 and ui . index_type IN ( ' NORМAL ' , ' NORМAL/REV ' ) 38 39 group Ьу i . i ndex_nате 40 41 1 - - ТАВLЕ NАМЕ CONSTRAINT NАМЕ COLUMNS с SYS С0 0 6 1 4 2 7 Х Сценар и й работает с огран ичениями внеш него ключа, которые содержат до восьми столбцов (есл и количество столбцов больше, возможно, проектное решение требует пересмотра) . Он н ачинается с построен ия встроенного представления CONS в предыдущем запросе . Это встроенное представление преобразует соответствую­ щие имена столбцов ограничения из строк в столбцы, давая в итоге дЛЯ каждого ограничения строку, которая содержит до восьми столбцов, имеющих имена как у столбцов в ограничени и . Кроме того, предусмотрен столбец COL_CNT, содержащий кол ичество столбцов в самом ограничении внеш него ключа. Для каждой строки , возвращенной из встроен ного представления, выполняется коррелированный под­ запрос, которы й провернет все и ндексы обрабатываемой в данный момент таблицы. Он подсчитывает количество столбцов в индексе, которые соответствуют столбцам в ограничении внеш него ключа, и затем группирует их по имени индекса. Таким образом , подзапрос генерирует набор ч исел , каждое из которых пред­ ставляет количество совпадающих столбцов в каком-либо и ндексе обрабатываемой таблицы. Если исходное значение COL CNT больше всех эти х ч исел, то таблица не содержит ни одн ого и ндекса, поддерживающего это ограничение. Есл и значение COL CNT меньше всех этих чисел , то таблица содержит, по крайней мере , оди н ин­ декс, которы й поддержи вает данное ограничение. Обратите вни мание на примене­ ние функции NVL 2 , предназначен ной для преобразования списка имен столбцов в список с разделителям и-запяты м и . Фун кция NVL2 прин имает три аргумента: А, В и с. Есл и аргумент А не равен nul l , функция возвращает аргумент В; в противном случае она возвращает аргумент с. В этом запросе предполагается , что владелец ог­ раничения я вляется также владельцем таблицы и и ндекса. Если таблицу индекси­ ровал другой пол ьзователь или если она принамежит другой схеме (обе ситуации встречаются крайне редко), то сценарий будет работать некорректно. _ _ Б л окировка и защ ел ки ван и е дан н ых 325 В предыдущем сценар и и также производится п роверка, имеет ли и ндекс тип В-дерева (NORМAL или NORМAL / REV). Причина в том, что битовый индекс на столб­ це внешнего ключа не предотвращает возни кновение проблем ы блокировки. На заметку! В средах хранил и щ данных общепринято создавать битовые и ндексы на стол­ бцах внешних ключей таблицы фактов. Однако в таких средах загрузка дан н ых обычно делается в упорядоченной манере с помощью запланированных п роцессов ЕТL ( extract, traпsform, load - извлечение, преобразование, загрузка) и , следовательно, не будет стал­ киваться с ситуацией вставки в дочернюю табли цу в одном процессе и параллельного удаления из родительской табли цы в другом п роцессе (то, что можно встретить в п рило­ жении OLTP). Таким образом , предыдущий сценарий показывает, что таблица с имеет внешн и й ключ на столбце х , но без и ндекса. Создавая на столбце х и ндекс со структурой В-дерева, мы можем полностью устран ить эту проблему блокирования . Кроме бло­ кировки этой таблицы неиндексированный внешний ключ может также пораждать проблемы в перечисленных н иже случаях. • При наличии конструкци и O N D E L E T E CAS CADE и неиндексированной до­ черней таблицы. Например, предположим , что ЕМР - это дочерняя таблица таблицы DE PT. Оператор DELETE DE PTNO= l O должен выпол нить операцию ON DELETE CASCADE В таблице ЕМР. Если столбец DE PTNO В ЕМР не и ндексиро­ ван , то каждое удаление строки из таблицы DEPT будет приводить к полному просмотру таблицы ЕМР. Скорее всего, этот пол н ы й просмотр нежелателен, и в случае удален ия множества строк из родительской таблицы дочерняя таблица будет просматриваться при каждом удален и и строки из родительской таблицы. • При выполнении запроса дочерней таблицы из родительской. Снова обратим­ ся к примеру с таблицами EMP/DE PT. Запрос таблицы ЕМР в контексте столбца DEPTNO я вляется довольно распространенной ситуацие й . При частом запуске следующего запроса (скажем , при создании отчета) , вы обнаружите , что от­ сутствие индекса будет замедлять выполнение запросов: select * frorn dept , ernp where ernp . deptno = dept . deptno and dept . deptno = : Х ; А когда не следует и ндексировать внешний ключ? В общем случае и ндексация не требуется при удовлетворен и и перечисленных н иже условий. • Отсутствие удалений из родительской таблицы. • Отсутствие обновлений значения уникальногоjпервичного кл юча родитель­ ской таблицы (при этом следует следить за неумышлен н ы м и обновлениями первичного ключа со сторон ы инструментов) . • Отсутствие соединений родительской таблицы с дочерней таблицей (подобных соеди нению DEPT и ЕМР). Если удовлетворен ы все три условия , можете смело отказываться от и ндекса он не нужен. Если соблюдается любое из переч исленных условий , помните о воз­ можных последствиях. Это оди н из тех редких случаев, когда СУБД Oracle склонна чрезмерно блокировать данные. 326 Глава 6 Э скалация блокировок При эскалации блокировок система снижает уровень их детализации . Примерам может служить преобразование ста блоки ровок на уровне строк в единствен ную блокировку на уровне таблицы. В этом случае мы используем одну блокировку для блокирования всего и , как правило, блокируем значительно больше дан ных, чем ра­ нее. Эскалация блокировок часто применяется в базах данн ых, где блокировки счи­ таются дефицитны м ресурсом и причиной накладных расходов, которых стремятся избежать. Н а заметку! СУБД O racle н и когда н е выпол няет эскалацию блокировок. Ни при каких условиях. СУБД Oracle н икогда не предприн имает эскалацию блокировок, но практикует преобразование или продвижение блокировок - термины, которые часто путают с эскалацией блокировок. На заметку! Понятия преобразование блокировки и продвижение блокировки являются си­ нонимам и . В Oracle этот процесс обычно называется преобразованием блокировки ( lock conversion). СУБД Oracle будет устанавливать блокировку на минимал ьно возможном уров­ не (т.е. испол ьзовать наименее ограничивающую блокировку) и при необходимости преобразовывать ее в блокировку более ограничивающего уровня . Н апример, при выборе строки в табли це с указанием конструкции FOR U P DAT E создаются две бло­ кировки . Одна помещается на выбранную строку или строки (и эта блокировка бу­ дет монопольно й ; никто другой не сможет заблокировать эту конкретную строку в монопольном режиме) . Вторая блокировка, ROW S HARE TABLE, помещается на саму табли цу. Это предотвратит блокирование таблицы в монопольном режиме другими пол ьзователям и , что будет препятствовать, например, изменению ими структуры таблицы. Другой сеанс может модифицировать любую другую строку в этой таблице безо всяких конфликтов. При наличии бло кированной строки в таблице будет раз­ решено выпол нять максимально возможное количество команд. Эскалация блокировки - это не " функциональная возможность" базы данных. Она не я вляется желательным атрибутом. Тот факт, что база дан н ых поддержива­ ет эскалацию блокировок, подразумевает наличие некоторых накладных расходов, присущих механ изму блокирован ия , и выполнение знач ител ьной работы по уп ­ равлению сотням и блокировок. Н акладные расходы , связанные с l блокировкой и l м иллионом блокировок, в Oracle одинаковы - они нулевые. Ти п ы блокировок Н иже описаны три основных класса блокировок в Oracle. • Блокировки DML. Здесь под D M L понимается Data Manipu/ating Language (язык манипулирования данными). В общем случае это означает операторы S ELECT, I N S ERT, U P DATE , MERGE и DELETE. Блокировки DML представляют собой ме­ ханизм , который обеспечивает паралл ельное изменение данных. Блокировками Б локировка и за щ ел ки вание дан ных 327 D М L будут, к примеру, блокировки определен н ых строк данн ых или блокиров­ ка на уровне таблицы, которая блокирует каждую строку в таблице. • Блокировки DDL. Здесь DDL означает Data Definition Language (язык определе­ н ия дан н ых) и охватывает операторы CREAT E, ALT ER и т.д. Блокировки D D L защищают определение структуры объектов. • Внутренние блокировки и защелки. В Oracle эти бло кировки применяются для защиты внутрен н их структур данных. Н апример, коrда СУБД Oracle выполняет разбор запроса и генерирует оптимизированный план запроса, она будет защел­ кивать библиотечн ы й кеш , чтобы поместить в него этот план для использова­ ния другими сеансами . Защелка (latch) это легковесный н изкоуровневый ме­ ханизм сериализации , применяемый Oracle, которы й функционирует подобно блокировке. Пусть терми н легковесны й не вводит вас в заблуждение; вы уви ­ дите , что защелки являются общей причиной конкуренции в базе данных. Они являются легковесными в смысле реализации , но не в смысле воздействия . - Те перь мы более подробно рассмотри м конкретные типы блокировок внутри этих основных классов и последствия их использования . Типов блокировок намного больше , чем можно охватить в одной главе. В последующих разделах раскрывают­ ся самые распространенные и удерживаемые в течение продолжительного периода блокировки . Другие тип ы блокировок обычно устанавливаются на оче н ь короткие промежутки времен и . Б локировки DML Блокировки D M L позволяют гарантировать, что в каждый момент времени из­ менять строку может только оди н пользователь, и никто другой не сможет удалить таблицу, с которой производится работа. Во время этой работы Oracle будет само­ стоятельно помещать эти блокировки более или менее прозрачн ы м образом . Блокировки ТХ (транзакций) Блокировка ТХ выдается , когда транзакция инициирует свое первое изменение. В этот момент транзакция автоматически начинается (явно запускать транзакци ю в Oracle не требуется ) . Эта блокировка удержи вается до тех пор, пока транзакция не выполнит операцию COMM I T ил и RO LLBACK. Она выступает в качестве механизма организации очереди , чтобы другие сеансы могл и дождаться завершения транзак­ ции . Каждая модифицируемая или обрабатываемая с помощью S ELECT FOR U P DAT E строка в транзакци и будет указы вать на блокировку ТХ, связанную с этой транзак­ цией. Хотя такой подход выглядит затратным в смысле ресурсов, на самом деле это не так. Чтобы все стало понятным, необходимо и меть кон цептуальное представле­ ние о том , где н аходятся блокировки и как они управляются . В Oracle блокировки хранятся в виде атрибута данных (обзор формата блокировок Oracle представлен в главе 1 0) . В Oracle отсутствует традиционн ы й диспетчер блокировок, которы й вел бы длинный список всех строк, заблокированных в системе. М ногие другие базы дан ных располагают таким диспетчером, поскольку в их средах блокировки явля­ ются дефицитным ресурсом , за расходом которого необходимо следить. Чем больше блокировок применяется , тем большим объемом ресурсов эти системы должны уп ­ равлять, поэтому вовсе не удивительно, что эти системы беспокоятся о том , чтобы количество используемых блокировок не было сли ш ком большим. 328 Глава 6 В базе дан н ых с традиционным основанн ы м на памяти диспетчером блокировок процесс блокировки строки предусматривает выполнение следующих действий. 1 . Найти адрес строки , которую нужно заблокировать. 2. Установить связь с диспетчером блокировок (требуется сериализация , т. к. он представляет собой общую структуру в памяти) . 3 . Заблокировать список. 4. Выполнить поиск в списке, чтобы выяснить, не блокирует ли эту строку кто­ то друтой. 5 . Создать в списке новую зап ись, свидетельствующую том , что вы блокируете данную строку. 6. Разблокировать сп исок. Теперь, когда строка заблокирована, ее можно модифицировать. Позже, после фи ксации изменени й , процедура должна быть продолжена, как описано н иже. 1 . Снова установить связь с диспетчером блокировок. 2. Заблокировать список. 3. П росмотреть список и освободить все свои блокировки . 4. Разблокировать список. Как видите , чем больше блокировок получено, тем больше времени тратится на выпол нение этой операции , как до, так и после изменения данн ых. В Orac1e про­ цесс выглядит по-друтому. 1 . Найти адрес строки , которую нужно заблокировать. 2. П ерейти к этой строке. 3 . Заблокировать строку прямо здесь - по местоположен и ю строки, а не в бол ьшом списке где-то в друтом месте (с ожиданием завершения блокирую­ щей транзакци и , есл и строка уже заблокирована, если тол ько не применяется опция NOWAIT). Вот и все. П оскольку блокировка хранится как атрибут данных, Orac1e не нуЖДа­ ется в традиционном диспетчере блокировок. Транзакция просто обратится к дан­ н ы м и заблокирует их (есл и они уже не заблокирован ы ) . И нтересно, что при об­ ращении к данн ы м они могут выглядеть заблокированными, даже если это не так. При блокировани и строк в Orac1e строка указывает на копию идентификатора тран­ закции , хранящуюся с блоком, который содержит данные, а когда блокировка осво­ бождается, этот идентификатор транзакции остается . Он уникален для транзакции и представляет номер сегмента отката, слот и номер последовательности. Обязанность по уведомлению друтих сеансов о владе н и и эти ми данн ыми (не всеми дан ными в блоке , а только одной изменяемой строкой) возлагается на блок, содержащи й дан­ ные. Когда поя вляется другой сеанс , он обнаружи вает идентификатор блокировки и, учитывая , что этот идентификатор представляет транзакцию, может быстро вы­ яснить, активна ли по-прежнему транзакция, удерживающая блокировку. Если бло­ кировка не активна, сеансу разрешается доступ к данным. Если блокировка все еще активна, сеанс запросит уведомления об освобожден и и этой блокировки . Таким об­ разом, мы имеем дело с механизмом организации очереди : сеанс, запрашивающий Бл оки р о вка и за щ елки ван и е данных 329 блокировку, будет помещен в очередь для ожидан ия завершения этой транзакц и и , после чего о н получит данные. Н иже приведен небольшой пример, демонстрирующий происходя щее посредством трех таблиц V$ . • V$TRANSACT ION, которая содержит записи для каждой активной транзакции. • V$ SESS ION, отображающая сеансы, в которые бьm произведен вход. • V$ LOCK, которая содержит записи для всех находящихся в очереди удерживае­ мых блокировок, а также для сеансов, ожидающих освобожден ия блокировок. В этом предстамении вы не увидите строк для каждой строки , заблокирован­ ной сеансом . Как бьmо указано ранее, общего списка блокировок на уровне строк попросту не существует. Если сеанс имеет одну заблокированную строку в таблице ЕМР, то в предстамении V$ LOCK будет присутствовать одна строка для этого сеанса, отражающая данный факт. Если сеанс имеет миллионы заблоки­ рован н ых строк в табли це Е М Р , то предстамение V$ LOCK по-прежнему будет содержать только одну строку для такого сеанса. П редстамение показывает, ка­ кими помещенными в очередь блокировками располагают отдельные сеансы. Давайте сначала получим копии табли ц ЕМР и DE PT. Если они уже есть в вашей схеме, замените их следующими определениями: EODA@ORA12 CR1 > create taЬle dept 2 as select * from s cott . dept ; ТаЬlе c reated . Таблица создана . EODA@ORA12CR1> create taЬle emp 2 as select * from s cott . emp ; ТаЬlе created . Таблица создана . EODA@ORA12CR1> alter table dept 2 add cons traint dept_pk 3 prima ry key ( deptno ) ; Table altered . Таблица изменена . EODA@ORA12CR1> alter table emp 2 add cons traint emp_p k 3 primary key ( empno ) ; Table al tered . Таблица изменена . EODA@ORA12CR1> alter table emp 2 add constraint emp_fk_dept 3 foreign key ( deptno ) 4 refe rences dept ( deptno ) ; Table altered . Таблица изменена . EODA@ORA12CR1> create i ndex emp_deptno idx 2 on emp ( deptno ) ; Index created . Индекс создан . 330 Глава 6 Теперь запустим транзакцию: EODA@ ORA1 2CR1 > update dept 2 set dname = initcap ( dname ) ; 4 rows updated . 4 строки обновлено . Давайте выясни м состояние системы в текущий момент. В этом примере пред­ п олагается , что систем а я вляется однопол ьзовател ьско й ; в проти вном случае представление V$ T RAN SAC T I ON может содержать много строк. Но даже в систе­ ме с единствен н ы м пользователем не уди вляйтесь, есл и увидите в представлении V $ T RANSACT I ON более одной строки , т. к. многие фоновые процессы Oracle также могут выполнять транзакции . EODA@ ORA 1 2 CR1 > se lect use rname , v$lock . s id, 2 3 t runc ( id1 /powe r ( 2 , 1 6 ) ) rbs , 4 bitand ( id 1 , to_numЬer ( ' f f f f ' , ' хххх ' ) ) +О s l o t , id2 seq, 5 lmode , 6 7 reques t 8 from v$ l o c k , v $ s e s s ion 9 where v$ loc k . t ype = ' ТХ ' 10 and v$ lock . s id = v$ s e s s i on . s id 11 and v$ s e s s ion . use rname = USER; USERNAМE SID RВS S LOT SEQ LМODE REQUEST EODA 22 2 27 21201 6 о EODA@ ORA1 2CR1 > select X I DUSN , XI DS LOT , XI DSQN from v$trans act ion ; X I DUSN XI DS LOT XI DSQN 2 27 21201 Особы й и нтерес здесь представляют описанн ые н иже моменты . • В табли це V$ LOCK значение LMO DE равно 6 , а номер запроса - О . Согласно оп редел е н и ю табли ц ы V$ L O C K в руководстве O racle Database Reference (Справоч н и к по базе данных Oracle) , значен и е LMO D= 6 представляет моно­ польную блокировку. Значение О запроса свидетельствует об отсутствии запро­ са и наличии блокировки . • Эта табли ца содержит только одну строку. Таблица V$ LOCK является скорее таблице й очереди , чем табли це й блокировок. М ногие ожидают увидеть в ней четыре строки , поскольку есть четыре заблокированных строки. Однако следу­ ет помнить, что Oracle не хранит общий список всех заблокированн ых где-либо строк. Чтобы выяснить, заблокирована ли строка, необходимо перейти к ней . • Я извлек столбцы I D l и I D 2 и провел н ад н и м и ряд манипуляций . СУБД Oracle необходимо бьuю сохранить три 1 6-битных числа, но для этого имелось только два столбца. Поэтому первый столбец, I D l , содержит два числа из трех. Деление на 2 л 1 6 посредством t runc ( idl /powe r ( 2 , 1 6 ) ) rbs и маскирование старш их разрядов с помощью bi t and ( i d l , to _numЬ e r ( 1 f f f f 1 , 1 хххх ' ) ) + О s l ot позволяет получить два числа, скрытые в этом одном числе . 331 Б ло кировка и за щ ел ки ван и е данн ы х • Значения RB S , S LOT и S E Q соответствуют и нформации из V $ T RAN SAC T I ON. Они представляют идентификатор транзакции . Теперь запустим еще оди н сеанс с использованием того же самого имени пол ьзо­ вателя , обновим несколько строк в таблице ЕМР, а затем попытаемся обновить таб­ лицу DEPT: EODA@ORA12CR1 > update emp set ename = uppe r ( ename ) ; 1 4 rows updated . 1 4 строк обновлено . EODA@ORA1 2CR1 > update dept set deptno = deptno- 1 0 ; М ы заблокировали этот сеанс. Если снова запустить запросы к V$ , м ы увиди м следующий вывод: EODA@ORA1 2CR1 > se1ect use rname , v$ 1oc k . s i d , 2 trunc ( id1 /powe r ( 2 , 1 б ) ) rbs , 3 bi tand ( id1 , to_numЬe r ( ' f f ff ' , ' хххх ' ) ) + О s l ot , 4 5 id2 seq, lmode , б 7 reque st 8 from v$ 1oc k , v$ s e s s ion 9 where v$ 1oc k . type = ' ТХ ' 10 and v$ lock . sid = v$ s e s s ion . s i d 11 and v$ sess ion . use rname = USER; USERNAМE RВS SID 2 2 8 17 22 17 EODA EODA EODA S LOT SEQ LМODE REQUEST -------- ------- --------- 27 27 17 21201 21201 21403 о б б б о о EODA@ORA12CR1 > se 1ect X I DUSN , XI DSLOT , XI DSQN from v$transaction ; X I DUSN ---------- 2 8 XI DSLOT ---------- 27 17 XI DSQN 21201 21403 ---- ----- Здесь мы видим, что началась новая транзакция с идентификатором транзакции (8, 1 7 ,2 1 403 ). На этот раз новый сеанс с S I D= 1 7 и меет две строки в табли це V$ LOCК. Одна строка представляет блокировки , которым и он владеет (где LMOD= б ) . К сеансу также относится строка, в которой столбец REQUE S T и меет значение б . Это запрос монопольной блокировки . И нтересно отметить, что значения RBS/S LOT/S EQ в дан­ ной строке запроса я вляются идентификатором транзакции держателя блокировки . Транзакция с S I D= 7 0 3 блокирует транзакцию с S I D= 7 . Те же сведен ия можно вы­ вести в более наглядном виде, просто выполнив рефлексивное соединение (se1f-join) для представления V$ LOCK: EODA@ ORA12CR1 > select 2 ( select use rname from v$ s e s s ion where s i d=a . s i d ) Ьlocke r , 3 a . sid, 4 ' is Ьlocking ' , 5 ( s elect use rname from v$ s e s s i on where s id=b . s i d ) Ьloc kee , б b . sid 332 Глава 6 7 8 9 10 11 from v$lock а , v$ lock Ь where a . Ьlock = 1 and Ь . request > О and a . id1 = b . id1 and a . id2 = b . id2 ; BLOCKER SID ' I SBLOCKING ' BLOCKEE SID EODA 22 i s Ьlocking EODA 17 Если теперь м ы выпол н и м фиксацию первоначальной транзакции ( S I D= 2 2 ) и повторно запустим запрос блокировки , то обнаружим, что строка запроса исчезла: EODA@ORA 1 2 CR1 > select use rname , v $ l oc k . s i d , 2 3 t runc ( id1 /powe r ( 2 , 1 6 ) ) rbs , 4 bi tand ( id1 , to_numЬer ( ' f ff f ' , ' хххх ' ) ) + О s lot , 5 id2 seq, lmode , 6 7 reque st 8 from v$ lock, v$ s e s s ion 9 where v$ lock . type = ' ТХ ' 10 and v$ lock . s id = v $ s e s s ion . s id 11 and v$ s e s s ion . username = USER; USERNAМE SID RBS S LOT SEQ LМODE REQUEST EODA 17 8 17 21403 6 о EODA@ ORA1 2 CR1 > select X I DUSN , XI DSLOT , XI DSQN from v$ trans act ion ; X I DUSN XI DSLOT X I DSQN 8 17 21403 Строка запроса исчезла сразу же после того, как другой сеанс снял свою блоки­ ровку. Эта строка запроса и грала роль механизма организации очереди. База данных может пробуждать блокированные сеансы немедленно после завершения транзак­ ции . Существуют значительно более наглядные способы отображен ия информаци и с помощью разнообразных инструментов с графическим пользовательским интер­ фейсом, но при крайней необходимости наличие знани й о табли цах, которые следу­ ет просматри вать, очень полезно. Тем не менее , прежде чем можно будет заявлять о хорошем понимании работы блокировки строк в Oracle, нужно рассмотреть последнюю тему: каким образом ин­ формация о блокировках и транзакциях управляется с самими данными. Это часть дополнительного пространства блока. В главе 1 0 мы погрузимся в детали формата блока, но пока достаточно сказать, что в верхней части блока базы данных нахо­ д ится определен н ое дополн ител ьное п ространство, в котором хранится таблица транзакций для этого блока. Табл и ца транзакций содержит по одной записи для каждой реальной транзакц и и , которая блокирует какие-то данные в блоке. Размер этой структуры управляется двумя параметрами физических атрибутов в операторе CREATE для объекта. • I N I T RANS . Н ачальн ы й заранее определенный размер этой структуры . По умол­ чани ю значение этого параметра равно 2 для индексов и таблиц. Б л окировка и за щ ел ки ван и е дан ных • 333 MAXT RAN S . М аксимальный размер, до которого может расти эта структура. П о умолчанию максимальное значение этого п араметра равно 255, а м и ни ­ мальное - 2 . В Oracle 1 O g и последующих версиях эта настройка обьявлена устаревшей, поэтому она больше не применяется . В этих выпусках значение МAXTRANS всегда равно 255. По умолчанию каждый блок нач инает свое существование с двумя слотами тран­ закций. Количество одновременно активных транзакций, которые когда-либо могут находиться в блоке, ограничено значением МAXTRANS и доступн ы м пространством в блоке . При отсутствии в блоке пространства, достаточного мя увеличен ия этой структуры, достичь 255 одновременно выполняемых транзакций может быть невоз­ можно. М ы можем искусственно продемонстрировать, как это работает, путем создания таблицы с множеством строк, упакованных в единственный блок, так чтобы блок оказался практически полным с самого начала; после первоначальной загрузки дан ­ н ы х в н е м останется очень м ал о пространства. Присутствие этих строк ограничит пределы роста таблицы транзакци й из-за нехватки места. Я использовал размер бло­ ка в 8 Кбайт и тестировал этот конкретн ый пример во всех версиях - от Oracle9i Release 2 до Oracle 1 2с Release 1 - с тем и же самыми результатами (таким образом , если размер блока у вас составляет 8 Кбайт, то вы должны быть способны воспроиз­ вести пример). Начнем с создан ия упакованной таблицы. Я пробовал разные мины данных, пока не добрался до этого довольно специфичного случая : EODA@ORA12CR1 > create taЬle t 2 ( х int pr imary key , у varchar2 ( 4 0 0 0 ) 3 4 ) 5 1 ТаЬlе created . Таблица создана . EODA@ORA12CR1> insert into t ( х , у ) 2 select rownum, rpad ( 1 * 1 1 1 4 8 1 1 * 1 ) from dual 3 4 connect Ьу leve l <= 4 б ; 4 6 rows created . 4 б строк создано . EODA@ORA12CR1> select length ( y ) 1 2 dЬms rowi d . rowid Ьlock_numЬer ( rowid ) Ьl k 1 3 count ( * ) 1 min ( x ) l max ( x ) from t 4 5 group Ьу length ( у ) dЬms rowid . rowid_Ьlock_numЬer ( rowid) ; 1 LENGTH ( Y ) BLK COUNT ( * ) MIN ( X ) МАХ ( Х ) 148 23470 46 1 46 Итак, таблица имеет 4 6 строк, причем все находятся в одном и том ж е блоке . Я выбрал мину 1 48 символов, поскольку если бы мина была на 1 символ больше, то мя хранения тех же 46 записей понадобилось бы два блока. Теперь необходи м способ, который позволит посмотреть, что произойдет, когда множество транзак­ ций попытаются одновременно блокировать данные в этом единственном блоке . 334 Глава б Для этого м ы снова воспользуемся AUTONOMOUS T RANSAC T I ON, чтобы можно было обойтись одни м сеансом и не запускать несколько параллельных сеансов SQL*Pius. Наша хранимая процедура заблокирует строку в табли це по первичному ключу, на­ ч иная с его значен ия 1 ( первая вставленная запись) . Если процедура получит блоки­ ровку на этой строке без необходимости ожидания (т.е. не будет блокирована) , она просто увеличит значение первичного кл юча на 1 и посредством рекурсии сделает все это еще раз. То есть второй вызов попытается заблокировать запись 2, третий вызов - зап ись 3 и т.д. Есл и процедуре п ридется ждать, она сгенерирует ош ибку ORA-00054 (ресурс занят) и будет выведено сообщение " locked out trying to select row <primary key value> " (блокировка при попытке выбора строки <значение первично­ го кл юча>). Это указывает на то, что слоты транзакций в этом блоке исчерпались до блокировки всех строк. С другой стороны , если мы не найдем никакой строки для блокировки, это означает, что мы уже заблокировали каждую строку данного блока; в таком случае выводится сообщение об успешном выполнении (означающее, что табл и ца транзакци й в заголовке блока сможет расти , чтобы уместить все транзак­ ции ) . Н иже приведен код этой хранимой процедуры: EODA@ORA12CR1> create or replace procedure do_update ( p_n in numЬer 2 as 3 pragma autonomous_transaction ; 4 l_rec t % rowtype ; resource_busy exception ; 5 pragma excepti on_init ( resource_bu s y , - 5 4 ) ; 6 7 begin s e lect * 8 9 into 1 rec from t 10 11 where х = p_n 12 for update NOWAI T ; 13 do_update ( p_n+ l ) ; 14 15 commi t ; 1 6 exception 17 when resource_bus y 1 8 then 19 dЬms output . put_l ine ( ' locked out trying t o se lect row ' 1 1 p_n ) ; commi t ; 20 2 1 when n o data found 22 then dЬms_output . put_l ine ( ' we finished - n o proЬlems ' ) ; 23 24 commi t ; 2 5 end; 26 1 Procedure created . Процедура создана . Вся магия сосредоточена в строке 1 4 , где процедура рекурсивно вызывает себя с новым значением первичного ключа для многократного блокирования . Если вы запустите эту процедуру после наполнения таблицы 1 48-символьн ыми строками, то должны будете н аблюдать следующее: Б л окировка и за щ елки вание данных 335 EODA@ORA12CR1> ехес do_update ( 1 ) ; locked out trying to se lect row 3 8 PL/ SQL procedure s ucce s s fu l l y comp leted . блокировка при попытке выбора строки 38 Процедура PL/SQL успешно завершена . Этот вывод показывает, что мы смогл и заблокировать 37 строк, но на 38-й строке слоты транзакци й исчерпались. К данному блоку одновременно могут обращаться максимум 37 транзакци й . Если мы повторим пример со строкой чуть меньшего раз­ мера, то все пройдет удачно: EODA@ORA12CR1> truncate taЬle t ; ТаЬlе truncated . Та блица усечена . EODA@ORA12CR1> insert into t ( х , у ) 2 select rownum, rpad ( ' * ' , 1 4 7 , ' * ' ) from dual 3 4 connect Ьу level <= 4 б ; 4 6 rows created . 4 6 строк создано . EODA@ORA12CR1> select length ( y ) , 2 dЬms rowid . rowid Ьlock_numЬe r ( rowi d ) Ь l k , count ( * ) , min ( x ) , max ( x ) 3 from t 4 5 group Ьу length ( у ) , dЬms _rowld . rowid Ьlock numЬer ( rowid ) ; _ LENGTH ( Y ) BLK COUNT ( * ) MIN ( X ) МАХ ( Х ) 147 23470 46 1 46 EODA@ORA12CR1> ехес do_update ( 1 ) ; we finished - no proЬlems PL/ SQL procedure succe s s fu l l y completed . . завершено - проблемы не в озникали Процедура PL/SQL успешно завершена . На этот раз задача решена успешно - разница в единственный байт сработала! В данном случае наличие 46 дополнительных байтов свободного пространства в бло­ ке (каждая из 46 строк на оди н байт меньше) позвол ила иметь в блоке, по крайней мере , на 9 активных транзакци й больше. Приведенный пример демонстрирует, что происходит, когда множество транзак­ ций пытаются получить доступ к одному и тому же блоку одновременно - при ис­ ключительно высоком числе параллельных транзакций может возникнуть ожидание на таблице транзакций . Блокирование может случ иться , есл и п араметр I N I T RAN S установлен в н изкое значение и пространства в блоке недостаточно для динами­ ческого расширения транзакц и и . В большинстве случаев стандартного значен ия 2 для I N I TRANS вполне достаточно, т. к. таблица транзакци й будет динамически расти (при наличии свободного пространства) , но в некоторых средах может требоваться увеличение этого параметра (чтобы зарезервировать больше пространства для сло­ тов) для повы шения степени параллелизма и уменьшения времени ожидания . Примерам ситуации, когда имеет смысл увеличить I N I T RAN S , может быть нал и ­ ч и е таблицы или , даже еще чаще , и ндекса (поскольку блоки и ндекса могут содер- 336 Глава 6 жать знач ительно бол ьше строк, чем обычно хранит таблица) , который интенсивно изменяется и в среднем и меет много строк на блок. В таком случае может лонадо­ биться увеличить значение либо параметра PCT FREE (обсуждается в главе 1 0) , либо параметра I N I T RANS , чтобы заблаговременно выделить в блоке пространство, до­ статочное для предполагаемого количества параллельных транзакций. Это особенно справедливо, если ожидается, что с самого н ачала блоки будут почти полными, т.е. в них не будет места для динамического расши рения структуры транзакций. И последнее замечан ие о параметре I N I TRAN S . П ару раз я утверждал , что стан­ дартным значен ием для него является 2. Тем не менее, если вы просмотрите словарь данных после создан ия таблицы, то заметите , что для I N I T RANS отображается зна­ чение 1 : EODA@ORA12CR1> c reate taЬle t ( х int ) ; EODA@ORA 1 2 CR1 > select ini trans from user taЬles whe re taЬle name = ' Т ' ; INI TRANS 1 Так чему же равно стандартное количество слотов транзакци й - 1 или 2? Хотя словарь дан н ых показывает значение l , мы можем продемонстрировать, что в дейс­ твительности им я вляется 2. Проведем следующий эксперимент. Первым делом сге­ нерируем одну транзакцию для таблицы т, вставив в нее оди ночную зап ись: EODA@ORA12CR1> insert into t values ( 1 ) ; Теперь удостоверимся в том , что таблицей Т потребляется один блок: EODA@ORA12CR1> select dЬms_rowid . ROW I D_BLOCK_NUMBER ( rowid) DBMS_ROW I D . ROW I D_BLOCK_NUМBER ( ROW I D ) from t ; 57715 Далее поместим в перемен ные в и F номер блока и номер файла данных блока, испол ьзуемого таблицей т : EODA@ORA12CR1> column Ь new va l В EODA@ORA12CR1> column f new va l F EODA@ORA12CR1> s e lect dЬms rowid . ROW I D_BLOCK_NUМBER ( rowid) В , 2 dЬms_rowid . ROWI D_TO_AВSOLUTE_FNO ( rowid, user , ' Т ' ) F from t ; 3 Создадим дамп блока, применяемого табли цей т : EODA@ORA 1 2 CR1 > alter sys tem dump datafile & F Ьlock & В ; П оместим в переменную T RACE местоположен ие и имя трассировочного файла, содержащего информацию дампа для блока: EODA@ORA1 2CR 1 > column trace new val TRACE EODA@ORA12CR1> s e lect c . va1ue 1 1 ' / ' 1 1 d . ins tance_name 1 1 ' _ora ' a . spid 1 1 ' . trc ' trace f rom v$proces s а , v $ s e s s ion Ь , v$parameter с , v$ins tance d 2 3 where а . addr = Ь . paddr and Ь . audsid = userenv ( ' s e s s ionid ' ) 4 5 and c . name = ' user_dump_des t ' ; 1 1 Б ло кировка и за щ ел ки ван ие данных 337 А теперь завершим работу сеанса и откроем трассировочн ы й файл для редактирования: EODA@ORA1 2CR1 > di sconnect EODA@ ORA1 2CR1 > edit &TRACE Выполнив поиск в трассировочном файле значения I t l , мы увидим , что был и инициализированы два слота транзакций (хотя для этой таблицы была выдана толь­ ко одна транзакция): Itl Ох01 Ox02 Xid Uba Flag Lck Ох0 0 1 3 . ООе . 00002 4Ье ОхООсО О ОЬf . 0 3 9е . 2d --U­ ОхО О О О . 000 . 0 0 0 0 0 0 0 0 ОхО О ОО О О О О . 0 0 0 0 . 0 0 Scn/Fsc 1 fsc Ox0 0 0 0 . 0 1cfa56a О fsc ОхО О О О . О О О О О О О О Значение 1 для I N I T RAN S , сообщаемое словарем дан н ых, скорее всего, является унаследованным и в более новых версиях Oracle вместо него должно отображаться 2. Блокировки ТМ (помещение в очередь DML) Блокировки ТМ используются для гарантирования того, что структура таблицы не изменится во время модификации ее содержимого. Н апример, при обновлении таблицы вы запрашиваете блокировку ТМ на ней . Это предотвратит выдачу другим пользователем команд DRO P или ALT E R в отношении данной таблицы . Если дру­ гой пользователь попытается выполнить оператор D D L для этой таблицы в то вре­ мя , когда на ней размещена блокировка ТМ , он получит следующее сообщение об ошибке: drop taЬle dept * ERROR at 1 ine 1 : ORA- 0 0 0 5 4 : resource busy and acquire with NOWAIT speci fied ОШИБКА в строке 1 : ORA-0005 4 : ресурс занят и запрошен без указания NOWAIT На заметку! В O racle 1 1 g Release 2 и последующих версиях можно устанавли вать DDL_ LOCK_т IMEOUT, чтобы заставить DDL-oпepaтop ожидать. Обычно это делается ко­ мандой ALTER S ES S I ON . Например, перед выдачей команды DROP TABLE можно выпол ­ нить команду ALТER SES S I ON SET D D L_LOCK_T I MEOUT= б O ; . Тогда команда DROP TABLE должна будет ждать 60 секунд, прежде чем возвратить сообщение об ошибке ( разумеет­ ся , она также может выполниться успешно). Сообщение ORA- 0 0 0 5 4 поначалу может сби вать с толку, поскольку прямого ме­ тода указать конструкцию NOWAI T или WA I T в D RO P TABLE вообще не существует. Это просто универсальное сообщение, отображаемое при попытке выполнения опе­ рации , которая будет заблокирована, но не допускает блокирования . Как вы уже видели ранее, то же самое сообщение выводится при выдаче команды SELECT FOR UPDATE NOWAIT применительно к заблокированной строке. Н иже показано, как эти блокировки будут выглядеть в табли це V$ LOCK: EODA@ORA1 2CR1 > create taЬle t1 ( х int ) ; ТаЬlе created . Та блица создана . 338 Гл ава 6 EODA@ ORA1 2CR1> create taЬle t2 ( х int ) ; ТаЫе created . Та блица создана . EODA@ORA1 2CR1> insert into t 1 values ( 1 ) ; 1 row created . 1 строка создана . EODA@ORA1 2CR1> insert into t2 values ( 1 ) ; 1 row created . 1 строка создана . EODA@ORA1 2CR1> select ( se lect use rname 2 from v$ s e s s i on 3 whe re s i d = v$lock . s i d ) username , sid, 4 5 id1 , id2 , б lmode , 7 8 reque s t , Ьlock, v $ l oc k . t ype from v$1ock 9 10 where s i d = s ys_context ( ' use renv ' , ' s id ' ) ; USERNAМE SID --------- I D1 I D2 LMODE REQUEST ------- ------- ------- ------- EODA 22 133 EODA EODA 22 22 244271 244270 EODA 22 19бб095 BLOCK ТУ ------- о 4 о о о о о АЕ о з з 1 52 б о о тх о о тм тм EODA@ORA1 2CR1> s e 1 ect obj ect_name , obj e ct_id 2 from user_obj ects 3 where obj ect_id i n ( 2 4 4 2 7 1 , 2 4 4 2 7 0 ) ; OBJECT NАМ Т2 Т1 OBJECT I D 244271 244270 На заметку! Блокировка дЕ - это блокировка редакции , достуnная в Oracle 1 1 g и nоследую­ щих версиях. Она является частью средства Edition Based Redefin ition (Переоnределение на основе редакции ) , которое в настоящей книге не рассматривается. I D 1 - идентифи­ катор объекта редакции , SID которой исnользуется в текущий момент. Эта блокировка редакции защищает соответствующую редакцию от модификации ( вроде отбрасывания редакции ) nодобно тому, как блокировки ТМ защищают от структурных модификаций таб­ л и цы , на которые они указывают. В то время как для каждой транзакции м ы получаем только одну блокировку ТХ, блокировок ТМ может быть столько, сколько модифицируемых объектов. Здесь интересно отметить, что в столбце I D l блокировки ТМ находится идентификатор объекта, заблокированного для операции D M L, поэтому выявление объекта, на ко­ тором удерживается блокировка, не представляет труда. Еще одн а и нтересная особен н ость блокировок Т М : общее количество блоки ­ ровок Т М , разрешенных в системе, допускает конфигурирование (за деталями об­ ращайтесь к определен и ю п араметра D M L L O C K S в руководстве Oracle Database Б локиров ка и защ ел ки ван и е данных 339 Reference) . Параметр DML_LOCKS в действительности может быть установлен в О. Это не означает превращение базы дан ных в доступную тол ько для чтения (без блоки­ ровок), а то, что операции DDL не разрешены. П одобная возможность полезна в очень специализированных приложен иях, таких как реал изации RAC , для сокра­ щения объема работ по коорди нации внутри экзем пляра, которые и наче пришлось бы выполнять. Кроме того, с помощью команды ALT E R TAB L E <имя_т а блицы> D I SAB LE TABLE LOCK отключается возможность выдачи блокировок ТМ на уровне отдельных объектов. Это служит быстрым способом минимизации случайного уда­ ления таблицы, т. к. перед удалением табли цы придется заново включить блокировку таблицы. Данный прием можно применять также для обнаружен ия обсуждаемой ра­ нее блокировки всей таблицы из-за наличия неиндексированного внешнего кл юча. Б локировки DDL Блокировки DDL автоматически помещаются на объекты в о время выполнения операци и D D L с целью защиты этих объектов от измене н и й другим и сеансам и . Например, при выполнении D D L-операции ALT E R TABLE т н а табли цу т в общем случае будет помещена монопол ьная блокировка D D L, которая предотвращает по­ мещение на эту таблицу блокировок D D L и ТМ другим и сеансами . Н а заметку! В версии Oracle 1 1 g было модифицировано то, что привыкл и считать п равилам. В прошлом оператор ALTER TABLE т устанавливал на табли цу монопольную блокировку DDL. В этом примере табли ца т запрещает другим сеансам выполнение D DL-операций и запраши вание блокировок ТМ ( используем ых для изменения содержимого табл и цы ) . Теперь многие команды ALT E R могут выполняться оперативно - без п редотвращения модификаций . Блокировки D D L удерживаются на протяжен и и выполнения оператора D D L и освобождаются немедленно после его завершения. Фактически это достигается за счет помещения операторов DDL внутрь неявных фиксаций (или пары "фиксация/ откат" ) . По этой причине в Oracle операторы D D L всегда фиксируются . Каждый оператор CREATE, ALTER и т.д. в действительности выполня ется так, как показано в следующем псевдокоде: Begin Commi t ; ОПЕРАТОР DDL Commi t ; Exception Иначе выnолнить отка т ; End; Таким образом , оператор DDL фиксируется всегда, даже если он завершился не­ удачно. Вы полнение оператора D D L н ач инается с фиксации - помн ите об этом. Вначале выполняется фиксация , чтобы при необходимости отката оператора это не привело к откату транзакции. Запуск оператора DDL сделает постоя нной любую ос­ тавшуюся невыполиенной работу, даже когда он не я вляется успешным. Если вам необходимо выполнить оператор DDL, но вы не хотите фиксировать существующую транзакцию, можете воспользоваться автономной транзакцией. 340 Глава б Существуют три типа блокировок D D L. • Монопольные блокировки DDL. Такие блокировки препятствуют други м сеансам сами м получать блокировку D D L или ТМ ( D M L) . Это значит, что во время выполнения операции DDL таблицу можно запрашивать, но не модифициро­ вать ее каким-либо образом. • Разделяемые блокировки DDL. Такие блокировки защищают структуру соответс­ твующего объекта от изменений другими сеансам и , но разрешают модифика­ цию данных. • Прерываемые блокировки разбора. Эти блокировки разрешают объекту, такому как план запроса, кеш ираванный в разделяемом пуле, регистрировать свою за­ висимость от какого-то другого объекта. П ри выполнении операции DDL в от­ ношении этого объекта Oracle просмотрит сп исок объектов, которые зарегист­ рировали свою зависимость, и сделает их недействительными. Следовательно, такие блокировки я вляются прерываемыми - они не препятствуют выполне­ нию операции DDL. Большинство операций D D L захватывают монопольную блокировку D DL. Если вы запустите оператор вроде следующего: a l te r taЬ l e t move ; то таблица т будет недоступной для изменений на период его выполнения . В это время таблицу можно запрашивать с применен ием оператора S E L E C T , но вы пол­ нять больши нство других действий , включая все операторы DDL, будет запрещено. Теперь в базе дан н ых Oracle некоторые операции DDL могут выполняться без бло­ кировок DDL. Н апример, можно вьшать следующи й оператор: create index t_idx оп t ( x ) ONL I NE ; Ключевое слово ONL I NE модифицирует метод, посредством которого в действи­ тельности строится и ндекс. Вместо того чтобы использовать монопольную блоки­ ровку D DL, предотвращающую изменение данн ых, Oracle будет п ытаться получить для таблицы только н изкоуровневую блокировку ТМ (режима 2). Это эффективно воспрепятствует выполнению других операций D D L, но сделает возможным нор­ мальное выполнение операций D M L. База данных Oracle достигает этого результа­ та, сохраняя зап ись об изменениях, которые был и произведен ы в таблице во время выполнения оператора D D L, и применяя эти изменения к новому индексу по за­ вершении операции C REAT E. В результате существенно увеличи вается доступность данн ых. Чтобы убедиться в этом , создайте таблицу некоторого размера: EODA@ORA 1 2 C R 1 > create taЬle t as s e l ect * from al l_obj ects ; ТаЬlе created . Та блица создана . EODA@ORA12CR1> select obj ect_id from user_obj ects where obj ect_name = ' Т ' ; OBJECT I D 244277 Затем создайте и ндекс н а этой таблице: EODA@ORA1 2CR1> create index t_idx on t ( owne r , obj ect_type , obj ect_name ) ONLINE ; Б л окировка и з а щ ел ки вани е дан ных 341 В то же самое время запустите в другом сеансе приведенный н иже запрос, что­ бы увидеть блокировки , установлен н ые на этой вновь созданной табли це (не забы­ вайте , что значение I D 1=2 4 4 2 7 7 специфично для моего случая, поэтому указы вайте свой идентификатор объекта) : EODA@ORA12CR1> s e lect ( select use rname 2 from v$s es s ion whe re s i d = v$ lock . s i d ) use rname , 3 s id, 4 idl , 5 id2 , б lmode , 7 reque s t , Ьlock, v$ 1oc k . t ype В from v$ lock 9 10 where idl = 2 4 4 2 7 7 11 1 USERNAМE SID --------- EODA EODA EODA EODA 22 22 22 22 IDl I D2 LMODE REQUEST BLOCK ------- ------- ------- ------- ------- 244277 24 4277 244277 244277 о о о о 3 3 2 4 о о о о о о о о ТУ DL DL тм OD Итак, здесь мы видим четыре блокировки, установленные н а нашем объекте. Две блокировки DL - это блокировки прямой загрузки (direct load). Они испол ьзуются для предотвращения загрузки в прямом режиме в базовую таблицу, когда создается индекс (естественно, это подразумевает невозможность одновременного выполне­ ния загрузки данных в прямом режиме и создан ия и ндекса). Блокировка O D отно­ сится к типу блокировок, впервые появившемуся в Oracle l lg (в версиях Oracle ! Og и Oracle9i он и отсутствуют), которы й разреш ает по-настоящему оперативные коман­ ды DDL. В прошлом (в Oracle \ Og и предшествующих версиях) оперативные коман­ ды DDL, такие как CREAT E I N DEX ONL I N E , не был и на 1 00% оперативными. Они требовали установки блокировки в начале и кон це оператора C REAT E , предотвра­ щая другие параллельные действия (измене н ия дан ных базовой таблицы). Они были по большей части оперативными, но не полностью оперативными. Н ачиная с версии Огас\е 1 \g, команда CREAT E I N DEX ONL I NE пол ностью оперативна; она не требует монопольных блокировок в начале/конце команды. Отчасти реализация этого трю­ ка стала возможной благодаря введению блокировки OD (Online D D L - оператив­ ная команда DDL); она применяется внутренне для обеспечения по-настоящему оперативн ых операций DDL. Другие тип ы операци й DDL и меют дело с разделяемыми блокировками D D L . Эти блокировки устанавливаются на зависимые объекты при создани и хранимых, компилируемых объектов, таких как процедуры и представления . Например, при выполнении следующего запроса разделяемые блокировки DDL будут помещен ы на таблицы ЕМР и DEPT на время обработки команды CREATE VI EW: create view MyView as select emp . empno , emp . ename , dept . deptno , dept . dname from emp , dept where emp . deptno = dept . deptno ; 342 Глава 6 Допускается изменять содержимое этих таблиц, но не их структуру. П оследни й тип блокировки D D L - прерываемая блокировка разбора. Когда се­ анс выпол няет разбор оператора , блокировка разбора устанавл ивается на каждый объект, на которы й ссылается этот оператор. Эти блокировки получаются для того, чтобы проанализированн ы й , кеш ираван ный оператор мог быть объя влен недейс­ твительным (оч и щен) в разделяемом пуле, если объект, на который он ссылается , был удален л ибо изменен . П р и п росмотре этой и нформации особенно полезным я вляется представление D BA_ DDL _ L O C K S . П одходя щих представлений V$ не существует. П редставление DBA DDL LOCKS строится на основе более загадочных таблиц Х $ и по умолчанию может быть не установлено в вашей базе данных. Это и другие представления , свя­ зан ные с блокировкой, можно установить, запустив сценарий c a t Ь l o c k . s q l , ко­ торый находится в каталоге [ ORACL E_ НОМЕ ] 1 rdbrns 1 admin. Указанный сценарий должен выпол няться от имени пользователя SYS. После его успешного завершения представление DBA_ DDL_ LOCKS можно запрашивать. Например, в только что под­ ключенном сеансе я могу получить следующий вывод: _ _ EODA@ORA1 2 CR1 > connect eoda / foo Connected . Подключено . EODA@ORA1 2 CR1 > set l ines i z e 1 0 0 0 EODA@ORA1 2CR1> s e l ect s e s s ion_id s id , owne r , name , t ype , 2 mode_he1d held, mode_reques ted reques t f rom dЬа ddl locks 3 4 whe re s e s s ion id = ( se l e ct s i d f rom v$mystat whe re rownum= 1 ) 5 1 S I D OWNER NАМЕ ТУРЕ HELD REQUEST 22 SYS 2 2 SYS 2 2 EODA 2 2 SYS 2 2 SYS 2 2 SYS 22 2 2 SYS DBMS OUT PUT DBMS OUT PUT EODA DBMS APPL ICAT I ON INFO PLI TBLМ DBMS APPL I CATI ON I N FO EODA DATAВASE Body TaЬle / Procedure/Type 18 Body TaЬle / Procedure /Type TaЬle/ Procedure /Type 73 18 Null Nul l Null Nul l Null Nul l Share Nul l None None None None None None None None -------------------- ------------------ -------- 8 rows s e l ected . 8 строк выбрано . Все это объекты , блокируемые моим сеансом. Я имею прерываемые блокировки разбора на п аре пакетов DBMS * . Это побоч ный эффект от применения интерфей­ са SQL* Plus; например, он может вызывать овмs_APPL I CAT ION I N FO, когда вы из­ начально в него входите (чтобы вкл юч ить/отключить овмs OUTPUT через команду S E T S E RVEROUT PUT ) . Я могу видеть здесь более одной копи и различных объектов; это нормально и просто означает, что разделяемый пул содержит более одного объ­ екта, которые ссылаются на эти объекты. Обратите вниман ие, что в этом представ­ лении столбец OWNER представляет не владельца блокировки , а владел ьца заблоки ­ рованного объекта. И менно потому мы видим множество строк SYS. Пользователь SYS владеет этим и пакетами, но все они принадлежат моему сеансу. _ _ _ Бло ки р о вка и за щ ел ки ван и е дан н ы х 343 Чтобы увидеть прерываемую блокировку разбора в действии, давайте создадим и запустим хранимую процедуру Р: EODA@ORA12CR 1 > c reate o r rep1ace p rocedure р 2 as 3 begin 4 nul l ; 5 end ; б 1 Procedure c reated . Процедура создана . EODA@ORA1 2CR1> ехес р PL/SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно завершена . Процедура Р теперь будет отображаться в представлении DBA_ DDL LOCKS . М ы имеем н а ней блокировку разбора: EODA@ORA12CR1> select s e s s i on_id s i d , owner , name , type , mode_held held, mode_requested reques t 2 from dЬа ddl locks 3 4 where s e s s ion id = ( sel ect s id from v$mys tat where rownum= 1 ) 5 1 S I D OWNER NАМЕ ТУРЕ HELD REQUEST 22 р TaЬle/Procedure/Тype Null None 18 Nul l None EODA DATAВASE 2 2 SYS 9 rows selected . 9 строк выбрано . Затем мы перекомп илируем процедуру и снова запроси м представление: EODA@ORA12CR1 > alter procedure р comp i l e ; Procedure altered . Процедура изменена . EODA@ORA12CR1> s elect s e s s ion_id s i d , owne r , name , type , mode_hel d held, mode_reque sted reque s t 2 3 from dba ddl locks 4 where s e s s ion id = ( s e lect sid from v$mys tat where rownum= 1 ) 5 1 S I D OWNER NАМЕ -------------------- ТУ РЕ ------------------ HELD DBMS OUT PUT Body Null 2 2 SYS TaЬle / Procedu re /Type Nul l DBMS OUT PUT 2 2 SYS 18 Null EODA 2 2 EODA DBMS APPLICAT I ON I N FO Body Nul l 2 2 SYS TaЬle / Procedure/Type Nu l l PLI TBLM 2 2 SYS DBMS APPL I CAT I ON I N FO TaЬl e / Procedure /Type Nul l 2 2 SYS 73 Share EODA 22 DATAВASE Nul l 18 2 2 SYS В rows selected . В строк выбрано . REQUEST -------- None None None None None None None None 344 Глава б Мы видим, что процедура Р исчезла из представлен ия . Блокировка разбора бьmа разрушена. П редставление D BA_ DDL _ LOCKS полезно для разработчи ка, когда обнаружива­ ется , что какая -то часть кода не комп илируется в тестовой системе или в системе разработки - она зависает и в конечном итоге прерывается . Это указывает на то, что ее использует кто-то другой (выполняет в текущи й момент) , и с помощью дан­ ного представления можно выяснить, что это за пользовател ь. То же самое будет происходить с операторами GRANT и другими типами операци й DDL, запускаемыми применительно к объекту. Например, нельзя выдать полномоч ия EXECUTE для вы­ полняющейся процедуры. Тот же самый метод можно использовать для выявления потенциальных блокирующих и ожидающих пользователей . Н а заметку! В Oracle 1 1 g Release 2 и последующих версиях имеется средство переопределе­ ния на основе редакции (EBR). С его помощью можно выдавать право EXECUTE иjили пра­ во на перекомпиляцию кода в базе данных, не мешая пользователям , которые выполняют код в текущий момент. Средство EBR позволяет иметь несколько версий одной и той же хранимой процедуры в схеме одновременно. Это обеспечивает возможность работы с ко­ пией процедуры в новой редакции (верси и ) , не конфликтуя с текущей версией процедуры, которая применяется другим и пользователями. Однако средство EBR в настоящей книге не рассматривается, а только упоминается там , где оно меняет установленные правила. Защелки Защелка (latch) - это легковесный механ изм сериал изации, используемый для координации м ногопол ьзовательского доступа к разделяемым структурам данных, объектам и файлам . Защелки представляют собой блоки ровки , предназначен ные для установки на очень короткие и нтервалы времен и , например, на время , которое требуется для мо­ дификации структуры данных в памяти. Они применяются для защиты определен­ ных структур п амяти , таких как кеш буферов блоков базы дан ных или библиотеч­ ный кеш в разделяемом пуле. Защелки обычно запраш иваются внутренне в режиме добровольного ожидания. Это означает, что есл и защелка не доступна, то запраши­ вающий сеанс будет приостановлен на короткий промежуток времени и повторит операцию позже. Другие защелки могут запраши ваться в немедленном режиме , что концептуально подобно выполнению оператора S ELECT FOR U P DATE NOWA I T , т.е. процесс предпримет какие-то другие действия , например, попытается захватить эк­ ви валентную родственную защелку, которая может быть свободной , а не будет прос­ то дожидаться, пока конкретная защел ка станет доступ ной. П оскольку в данный момент защелку могут ожидать множество запраш и вающих процессов, некоторые из них могут ждать дольше других. Защелки назначаются довольно случайным об­ разом, на основе везения , если уж на то пошло. Любой сеанс, запросивший защелку сразу после того, как она была освобождена, получит ее. Н и какой очереди ожидаю­ щих процессов не существует - есть только группа ожидающих процессов, которые постоянно повторяют свои попытки . Для оперирования защелками в Oracle используются атомарные инструкции типа "проверить и установить" и "сравнить и поменять местами " . Поскольку инструкции установки и освобожден ия защелок являются атомарным и , сама операционная сие- Б ло ки р о вка и за щ ел ки вание данных 345 тема гарантирует, что проверять и устанавливать защелку будет только оди н процесс, хотя одновременно она может требоваться нескольким процессам. С учетом того, что инструкция только одна, она может выполняться достаточно быстро (но весь алгоритм защелкивания представляет собой множество и нструкци й центрального процессора) . Защелки удержи ваются в течение коротких периодов и предоставля­ ют механизм для очистки в случае аварий ного отказа держателя защел ки . П роцесс очистки будет выполняться монитором процессов (PMON). Рассмотренная ранее организация очередей - еще одно, более развитое средс­ тво последовательной обработки , которое примен яется, например, при обновлен и и строк в таблице базы данн ых. О н о отличается о т защелок тем , что позволяет запра­ шивающему процессу стать в очередь и ожидать ресурса. При запросе защелки за­ прашивающий сеанс сразу получает ответ о том , получит он защелку или нет. П р и использовании блокировки в порядке очереди запрашивающий сеанс будет блоки­ роваться до тех пор, пока действительно не получит блокировку. На заметку! 8 случае применения S E LECT FOR U P DATE NOWA I T И Л И WAI T [ n ] МОЖНО ДО­ полнительно отказаться от ожидания предоставления блокировки в порядке очереди , если сеанс окажется заблокированным, но если вы все же решите выполнять блокировку и ожидать, то ожидание будет происходить в очереди . Сама по себе блокировка с очередью - не настолько быстрое средство, каким может быть защелка, но по сравнению с ней предоставляет намного больше функ­ циональных возможносте й. Блокировки с очередями разрешено получать на разно­ образных уровнях, поэтому может существовать множество разделяемых блокировок и блокировок с разными уровнями совместного использования . "Раскручивание " защелки В отношении защелок я хотел бы разъяснить оди н момент: защелки представ­ ляют собой тип блокировки , блокировки - это механизмы сериал изац и и , а меха­ низмы сериализации препятствуют масштабируемости . Если ваша цель заключается в построении приложения, которое хорошо масштабируется в среде Oracle, то вы должны искать подходы и решения, сводящие к минимуму необходимое количество защелок. Даже на первый взгляд простые действия вроде разбора SQ L-oпepaтopa получа­ ют и освобождают сотни или тысячи защелок на библиотечном кеше и связанн ых структурах в разделяемом пуле. Если мы располагаем защелкой, значит, кто-то дру­ гой может ожидать ее освобожден ия . Когда мы обращаемся за защелкой, то вполне можем ожидать ее предоставления . Ожидан ие защелки может оказаться дорогостоя щей в смысле ресурсов опера­ цией. Если защелка не доступна сразу же и мы готовы ее ждать, как происходит в большинстве случаев, то на м ногопроцессорной машине сеанс будет выполнять рас­ крутку (spin), циклически снова и снова повторяя попытки получить защелку. Такой подход обусловлен тем , что переключение контекста (т.е. отключение от процессо­ ра и повторное подключение к нему) является дорогостоящей операцией. П оэтому, если процесс не может получить защелку немедленно, он остается подключенным к процессору и незамедлительно повторяет попытку, а не просто приостанавли вается , освобождая процессор и повторяя попытку позднее при повторном подключении к 346 Глава 6 процессору в соответстви и с установленным расписанием. При этом есть надежда, что держатель защелки будет занят обработкой на другом процессаре (а поскольку защелки разработаны так, чтобы удерживаться в течение очен ь коротких периодов времени , это весьма вероятно), и н ам вскоре удастся получить защелку. Если после раскручи вания и непрерывных попыток получить защелку это все же не удается , то только тогда процесс перейдет в состоян ие бездействия, или отключится от процес­ сара и позволит ему выпол нять какую-то другую работу. Такой переход в состояние бездействия обычно я вляется результатом одновремен ного запрашивания многими сеансами одной и той же защелки . Проблема вовсе не в том , что одиночный сеанс удерживает защелку долгое время, а в том , что множество сеансов хотят получить ее в тот же самы й момент времени и каждый удерживает ее на протяжении короткого периода. Есл и вы делаете что-то краткое (быстрое) достаточно часто, то это все и объясняет! П севдокод получения защелки выглядит следующим образом: Цикл для значения i из диапазона 1 2000 Цикл Попытать ся получить защелку Если защелка получена , выполнить возврат Е сли i = 1 , то счетчик неудач = счетчик неудач + 1 Конец цикла ИНКРЕМЕНТИРОВАТЬ СЧЕТЧИК ОЖИДАНИЯ Бездействовать ДОБАВИТЬ ВРЕМЯ ОЖИдАНИЯ Конец цикла ; . . Логика работы предусматри вает поп ытку получения защел ки и , если сделать это не удается , то и н крементирование счетчи ка неудач ных поп ыток, являющегося статистическими сведе н ия м и , которые можно видеть в отчете Statspack или путем непосредствен ного запрашивания представления V$ LATCH . В случае неудачной по­ п ытки п роцесс циклически повторит попытки определен ное коли чество раз (ко­ личеством попыток управляет недокументированный параметр, который обычно установлен в 2000), снова и снова пробуя получить защелку. Есл и одна из этих по­ п ыток удается , происходит выход и обработка продолжается . Если все поп ытки ока­ зываются безуспешными, процесс на короткий период времени перейдет в состоя­ н ие простая, предварительно увеличив счетчик ожидания для этой защелки . После пробужден ия процесс повторяет все описанные действия заново. Это означает, что затраты на получение защелки не ограничи ваются только происходя щей операци­ ей типа "проверить и установить" , но также включают в себя значительную часть времени процессора, пока предпринимаются попытки получения защелки. Система будет выглядеть очень загружен ной (со значительн ы м потреблением времени про­ цессора) , но при этом выполняется не особенно большой объем работ. Измерение затрат на защелкивание разделяемого ресурса В качестве примера мы проанализируем затраты на установку защелки на раз­ деляемы й пул . М ы сравни м хорошо написан ную программу (использующую пере­ менные привязки ) с программой, написанной не настолько удачно (в которой для выполнения каждого действия применяется л итеральны й , или ун икальный, SQL­ oпepaтop) . Для этого мы воспользуемся небольшой программой на Java, которая Б ло кировка и за щ ел ки ван и е данн ых 347 просто входит в базу данных Oracle, отключает фун кцию автоматической фиксации (как и должн ы поступать все Jаvа-программы немедленно после подключен ия к базе данн ых) и выполняет в цикле 25 000 уни кальных операторов I N S E RT . М ы прогоним два набора тестов: в первом наборе программа не будет использовать перемен н ые привязки , а во втором - будет. Чтобы оценить эти программ ы и их поведение в м ногопол ьзовательской среде , для сбора результатов измерени й я предпочел использовать пакет Statspack, как опи­ сано ниже . 1 . С помощью пакета Statspack получите снимок текущего состояния системы. 2. Запустите N копи й программы, заставив каждую программу выпол нять опера­ цию I NS E RT в собствен ную таблицу базы дан н ых, чтобы избежать конкурен­ ци и, связан ной с попытками всех программ производить вставку в еди нствен ­ ную таблицу. 3. Получите еще оди н снимок состоян и я систем ы немедленно после заверше­ ния последней копи и программы. Теперь остается только вывести отчет Statspack и выяснить, сколько времен и пот­ ребовалось для завершения операции N копиями программы, сколько было потреб­ лено времени процессора, какие основные события ожидания имели место и т.д. На заметку! Почему бы для nроведения этого анализа не nрименить AWR (Automatic Workload Repository - автоматический реnозиторий рабочей нагрузки )? Дело в том , что достуn к nакету Statspack имеют все - действительно все. Он может требовать установки адм и ­ нистратором базы данных, но достуn к н е м у имеет каждый nользователь Oracle. Я хочу nредставить резул ьтаты, которые могли бы быть восnроизведены абсол ютно всем и . Эти тесты были выполнены н а двухпроцессорной машине с включенной гипер­ поточностью (создавшей иллюзи ю наличия четырех процессоров) . Учитывая нали­ чие двух физических процессоров, здесь можно было ожидать весьма линей ного масштабирования - то есть, если оди н пользователь для обработки своих операций вставки задействует 1 единицу загрузки процессора, то двоим пользователям потре­ буются 2 таких еди ницы. Вы обнаружите , что это предположение, хотя и кажется правдоподобным, может быть неточн ы м ( как вы убедитесь, степень расхожден ия зависит от используемой техн и ки программирован и я ) . П редположение было бы корректным, если бы выполня емая обработка не нуждалась в разделяемых ресурсах, но наш процесс применяет такой ресурс, а именно - разделяемый пул . Нам необ­ ходимо защелки вать разделяемый пул для выполнения разбора SQL-операторов, и это требуется делать из-за того, что он является совместно используемой структурой данных, и мы не можем его изменять, пока другие пользователи производят чтение из него, или выполнять чтение из него, когда другие его модифицируют. На заметку! Я nрогнал эти тесты с участием Java, PL/SQL, Pro*C и других языков nрограм­ м и рования. Каждый раз конеч ные результаты были в основном таки м и же . П ри ведеиная демонстрация и обсуждение nрименимо ко всем языкам и всем и нтерфейсам , n редна­ значенным для взаимодействия с базой данных. В этом nримере я выбрал язык Java, nос­ кольку nрограмм ы на Java и Visual Basic, скорее всего, не будут исnользовать nеременные nри вязки nри работе с базой данных Oracle. 348 Глава 6 Настройка теста Для того чтобы провести тестирование, понадобится схема (набор таблиц), с ко­ торой мы будем и меть дело. М ы будем выпол нять тестирование с множеством поль­ зователей и хотим измерить в основном степень конкуренции из-за защелки вания , т.е . мы не заинтересован ы в измерен и и степени конкуренци и , вызванной тем , что множество сеансов выпол ня ют вставку в одну и ту же табли цу базы данных. Таким образом, мы создадим по одной табли це на пользователя и назовем их от Tl до T l O . Например: S COTT @ORA 1 2 CR 1 > connect s cot t / t iger Connected . Подключено . SCOT T @ORA1 2CR1> begin 2 for i in 1 . . 1 0 l oop 3 4 for х in ( s e 1ect * from user taЫ es whe re tаЫ е name = ' Т ' 1 1 i ) loop 5 б execute immediate ' drop tаЫе ' 1 1 х . tаЫе name ; 7 end loop ; execute immediate ' create tаЫ е t ' 1 1 i 1 1 ' ( х int ) ' ; 8 9 end l oop ; 1 0 end; 11 1 PL/ SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно завершена . М ы будем запускать этот сценарий перед каждой итерацией теста, чтобы сбро­ сить схему и инициировать полный разбор, если тест прогоняется более одного раза. Во время тестирования мы будем выпол нять следующие шаги . 1 . Запуск S t a t s pa c k . s nap. 2 . Н емедленный запуск N процедур Java, где N варьируется от 1 до 1 0, представляя от 1 до 1 О п аралл ельных пользователей. 3 . Ожидание завершения всех N процедур. 4. Запуск S t a t spac k . snap. 5 . Генерация отчета Statspack для последних двух идентификаторов Statspack. Ч исла, получен н ые в результате показанных ниже прогонов тестов, были собраны с применением этого п риема. Совет. Сценари и , предназначенные для автоматизации описанного здесь теста, доступны для загрузки на веб-сайте издательства. В каталоге сh О б есть два подкаталога: nob i nds и b i nds . В нутри этих подкаталогов сценарий run . sql вызывает код, требующийся для выполнения этого теста. Вам понадобится изменить код, чтобы отразить актуальную ин­ формацию о подключении к базе данных там , где это необходимо. Кроме того, вы также должны , конечно же , скомпилировать Jаvа-программу на своем сервере. Б л окиров ка и за щ елки ван и е дан н ых 349 Тестирование без переменных привязки В первом случае при вставке дан н ых наша программа будет испол ьзовать н е пе­ ременные привязки , а конкатенацию строк (очевидно, что вы должн ы указать свою строку подключен ия ) : irnport j ava . sql . * ; puЬlic class instest { static puЬ l i c void rna in ( St r i ng args [ ] ) throws Excepti on { Drive rManager . regi sterDriver ( new oracle . j dЬc . drive r . OracleDriver ( ) ) ; Connection conn = Drive rManager . getConnect i on ( 11 jdЬc : oracle : thin : @heesta : 152 l : ORA12CR1 11 , 11 Scott 11 , 11 tiger 11 ) ; conn . s etAutoCornrni t ( false ) ; Staternent s trnt = conn . createStaternent ( ) ; for ( int i = О ; i < 2 5 0 0 0 ; i + + ) { stшt . execute ( 11 insert into 11+ args [ 0 ] + 11 (х) values ( 11 + i + 11 ) 11 ) ; conn . cornrni t ( ) ; conn . close ( ) ; Я запустил этот тест в однопользовательском режиме (т.е. в отсутствие других ак­ тивных сеансов базы данных) , и пакет Statspack возвратил отчет с такой и нформа­ цией: Elapsed : 0 . 2 5 (mins) Av Act Ses s : 0.9 DB tirne : 0 . 2 2 (rnins ) 0 . 2 0 (rnins ) Cache S i ze s Begin Buffer Cache : Shared Pool : Load Profi l e Parses : Hard parses : DB CPU : End 2 , 6 5 6М 6 4 0М S td Block S i z e : Log Buffer : 8К 1 4 , 808К Per Ехес Per Cal l Redo NoWai t % : Optirnal W /A Ехес % : Soft Parse % : Latch H i t % : % Non- Parse CPU : 100 . 00 100 . 00 50 . 12 100 . 00 1 6 . 29 Per Second Per Transaction 3 , 342 . 1 1 , 667 . 2 25, 066 . 0 12, 504 . 0 Ins tance Efficiency I ndicators Buffer Nowa i t Buffe r H i t Library H i t Execute to Parse Parse CPU to Parse Elapsd %: %: %: %: %: 100 . 00 99 . 99 60 . 0 5 0 . 11 108 . 72 350 Глава 6 Avg wait (ms ) % Tota1 Cal l Time 30010 1004 1055 3001 36. 1 18 . 1 17 . 8 14 . 4 Тор 5 T imed Events Event Wai t s T ime ( s ) -------- -------- 1 15 14 4 30 15 15 12 AQPC id1e heartbeat redo informe r LGWR wor ke r group idle lreg timer 13 . 4 11 CPU time В справоч н ы х целях в отчет была включена конфи гурация SGA, но в дан ном случае интерес представляет следующая информация : • затраче нное время ( Elapsed time) или время базы дан н ых ( D B time ) , равное приблизительно 1 5 секундам (0,25 м инуты) ; • 1 667 полных разборов ( H ard parses), выполненных в секунду; • использованное время процессара (CPU time), составляющее l l секунд. Теперь если бы мы запустили две таких программ ы одновременно, то могли бы ожидать увеличения скорости полного разбора примерно до 3300 разборов в секунду (в конце кон цов, мы располагаем двумя процессорами) и п отребляемого времени процессара - до 22 секунд. Давайте посмотрим: 0 . 2 7 (mins ) Av Act Ses s : 0 . 4 4 (mins ) DB CPU : E l apsed : DB time : Load Pro f i l e 1.6 О . 4 1 (mins ) Per Second Per Transaction 6, 2 59 . 8 3 , 125 . 6 33, 385 . 3 1 6 , 669 . 7 Parses : Hard parses : Per Ca l l Per Ехес I n s t ance E fficiency I ndicators Bu ffer Nowai t % : Buffer H i t %: %: Library H i t Execute to Parse % : Parse CPU to Parse Elapsd % : Redo NoWai t % : 100 . 00 9 9 . 9 9 Opt imal W/A Ехес % : 60 . 0 3 Soft Parse % : 0 . 06 Latch Hit % : 96 . 28 % Non-Parse CPU : Тор 5 T imed Events ------------------ Event - - - ----- Waits - - -- -- - - - - - - --- --- - - - ----- CPU time LGWR wor ke r group i d l e heartbeat redo i nforme r l reg timer latch : shared pool T ime ( s ) --- - - - 100 . 00 100 . 00 50 . 07 98 . 4 1 15 . 06 Avg wa i t (ms ) -- 32 . 7 23 18 15 5 15 , 076 % Total Cal l T ime 16 15 15 о 876 1005 3001 о 22 . 8 21 . 8 21 . 7 .б Легко заметить, что скорость выполнения пол н ых разборов слегка возросла, а время процессара увеличилось более чем в два раза. В чем дело? Ответ кроется в реа­ лизации защелкивания в Oracle. На этой многопроцессорной машине невозможность Б л окировка и за щ ел ки вани е дан ных 351 немедленного получения защелки приводит к раскрутке. Сама раскрутка потребляет время процессора. Процесс 1 много раз п ытался получить защелку на разделяемом пуле всего лишь для того, чтобы выяснить, что эту защелку удерживает процесс 2 ; в итоге процессу 1 пришлось выполнять раскрутку и ожидать освобожден ия защелки (загружая при этом процессор) . Для процесса 2 справедли во обратное утверждение: он многократно обнаруживал, что процесс 1 удерживает защелку на необходимых ему ресурсах. Таким образом, значительная часть процессориого времени бьша потрачена не на выполнение реальной работы , а на ожидание, пока ресурс станет доступным. Если пролистать отчет Statspack до раздела Latch S l eep B r e a kdown ( П рекращение бездействия защелки), можно найти следующие сведен ия : Latch Name Requests Misses S leeps Gets shared pool 2, 2 9 6 , 0 4 1 75, 240 1 5 , 2 67 60 , 1 6 5 Обратили внимание н а число 1 5 267 в столбце SLEEPS? Оно довольно близко со­ ответствует количеству ожидани й (указанному в столбце Wa i t s ( ) и строке l a t ch : s h a r e d p o o l (защелки: разделяемы й пул ) ) в предыдущем отчете Т о р 5 T im e d Event s (5 первых событи й , касающихся времени). На заметку! Количество засыпаний (sleep) близко соответствует количеству ожидани й ; это может вызвать недоумение. Почему не точно соответствует? Причина в том , что действие по получению снимка не является атомарным; во время его выполнения запускается пос­ ледовательность запросов, собирающих статистические сведения в таблицы, и каждый запрос начинается в слегка отличающийся момент времени . Таким образом , показатели события ожидания были собраны чуть раньше сведений о защелкиван и и . Н а ш отчет L a t ch S l e e p B r e a kdown показывает количество раз, когда м ы п ы ­ тались получить защелку и не смогл и , оказавшись в цикле раскрутки . Это значит, что отчет Тор 5 T ime d Event s отражает только верхушку айсберга, касающегося проблем с защелками - 75 240 неудачных попыток (означающих раскрутку с повто­ рением попыток получить защелку) в нем не отображен ы . П осле изучения данного отчета можно и не догадаться о наличии проблемы с пол н ы м разбором , хотя она является весьма серьезной . Для выполнения 2 единиц работы понадобилось более 2 единиц загрузки процессора. Это всецело обусловлено потребностью в ресурсе сов­ местного использования - разделяемом пуле. Такова природа защелкивания . Как видите , диагностирование проблем, связанных с применением защелок, мо­ жет оказаться очен ь сложной задачей , если только не уяснить механи ку их реали ­ зации . П р и беглом просмотре раздела Тор 5 T imed Event s отчета Statspack можно упустить из виду тот факт, что мы имеем дело с крупной проблемой масштабирова­ ния. Вскрыть существование этой проблемы позволит только более глубокий анал из раздела с и нформацией о защелках в отчете Statspack. Кроме того, обычно невозможно определить, сколько процессориого време н и используется системой из-за раскрутки - в этом тесте с двумя пользователями мож­ но выяснить только то, что обработка заняла 23 секунды процессориого времени и 75 240 раз не удалось получить защелку на разделяемом пуле. М ы не знаем, сколько раз выполнялась раскрутка при каждой неудачной попытке получения защелки , по­ этому нет реального способа измерить процессорное время , затраченное на раскрут- 352 Глава 6 ку, и п роцессорное время , в течение которого производилась полезная обработка. Чтобы вывести такую информацию, необходимо располагать несколькими измери­ тельными точками. Н а основе результатов тестирования , поскольку сравнение выполняется с одно­ пользовательским случаем, можно заключить, что около 1 секунды процессориого време н и было потрачено на раскрутку для получения защелки в ожидании осво­ божден ия данного ресурса. Мы можем прийти к этому заключению, т. к. знаем, что одному пол ьзователю требуется только 1 1 секунд процессориого времени, поэтому двум пол ьзователям понадобится 22 секунды , а 23 (общее количество секунд про­ цессориого времени) минус 22 равно 1 . Тестирование с переменньtми привязки Теперь рассмотрим ту же ситуацию, что и представленная в предыдущем разделе, но на этот раз с применением программы , которая во время своей работы использует значительно меньше защелок. В этой Jаvа-программе будут задействованы перемен­ ные привязки. Для этого мы замен им тип S t a t ement типом Prepa redS t a t ement, проведем разбор одиночного оператора I N S E RT , а затем привяжем и многократно выполним PreparedS t a t ement в цикле: import j ava . sql . * ; puЫ i c c l a s s instest { static puЬ l i c void mai n ( St r i ng args [ ] ) throws Exception { System . out . println ( " s tart " ) ; DriverManager . regi sterDriver ( new oracle . j dЬc . driver . OracleDriver ( ) ) ; Connect i on conn = DriverManager . getConnection ( " j dЬc : oracle : thin : @ heesta : 1 5 2 l : ORA1 2CRl " , " s cott " , " t iger " ) ; conn . s e tAutoCommi t ( false ) ; PreparedStatement pstmt conn . prepareStatement ( " insert into " + args [ O ] + " (х) values ( ? ) " ) ; = for ( int i = О ; i < 2 5 0 0 0 ; i + + { p s tmt . se t i n t ( 1 , i ) ; p s tmt . executeUpdate ( ) ; } conn . commit ( ) ; conn . cl os e ( ) ; Sys tem . out . println ( "done " ) ; Давайте взглянем на отчеты Statspack для одного и двух пользователей, как это было сделано в примере без переменных привязки . Результаты существенно отлича­ ются . Вот отчет для одного пользователя: Elapsed : О . 07 (шins ) Av Act Sess : 0.6 DB time : 0 . 0 4 (mins ) 0 . 0 3 (mins ) DB CPU : Б ло кировка и за щ ел кивание данн ых Begin Cache S i zes End 2 , 6 5 6М 6 4 0М Buffer Cache : Shared Pool : Std Block S i z e : Log Bu ffer : Per S econd Per Transaction Parses : 1 58 . 5 317 . 0 Hard parses : 29 . 8 59 . 5 Load Profile 353 8К 1 4 , 8 08К Per Ехес Per Cal l Instance Effi ciency I ndicators Buffe r Nowa i t g, . 1 0 0 . 0 0 Redo NoWait % : Buffer Hit % : 9 8 . 9 9 Optimal W/A Ехес % : Library Hit % : 96. 14 Soft Parse % : 97 . 72 Execute t o Parse % : Latch H i t % : Parse CPU to Parse Elapsd % : 87 . 10 % Non- Parse CPU : о . Тор 5 Timed Events ------------------ Event ------------------------------ Waits T ime (S) -------- -------- 1 2 4 12 30 б AQPC idle l reg t ime r heartbeat redo informe r LGWR wor ker group idl e 4 4 100 . 00 100 . 00 8 1 . 23 100 . 00 7 1 . 58 Avg wai t ( ms ) % Total Ca l l T ime 30004 3004 1006 331 66 . 6 13 . 3 8.9 8.8 1 CPU time 2.1 Изменение довольно резкое: умен ьшение процессарного времени с 1 1 секунд в примере без перемен н ых привязки до 1 секунды в текущем примере. Количество полных разборов, выпол няемых в секунду, снизилось с 1 667 до почти 29 ( и , зная внутреннюю работу пакета Statspack, я могу утверждать, что большая их часть при­ ходится именно на него) . Даже общее время обработки значительно уменьшилось с почти 1 5 до 4 секунд (0,07 минуты) . Без применения переменных привя зки десять одиннадцатых процессарного времени тратилось на разбор SQL- кoдa ( 1 секунда против 1 1 ) . Это было связано не только с защелками , т. к. без использования пере­ менных привязки значительная часть процессарного времени тратилась на разбор и оптимизацию SQL-запросов. Разбор SQL-операторов требует очен ь большой загруз­ ки процессора, но вынуждать процессор тратить десять один надцатых своего време­ н и на выполнение каких-то действий (разбор) , которые в действительности для нас бесполезны - работы , которую делать не нужно - весьма расточительно. Прогон теста для двух пол ьзователей показывает, что результаты продолжают улучшаться: Elapsed : DB t ime : 0 . 0 8 (mins ) Av Act Ses s : 0 . 0 7 (mins ) DB CPU : 0.9 0 . 0 7 (mins ) Per S econd Per Transaction Parses : 25. 6 42 . 7 нard parses : 0.8 1.3 Load Profile Per Ехес Per C a l l 354 Глава 6 I n s tance E f f i ciency I ndicators Buffer Nowai t % : 1 0 0 . 0 0 Redo NoWai t % : Buffer Hit % : 9 9 . 9 3 Opt imal W/A Ехес % : Library Hi t % : Soft Parse % : 99 . 97 Execute to Parse % : 99 . 74 Latch Hit % : Parse CPU to Parse E lapsd % : 1 0 0 . 0 0 % Non-Parse C PU : 100 . 00 100 . 00 96 . 8 8 99 . 99 99 . 66 Тор 5 T imed Events Avg wa it (ms ) % Total Ca ll Time 30012 1010 3000 74 . 6 10 . 0 7.5 7.3 .3 ------------------ Event -------------- Waits - ------------- - - - - ------ AQPC idle heartbeat redo i n fo rme r l reg t ime r CPU t ime log f i l e pa ra l l e l write 1 4 1 22 Time ( s ) - 30 4 3 3 о -- -- -- 5 Время загрузки процессара увеличилось примерно в 2-3 раза по сравнению с тестовым сценарием, в котором участвовал оди н пользователь. Н а заметку! Из-за округления 1 секунда процессорного времени в действительности пред­ ставляет значение из диапазона от О до 2, а 3 - значение между 2 и 4. Более того , процессорное время , потрачен ное двумя пользователями в случае применения переменных привязки , гораздо меньше полови ны процессарного вре­ мен и , которое потребовалось одному пользователю в ситуации без переменных при­ вязки! Когда я просмотрел раздел, посвя щенный защелкам, в этом отчете Statspack, то обнаружил, что конкурен ция за разделяемый пул и библиотечный кеш была на­ столько низкой, что она даже не стоила отражен ия в отчете. На самом деле более тщательное изучение отчета показала, что защелка разделяемого пула запрашива­ лась 50 5 1 1 раз вместо более 2,2 миллиона раз в ходе выполнения предыдущего теста с двумя пользователям и без переменных привязки : Latch Name Requests Misses S l eeps Gets shared pool 50, 511 48 1 47 Сравн ение производительностиjмасштабир уемости В табл . 6 . 1 приведена сводка по затратам процессарного времени в каждой реа­ л изац и и , а также показатели защелкивания при увеличе н и и количества пользова­ телей свыше двух. Как видите , решение, в котором используется меньше защелок, будет намного лучше масштабироваться с ростом числа пользователей . И нтересно отметить, что l O пользователей, применяющих переменные привязки (и в результате очень мало запросов защелок) , используют столько же аппаратных ресурсов (центральный процессор) , сколько и 1 пол ьзователь, который не приме­ няет переменные привязки (т.е. злоупотребляет защелкой или обрабатывает больше, чем требуется) . Б локировка и за щ елки ван и е дан н ых 355 Таблица 6. 1 . Сравнительные данные по использованию п роцессора с переменными привязки и без них Количество пользова· теле й Время процессора в секундах/об щее время в минутах Без переменных привязки 1 С пере- менными привязки Количество запросов за щелки на разделяемом пуле Без переменных привязки С пере- менными привязки Счетчик ожидания защелок/время ожидания в секундах Без переменных привязки * С пере- менными привязки 1 1 /0,22 1 /0,04 о о 0/0 0/0 > 2,2 млн. > 50 тыс. 1 5,0 тыс./0 0/0 2 23/0,44 3/0,07 3 35/0,65 4/0, 1 0 > 3 , 5 млн. > 75 тыс. 1 9 , 1 ТЫС./1 0/0 4 47/0,89 4/0, 1 3 > 4,7 млн. > 95 тыс. 33,9 ТЫС./1 0/0 5 58/ 1 , 1 3 4/0 , 1 5 > 5,9 млн. > 1 26 тыс. 55,8 ТЫС./3 1 0/0 6 70/1 ,35 6/0, 1 8 > 7, 1 млн. > 1 52 тыс. 6 1 , 1 ТЫС./3 22/0 7 82/1 ,56 7/0 , 2 1 > 8 , 3 млн. > 1 76 тыс. 70,0 ТЫС./3 23/0 8 90/2,55 7/0,23 > 9,5 млн. > 20 1 тыс. 1 21 ,3 тыс./42 28/0 9 1 05/2,21 8/0,27 > 1 0,7 млн. > 226 тыс. 1 1 1 ,6 ТЫС./1 3 25/0 10 1 1 5/2,49 8/0,28 > 1 1 ,9 млн . > 252 тыс. 1 23, 1 ТЫС./1 7 4 1 /0 * Прнмечанне: в столбце "Без переменных привязки" значения счетчика ожидания защелок выражается в тысячах, а в столбце "С переменными привязки" - в единицах. Проанализировав результаты дЛЯ 1 0 пользователей , вы увидите , что отказ от пе­ ременных привязки приводит к использованию почти в 1 4 раз больше процессорио­ го времени, а общее время выполнения увеличивается , по крайней мере, в 9 раз по сравнению с решением с переменными привязки . Чем больше со временем добавля­ ется пользователей , тем дольше каждому из них приходится ожидать освобожден ия защелок. Среднее время ожидан ия защелок увеличивается с 0,6 секунды на сеанс (3 секунды ожидан ия на 5 сеансов) для 5 пользователей до 1 ,7 секунды на сеанс для 1 0 пользователей . Однако реализация , которая избегает злоупотребления защел ка­ ми, не испыты вает н и какого отри цательного влияния при масштабировани и в сто­ рону увеличения числа пользователей . Семафоры Семафор (mutex) представляет собой механизм сериал изац и и , во м ногом по­ добный защел ке ; в действительности mutex означает mutual exclusion ( взаим ное ис­ ключение). Это еще оди н и нструмент сериал изации , приме няемый базой данн ых , который был введен в версии Oracle 1 0g Release 1 и испол ьзуется вместо традици­ онных защелок во многих местах сервера. Семафор отличается от защелки тем , что его реализация еще более легковесна. Он требует меньше кода дЛЯ реализации примерно одну пятую объема инструкций (что дает в результате меньше обращений к процессору) , и также требует меньше памяти - приблизительно одну седьмую часть. В дополнение к легковесности семафор в некоторых отношениях чуть менее функционален. 356 Глава 6 П одобно тому, как блокировка с очередью намного сложнее защелки , защелка сложнее семафора. Но, как и при сравнени и блокировки с очередью и защелки , в некоторых случаях защелка может делать больше, чем семафор (как и блокировка с очередью в ряде ситуаци й позволяет сделать больше, чем защел ка) . Это значит, что не каждая защелка может или должна быть заменена семафором , равно как и не каждая блокировка с очередью - защелкой . Ч итая о семафорах в разных источни ках, всегда помните, что они явля ются лег­ ковесным механизмом сериал изации . Они делают возможной более высокую мас­ штабируемость, чем защелка (подобно тому, как защелки обеспечи вают большую масштабируемость, чем блокировки с очередью) , но все равно остаются механизмом сериализации. Если вы можете обойтись без действия , требуюше rо применения се­ мафора, то обычно должн ы так и поступать по той же самой причине, по которой , где только возможно, следует избегать запрашивания защелки . Б локировка вручную и блокировки , определенные пользователе м До сих пор мы рассматривали главным образом блокировки , которые Oracle уста­ навли вает автоматически . При обновлени и таблицы Oracle помещает на нее блоки ­ ровку ТМ , чтобы предотвратить удаление таблицы другими сеансами (или, фактичес­ ки , выпол нять большинство операций DDL). Существуют блокировки ТХ, которые остаются на различных модифицируемых нами блоках, что позволяет другим пользо­ вателям выяснить, какими данными мы владеем. База данн ых задействует блокиров­ ки D D L для защиты объектов от изменения, пока мы сами их изменяем. Она внут­ ренне использует защелки и блокировки для защиты собствен ной структуры. Давайте посмотрим, как можно вмешаться в некоторые из этих действий по блокировке . Мы располагаем перечисленными н иже возможностями: • • блокировка данных вручную с помощью SQ L-oпepaтopa; создание собственных блокировок посредством пакета овмs _LОСК. В последующих разделах кратко обсуждаются причин ы , по которым могут требо­ ваться эти возможности . Блокировка вручную Фактически м ы уже видели пару случаев, когда может понадобиться ручная бло­ кировка. Оператор S ELECT . . . FOR U P DAT E является доминирующим методом бло­ кирования данных вручную. Мы применяли его в предшествующих примерах для предотвращен ия проблемы потерян ных обновлений, когда один сеанс мог бы пере­ записать изменения, внесенные другим сеансом . Он использовался в качестве ме­ тода сериализации доступа к записям подробностей, чтобы обеспечить соблюдение бизнес-правил (скажем, в примере графика резервирования ресурсов в главе 1 ) . Данные можно также блокировать вручную с помощью оператора LOCK TABLE. Этот оператор применяется редко, из-за круп нозернистости такой блокировки . Он просто блокирует всю табли цу, а не строки в ней. Есл и вы начинаете изменять строки, они будут заблокированы обычным образом . Следовательно, это не метод, позволяющий сэкономить ресурсы (как это может быть в других СУБД). Оператор LOCK TABLE I N EXCL U S I VE MODE можно испол ьзовать при реал изаци и объемного пакетного обновления , которое будет воздействовать на большинство строк в конк- Бл окировка и за щ елки ван и е дан ных 357 ретной табл ице, и нужна уверенность в том , что никто не сможет вас заблокировать. Блокируя таблицу в такой манере, вы можете гарантировать, что обновлен ие сможет выполнить всю свою работу, не оказавшись заблокированным другим и транзакция­ ми. Тем не менее, приложения , содержашие оператор LOCK TABLE, встречаются до­ вольно редко. Создание собственных блокировок В действительности через пакет DBMS LOCK СУБД Oracle предоставляет разра­ ботчикам механизм блокирован ия в порядке очереди , которы й она применяет внут­ ренне. Ч асто возни кает вопрос, зачем может понадобиться создание собствен н ых блокировок. Как правило, ответ зависит от кон кретного приложе н ия . Например, этот пакет может требоваться для обеспечения последовательного доступа к ряду внешних ресурсов Oracle. П редположим, что вы испол ьзуете процедуру UTL_F I LE , которая позволяет выполнять зап ись в файл в файловой системе сервера. Вы могли разработать обшую процедуру подготовки сообщения, которую каждое приложение вызывает для записи сообщений. П оскольку файл я вляется вне ш н им , Oracle не бу­ дет координировать множество пользователей, которые одновременно п ытаются его измен ить. В этой ситуаци и пригодится пакет о в м s _ LOCK. Теперь, прежде чем от­ крывать, выполнять запись и закрывать файл , вы будете запраш ивать монопольную блокировку от имени файла, а после закрытия файла - вручную освобождать эту блокировку. В результате в кажды й момент времени только один пользователь смо­ жет зап исы вать сообщение в этот файл . Запросы от всех остальных пол ьзователе й будут помещены в очередь. П акет овмs LOC K позволяет освобождать блокировку вручную по окончании работы с объектом , автоматически при выполнении фикса­ ции или даже сохранять ее на все время нахождения в системе. Р ез ю ме Эта глава содержит огромн ы й объем материала, который временами способен довести до головной бол и . Хотя блокирование само по себе прямол и нейно, подоб­ ное нельзя сказать о некоторых его побоч н ых эффектах. Одн ако очен ь важно по­ нимать эти проблемы. Н апример, если вы не знаете о бло кировке таблицы, приме­ няемой Oracle для поддержки отношения внешнего ключа, когда внешний ключ не индексирован , то ваше приложение будет страдать от н изкой производительности . Если вы не понимаете, каким образом просматривать словарь данных, чтобы уви­ деть, кто кого блокирует, то можете н икогда не выяснить этот вопрос . В ы п росто придете к выводу, что иногда база данных зависает. И ногда я жалею, что не получал по доллару каждый раз, когда мне удавалось решать неустранимую проблему зависа­ н ия , просто запуская запрос для выявления неиндексированных внешних ключей и подсказывая о необходимости их и ндексации . Я стал бы богачом . ГЛ А В А 7 П ар аллел и з м и м н о г ов е р с ио нн о с т ь к ак констатировалось в предыдуще й главе , одной из кл ючевых проблем при разработке многопользовательских приложений, работающих с базами дан н ых, является доведение до максимума уровня п араллелизма доступа, но в то же самое время и обеспечение дJIЯ каждого пользователя возможностей чтения и модифика­ ции данных в согласованной манере. В этой главе мы детально рассмотрим, каким образом Oracle достигает многовереионной согласованности чтения, и что это означа­ ет для разработчика. Будет также представлен новый термин согласованность записи, который используется дJIЯ описания работы Oracle не только в среде чтения с согла­ сованностью прочитанных данных, но также в смешанной среде чтен ия/записи. Понятие управл ен ия параллелизмом Управление параллелизмом это коллекция фун кц и й , предоставляе м ых базой дан н ых дJIЯ разрешения многим пользователям одновременного доступа к дан н ы м и и х модификации . В предыдущей главе отмечалось, что блокировка это оди н из основн ых механизмов, посредством которого Oracle регули рует параллел ьн ы й до­ ступ к разделяемым ресурсам базы данных и предотвращает взаим ное влияние друг на друга параллельна выполняющихся транзакций базы данн ых. П одводя краткие итоги , можно сказать, что Oracle применяет разнообразн ые блоки ровки , включая перечисленные н иже . - - • Блокировки ТХ (транзакции). Эти блокировки устанавливаются на протяжен и и транзакции, модифицирующей данные. • Блокировки ТМ (помещение в очередь DML) и блокировки DDL. Эти блоки ­ ровки гарантируют, что структура объекта не изменится во время модифика­ ции его содержимого (блокировка ТМ) или структуры самого объекта (блоки­ ровка DDL). • Защелки и семафоры. Это внутренние блокировки , используемые Oracle при посредничестве доступа к разделяемым структурам данных. На защелки и се­ мафоры в этой главе мы будем ссылаться просто как на защелки , хотя в зави­ симости от версии Oracle они могут быть реал изованы в виде семафоров опе­ рационной системы. 360 Глава 7 В каждом случае с установкой блокировки связаны минимальные накладные расходы. Блокировки ТХ исключительно масштабируемы в отношен и и как произ­ водительности , так и кардинальности. Блокировки ТМ и D D L применяются в на­ и менее ограничивающем режиме всякий раз, когда это возможно. Защелки и оче­ реди я вляются очень легковесными и быстрыми (из них очереди немного сложнее, хотя обладают более развитыми возможностями). Проблемы возникают только из-за неудачно спроектированных приложений, которые удерживают блокировки дольше, чем необходимо, и вызывают блокирован ие в базе данных. Если вы аккуратно проек­ тируете свой код, то механ измы блокировки Oracle позволят строить масштабируе­ мые приложен ия с высокой степенью параллелизма. Н а заметку! Выше исnользуется формулировка "дольше , чем необходи мо". Это не зна­ чит, что вы должны nытаться зафиксировать (завершить) транзакцию как можно скорее. Транзакции должны длиться столько, сколько нужно, но не дольше. То есть транзакция является еди ницей работы - либо все , либо ничего. Вы должны осуществлять фиксацию, когда единица работы завершена, но не раньше и не nозже! Однако поддержка параллелизма в Oracle не ограничивается эффекти вной бло­ кировкой. В Oracle реализована архитектура многоверсионности (представленная в главе 1 ) , которая обеспечивает управляемы й , но с высокой степенью паралл елизма доступ к данным. М ноговерсионность характеризует способность Oracle параллель­ но материализавы вать множество версий данных и я вляется механизмом , с помо­ щью которого Oracle обеспечивает согласованные по чтению представления дан ных (т.е. согласованные результаты на определенный момент времени). Довольно прият­ н ы й побочный эффект многоверсионности состоит в том , что процесс чтения дан­ ных н икогда не блокируется процессом записи данных. Другими словами , операции записи не блокируют операции чтения . В этом заключается одно из фундаменталь­ ных отличий Oracle от других баз дан ных. Запрос, которы й только читает информа­ цию, в Oracle н и когда не будет блокироваться , он никогда не попадет в состояние взаимоблокировки с другим сеансом и ни когда не выдаст ответ, который в базе дан ­ ных отсутствует. На заметку! Во время обработки расnределенной двухфазной фиксации (Two Phase Commit) существует короткий nериод, когда Oracle будет n редотвращать достуn no чтению к ин­ формации. Поскольку эта обработка nредставляет собой редкое и необычное явление ( nроблема касается только заnросов, которые заnускаются между фазами nодготовки и фи ксаци и и nытаются nрочитать данные до nостуnления команды фиксации ) , nодробно здесь она не рассматривается . Модель многоверсионности Oracle для обеспечения согласованности чтения по умолчан и ю применяется на уровне операторов (для каждого запроса) и также мо­ жет применяться на уровне транзакций . Это знач ит, что каждый оператор SQL, от­ правленный базе данн ых , видит согласованное по чтению представлен ие базы - по крайней мере . Если такое согласованное по чтению состояние базы данных необхо­ димо получить на уровне транзакции (набора SQ L-операторов) , то это также можно сделать, как будет показано в разделе " Уровень изоля ции S E RIAL I ZABLE " далее в главе. П араллели з м и мно г оверсионность 361 Основным назначением транзакции яRЛЯется перевод базы из одного согласован­ ного состояния в другое . В стандарте I SO языка SQL описаны разнообразные уровни изоляции транзакций, которые определяют, насколько чувствительна одна транзак­ ция к изменениям, произведенным другой транзакцией . Чем выше уровень чувстви­ тельности , тем выше степень изоляции, которую база данных должна обеспечивать между транзакциям и , выполняемыми ваш им приложением. В следующем разделе мы посмотрим, как через архитектуру м ноговерсионности с абсолютно м и н и маль­ ным блокированием Oracle может поддержи вать каждый из определенных уровней изоляции. У р о вни и золя ц и и транзак ц ий Стандарт ANSI/I SO языка SQL определяет четыре уровня изоляции транзакци й с разными возможн ыми исходами для одного и того ж е сценария транзакц и й . То есть одна и та же работа, выполненная в той же манере с теми же самыми входными данными, в зависимости от выбранного уровня изоляции может приводить к полу­ чению разных ответов. Эти уровни изоляции определен ы в терминах трех " феноме­ нов", которые либо разрешены, л ибо запрещены на заданном уровне изоляции. • Грязное чтение (dirty read). Смысл этого термина так же плох, как он звучит. Вам разрешено читать незафиксированные, или грязные, дан ные. Вы достига­ ете такого эффекта, просто открывая файл операционной системы, куда кто­ то другой производит запись или чтение, какие бы дан н ые там не оказал ись. При этом не обеспечивается целостность данных, нарушаются внешние ключи и игнорируются ограничения уникальности . • Невоспроизводимое чтение (nonrepeataЬie read). Это означает, что есл и вы чи­ таете строку в момент времен и T l и затем считы ваете ее повторно в момент времени Т2, то за данный промежуток времени строка может измениться , ис­ чезнуть, обновиться и т.д. • Фантомное чтение (phantom read). Это значит, что если вы запустили запрос в момент времен и T l , а затем выполните его повторно в момент времени Т2, то в базе данных могут поя виться дополнительные строки , что повлияет на полу­ ченные результаты . Отличие фантомного чтения от невоспроизводимого чте­ ния состоит в том , что уже прочитанн ые данные не изменяются , но критери ю запроса удовлетворяет больший объем данных, ч е м было д о того. На заметку! Стандарт ANSI/ISO языка SQL оnределяет характеристики уровня транзакции, а не характеристики на уровне и ндивидуальных оnераторов . В nоследующих разде­ лах мы будем исследовать изоляцию уровня транзакци й , а не только изоляцию уровня оnераторов. Уровни изоля ции SQL определены на основе того, допускают л и они каждый из описан ных ранее феноменов. И нтересно отметить, что стандарт SQL не н авязывает специфичную схему блокирования и не регламентирует определенное поведение, а взамен описывает уровни изоляции в терминах этих феноменов, делая возможн ым существование разнообразных механ измов блокирован ияjпараллелизма (табл . 7 . 1 ) . 362 Глава 7 Таблица 7. 1 . Уровни изоляции ANSI Уровен ь изоляции Грязное чтение Невоспроизводимое чтение Фантомное чтение READ UNCOММITTED Разрешено Разрешено Разрешено Разрешено Разрешено READ СОММ I ТТЕD RE PEATAВLE READ Разрешено SERIALI ZAВLE В Oracle Я ВНО поддерживаются уровни ИЗОЛЯЦИИ READ СОММIТТЕD И SERIALI ZAВLE в том виде , как они определены стандартом . Однако это еще не все. Стандарт SQL п ытался установить уровни изоляции , которые допускают разнообразные степени согласованности запросов, выпол няемых на каждом уровне. RE PEATABLE READ ­ это уровен ь изоля ции, при котором стандарт SQL требует гарантии согласованно­ го по чте н и ю резул ьтата, получаемого из запроса. В определении этого стандарта READ COMM I TT E D не дает согласованные результаты , а READ UNCOMMITTED является уровнем, испол ьзуемым для обеспечения неблакирующих чтений. Тем не менее, в Oracle уровень READ COMM I TT E D обладает всеми атрибутами, не­ обходимыми для достижения согласован ных по чтению запросов. Во многих других базах данных запросы READ COMM I T T E D могут и будут возвращать ответы, которые н и когда не существовали в базе ни в какой момент времени. Более того, Oracle так­ же п оддерживает дух уровня READ UNCOMM I T T E D . Цель предоставлен ия грязного чтения заключается в обеспечен и и неблаки рующего чтения, когда запрос не блоки­ руется и не блокирует обновления некоторых данных. Однако для достижен ия этой цели Oracle не нуждается в грязных чтениях и не поддержи вает их. Грязные чтения вынужден ы реализовывать другие СУБД, чтобы предоставить возможность неблаки­ рующих чтений. Вдобавок к перечисленным выше четырем уровням изоляции SQL в Oracle пред­ лагается еще оди н уровен ь - READ ONLY. Транзакция READ ONLY является эквива­ лентом транзакции RE P EATABLE READ ил и S E R IAL I ZAB L E , которая не выполняет никаких модификаций в SQL. Транзакция , применяющая уровень изоляции READ ONL У, видит только те изме­ нения , которые был и зафиксированы на момент ее начала, но вставки , обновления и удале н ия в этом режиме не разрешены (другие сеансы могут обновлять данные, но не транзакция READ ONL У ) . Испол ьзуя этот режим , можно достичь уровней изо­ ляции RE PEATABLE READ и S ERIAL I ZABLE. Давайте теперь посмотрим, как и менно м ноговерсионность и согласованность чтения вписывается в схему изоляции , и каким образом базы дан ных, не поддержи­ вающие м ноговерсионность, доби ваются тех же результатов. Эта и нформация будет п олезна все м , кто работает с другим и базами данн ых и уверен , что понимает, как должн ы работать уровни изоляции. И нтересно также увидеть, каким образом стан­ дарт, предназначенный для устранен ия различий между базам и дан ных - AN SI/I SO SQL - в действительности позволяет делать это. Стандарт, хотя он и очень детал ь­ н ы й , может быть реализован совершенно разны м и способами . Паралл ел изм и мно г оверсионность 363 Уровень ИЗОЛЯЦИИ READ UNCOММITТED Уровень изоляции READ UNCOMM I T T E D допускает грязн ые чтения. В Oracle гряз­ ные чтения не применя ются и даже не разрешены. Основная цель уровня изоляции READ UNCOММ I T T E D - предоставить основанное на стандартах определение, которое обслуживает неблаки рующие чтения . Как уже было показано, Oracle обеспечи вает неблакирующие чтения по умолчан ию. Вы бы с трудом решились на блокировку запроса S ELECT в базе данных (как отмечалось ранее, и меется специальн ы й случай распределенной транзакции) . Каждый одиночный запрос, будь то SELECT, I N S ERT , U P DAT E , M E RG E или D E L E T E , вы полняется в согласован ной по чте н и ю манере . Причисление оператора U P DAT E к запросам может показаться забавным, но это так и есть. Операторы U P DAT E содержат два компонента: компонент чтения, определя­ емый конструкцией WHERE, и компонент записи, определяемый конструкцией S ET . Операторы U P DATE выполня ют чтение и запись в базу данных; такой возможностью обладают все операторы D M L. Случай однострочного оператора I N S E RT , исполь­ зующего конструкцию VALUE S , я вляется единствен н ы м исключением - операторы подобного рода не имеют компонента чтения , а только компонент записи. В главе 1 метод обеспечен ия согласованного чтения Oracle был продемонстри­ рован на примере простого однотабличного запроса, который извлекал строки , уда­ ленные после открытия курсора. Теперь мы обратимся к реальному примеру и пос­ мотрим, что происходит в Oracle за счет применения м ноговерсионности , а также каким образом ведут себя в аналогичной ситуаци и другие базы данн ых. Начнем с той же самой элементарной таблицы и запроса: create taЬle accounts ( account_nшnЬer nшnЬer p rima ry key , account bal ance nшnЬe r n o t nul l ); select sum ( account_ba lance ) from account s ; Предположим , что перед началом запроса м ы имеем данные, приведеиные в табл. 7.2. Таблица 7 . 2 . Таблица ACCOUNTS перед модификацией Номер счета Бал анс счета 1 23 $500.00 2 456 $240. 25 342 023 987 $ 1 00.00 Строка Теперь наш оператор S E LECT начинает свое выполнение и читает строку 1 , стро­ ку 2 и т.д. На заметку! В этом примере я вовсе не п редполагаю, что строки размещаются на диске в каком-нибудь физическом порядке . На самом деле в табли це не существует первой, второй или последней строки . Есть п росто набор строк. Здесь мь1 предполагаем , что строка 1 в действительности означает "первую прочитанную строку", строка 2 "вторую прочитанную строку" и т.д. - 364 Гл�ва 7 В какой -то момент посреди запроса другая транзакция переводит $400 со счета 1 23 на счет 987. Эта транзакция делает два обновления, но не фи ксируется . Таблица теперь выглядит так, как показано в табл . 7 . 3 . Таблица 7 . 3 . Таблица ACCOUNTS в о время модификации Строка Номер счета Баланс счета 1 23 Значение ( $500 .00) изменилось на $ 1 00.00 2 456 $240.25 342 023 987 Значение ($1 00.00) изменилось на $500.00 Блокирована ? х х И так, блокированы две строки . Если кто-то попробует обновить их, эта попытка будет заблокирована. До сих пор наблюдаемое нами поведение я вляется более или менее согласованным во всех базах данных. Отличия начнут проявляться в том, что произойдет, когда запрос доберется до блокированных данных. Когда функционирующий запрос достигает блока данных, содержащего блокиро­ ванную строку (строку 342 023) в н ижней части таблицы , он обнаружит, что данные в этой строке изменились с момента его запуска на выполнение. Для предоставле­ н ия согласованного ( корректного) ответа Oracle создаст в этой точке коп ию блока, в котором находится данн ая строка, в том виде, в каком он существовал на момент начала запроса. То есть будет прочитано значение $ 1 00.00 - значение, которое было при запуске запроса. В сущности Oracle обходит модифицированные данные, в про­ цессе чтения реконструируя их из сегмента отмены ( который также называется сег­ ментом отката и детально обсуждается в главе 9 ) . Согласованный и корректн ый ответ возвращается обратно без ожидания , пока транзакция будет зафиксирована. Теперь база данн ых, допускающая грязное чтение, просто возвратит значение, которое обнаружит в строке для счета 987 в момент ее чтения - в данном случае это $500.00. Запрос учтет переведенную сумму $400 дважды . Таким образом , он не толь­ ко выдаст неправильный ответ, но также вернет общую сумму, которая н икогда не существовала в базе данн ых ни в оди н зафиксированный момент времени . В много­ пользовательской базе грязное чтение может быть опасной характеристикой , и лич­ но я совершенно не видел в нем хоть какой -нибудь пользы. Пусть вместо перевода транзакция просто добавила $400 на счет 987. Грязное чтение при няла бы во вни­ мание $400.00 и вьщало бы " правил ьный" ответ, не так ли? Хорошо, предположим, что произошел откат незафиксированной транзакции . М ы получаем сумму $400 .00, которой в действительности н икогда не было в базе дан ных. В ывод из этого такой: грязное чтение - это не средство, а источник неприятнос­ тей . В Oracle оно просто не нужно. Вы получаете все преимущества грязного чтения (без блокирования) безо всяких некорректных результатов. Уровень ИЗОЛЯЦИИ READ СОММI ТТЕD Уровен ь изоляции READ COMM I TT E D устанавливает, что транзакция может читать только те данные, которые были зафиксирован ы в базе данных. Грязные чтения от­ сутствуют. Могут возн и кать невоспроизводи мые чтения (т.е. повторн ые чтения той Параллел и зм и мно г оверси о н н ость 365 же строки могут давать разные ответы в одной и той же транзакции) и фантомные чтения (т.е. вновь вставлен ные и зафиксированные строки становятся видимыми за­ просу, который не видел их ранее в транзакции ) . Вероятно, READ COMM I T T E D я вля ­ ется наиболее часто используем ым уровнем изоляции в о всех приложениях баз дан­ ных, будучи стандартным режимом в базах данных Oracle . Друтие уровни изоляции встречаются редко. Однако обеспечение уровня изоля ции READ COMM I T T E D не так просто, как мо­ жет по казаться . Если вы заглянете в табл. 7 . 1 , то все выглядит простым . Очевидно, с учетом изложенных выше правил запрос, выполняемый в любой базе данных с применен ием уровня изоляции READ COMM I TTED, будет вести себя одинаково? Нет, не будет. Если запросить несколько строк в одном операторе , то почти во всех дру­ гих базах данных в зависимости от реализации изоляция READ COMM I T T E D будет на­ столько же плохой , как и грязное чтение. В Oracle за счет использования многоверсионности и согласованных по чтению запросов ответ, получаем ы й из запроса таблицы ACCOUN T S , для уровня изоля ци и READ COMM I T T E D будет таким же, как в примере с READ UNCOMM I Т T E D . СУБД Oracle воссоздает модифи цирован ные дан н ые в том виде , в каком они были на момент начала запроса, возвращая ответ, которы й содержался в базе данн ых, когда запрос только запускался. Давайте теперь посмотрим, как предшествующий пример может работать в режи ­ ме READ COMM I T T E D в друтих базах данных. Ответ вас удивит. Обратимся к примеру в точке , описанной в предыдущей таблице. • Мы находимся в середине таблицы . М ы прочитали и просумм ировали первые N строк. • Другая транзакция перевела $ 400.00 со счета 1 23 на счет 987. • Транзакция пока не зафиксирована, поэтому строки, содержащие и нформа­ цию о счетах 1 23 и 987, блокированы. М ы знаем , что происходит в СУБД Oracle, когда она добирается до счета 98 7 : о н а обходит модифицированные данные, выясняет, что они должны выглядеть как $ 1 00.00, и завершает обработку. В табл. 7.4 показано, какой ответ может выдать дру­ гая база данных, функционирующая в стандартном режиме READ COMM I TTED. Первое , что следует отметить - другая база данных, добравшись до счета 987, блокирует запрос. Сеанс должен ожидать, находясь на этой строке , пока не будет зафиксирована транзакция , удержи вающая монопол ьную блокировку. Это одна из прич и н , почему м ногие и меют плохую привычку фиксировать каждый оператор вместо того , чтобы обрабаты вать тщательно продуманные транзакции , которые со­ стоят из всех операторов, необходимых для перевода базы данных из одного согла­ сованного состояния в друтое . Обновления служат препятствием для чтений в боль­ шинстве других баз данных. Но что действительно плохо в таком сценарии - то, что мы вынуждаем конечного пользователя ожидать неправильного ответа. Мы получаем ответ, который не существовал в базе данных ни в какой момент времени, как было бы при грязном чтении, но на этот раз еще и заставляем пользо­ вателя ждать этого некорректного ответа. В следующем разделе мы посмотрим, что необходимо предпринять в друтих базах данных, чтобы получить согласованные по чтению, правильные результаты . 366 Глава 7 Таблица 7 .4. Временная ш кала в отличной от Oracle базе данных, использующей изоляцию READ COMMIПED Момент времени Запрос Т1 Читает строку 1 , счет 1 23 , значение = $500. К этому моменту сумма = $500.00 Т2 Читает строку 2, счет 456, значение = $240.25. К этому моменту сумма = $740.25 ТЗ Т4 Обновляет строку 1 (счет 1 23 ) и помещает на нее монопольную блокировку, пре­ дотвращая другие обновления и чтения. Строка 1 содержала $500.00, теперь она содержит $ 1 00.00 Ч итает строку N. Сумма = . . . Т5 Тб Транзакция перевода между счетами Обновляет строку 342 023 (счет 987) и по­ мещает на нее монопольную блокировку. Строка 342 023 содержала $ 1 00.00, теперь она содержит $500.00 Пытается прочитать строку 342 023, счет 987. Обнаруживает, что она блокирована. Сеанс ожидает снятия блокировки с этой строки . Вся обработка в этом запросе оста­ навливается Т7 ТВ Фиксирует транзакцию Ч итает строку 342 023, счет 987. Видит в ней $500.00 и предоставля­ ет окончательный ответ, в котором дважды учтена сумма $400 .00 Важный урок, которы й следует здесь извлечь, заключается в том , что разные базы данных, реализуя один и тот же очевидно безопасный уровен ь изоляции, в со­ вершенно оди наковых обстоятельствах могут и будут возвращать значительно отли­ чающиеся ответы . Важно понимать, что неблакирующие чтения в Oracle обеспечи­ ваются не за счет корректности ответов. И ногда можно не только иметь мед, но и есть его ложкой. Уровень ИЗОЛЯЦИИ REPEATAВLE READ Целью RE PEATAB L E READ я вляется обеспечение такого уровня изоляци и , кото­ рый дает согласованные, корректные ответы и предотвращает потерян ные обнов­ ления . Мы рассмотрим примеры того и другого, увидим , что нужно делать в Oracle для достижен ия этих целей , и исследуем происходя щее в других системах. nолучение согласованного ответа Если установлен уровен ь изоля ции R E P EATAB L E READ, то результаты задан­ ного запроса должны быть согласова н н ы м и на определенный момент времен и . Параллел изм и мно г оверси о н н ость 367 Большинство баз дан ных ( не Oracle) добиваются воспроизводимых чте н и й через применение разделяемых блокировок чте н ия на уровне строки. Это, конечн о же , сн ижает степень параллелизма. Для обеспечения согласованных по чтению ответов в Oracle была выбрана более паралл е льная , многовереионная модель. В Oracle с использованием м ноговерсионности мы получаем ответ, согласован­ ный на момент времен и , когда запрос начал свое выполнение. В других базах дан ­ ных с применением разделяемых бло кировок чтения м ы получаем ответ н а момент завершения запроса - т.е. тогда, когда вообще можно получить ответ (об этом речь пойдет далее в главе) . В системе, в которой дл я обеспечения воспроизводимых чте н и й задействована разделяемая блокировка чтения, мы можем наблюдать в табли це строки , заблокиро­ ванные процессом, которы й их обрабатывает. Таким образом, в приведеином ранее примере при чтении таблицы ACCOUNTS запрос оставляет разделяемые блокировки чтения на каждой строке (табл . 7.5). Таблица 7 . 5 . Временная шкала 1 в отличной о т Orac\e базе данных, использующей изоляцию READ REPEATABLE Момент времени Запрос Т1 Ч итает строку 1 . К этому моменту сумма = $500.00. Устанавливает разделяемую блоки­ ровку чтения на строку 1 Т2 Читает строку 2. К этому моменту сумма = $740.25. Устанавливает разделяемую блоки­ ровку чтения на строку 2 тз П ытается обновить строку 1 , но она заблокирована. Транзакция приоста­ навливается до тех пор, пока не смо­ жет получить монопольную блокировку Т4 Ч итает строку N. Сумма = . . . Т5 Ч итает строку 342 023, видит $ 1 00.00 и возвращает окончательный ответ Тб Т7 тв Транзакция перевода между счетами Фиксирует транзакцию Обновляет строку 1 и помещает моно­ польную блокировку на эту строку. В строке теперь $ 1 00.00 Обновляет строку 342 023 и помещает монопольную блокировку на эту строку. В строке теперь $500.00. Фиксирует транзакцию В табл . 7.5 легко заметить, что мы теперь получаем корректный ответ, но за счет физического блокирован ия одной транзакции и выполнения двух транзакций пос­ ледовательно. Так проявляется оди н из побочных эффектов разделяемых блокиро­ вок чтения для согласованных ответов: процессы чтения данных будут блокировать 368 Глава 7 процессы записи данных. Это еще и в дополнение к тому факту, что в таких системах процессы записи дан н ых будут блокировать процессы чтения . Только представьте, если бы банкоматы работали подобным образом в реальной жизни . Итак, вы видите , что разделяемые блокировки чтения могут подавлять паралле­ лизм, но они также могут вызывать поя вление фиктивных ошибок. В табл . 7.6 мы начи наем с исходной таблицы ACCOUNT S , но на этот раз цель заключается в перево­ де $50.00 со счета 987 на 1 23 . Таблица 7 б Временная ш кала 2 в отличной о т Oracle базе данных, . . использующей изоляцию READ REPEATABLE Момент времени Запрос Т1 Читает строку 1 . К этому моменту сумма ::: $500.00. Устанавливает разделяемую блокировку чтения на строку 1 Т2 Читает строку 2. К этому моменту сумма ::: $740.25. Устанавливает разделяемую блокировку чтения на строку 2 ТЗ Т4 Обновляет строку 342 023 и помещает мо­ нопольную блокировку на строку 342 023, предотвращая другие обновления и ус­ тановку разделяемых блокировок чтения. Строка теперь содержит $50.00 Ч итает строку N. Сумма ::: . . . Т5 Тб Транзакция перевода между счетами Пытается обновить строку 1 , но она забло­ кирована. Транзакция приостанавливается до тех пор, пока не сможет получить моно­ польную блокировку Пытается прочитать строку 342 023, но не может, т. к. установлена монопол ьная блокировка М ы тол ько что получили классическое условие взаимоблокировки . Н аш запрос удерживает ресурсы , в которых нуждается обновление, и наоборот. Транзакция на­ шего запроса взаимно заблокирована транзакцией обновления . Одна из них долж­ на быть выбрана в качестве жертвы и уничтожена. М ы потратили много времени и ресурсов л и ш ь для того, чтобы в кон це потерпеть неудачу и произвести откат. Это второй побоч н ы й эффект разделяемых блокировок чтения: процессы чтения и про­ цессы записи данных могут и часто будут попадать в ситуацию взаимоблокировки друг друга . В Oracle обеспечивается согласованность чтения на уровне операторов без бло­ кирования операций записи операциями чтения или взаимоблокировок. В Oracle н и когда не п р и м е н я ются разделяе м ы е блокировки чте н и я вообще никогда . Разработчи ки Oracle избрали трудную в реализации , но обеспечи вающую намного более высокую степень параллелизма схему многоверсионности . - Параллел изм и мно г оверси о н н ость 369 nотерянные обновления : еще одна проблема переносимости Распространенное использование RE PEATABLE READ в базах дан н ых, эксплуати­ рующих разделяемые блокировки чтения, связано с предотвращением потерянных обновлений. На заметку! Обнаружение потерянных обновлений и решения п роблемы потерянных обнов­ лений обсуждаются в главе 6. При наличии уровня изоля ции R E P EATAB L E READ в базе данн ых, которая за­ действует разделяемые блокировки чтения ( и не поддерживает многоверсионность) , ошибки потерян н ых обновлений происходить не могут. Причина отсутствия поте­ рянных обновлен и й в этих базах данных связана с тем , что простая выборка данн ых оставляет на них блокировку, и данные, однажды прочитанные нашей транзакцией, не могут быть модифицированы никакой другой транзакцией. Теперь, есл и в приложении предполагалось, что REPEATABL E READ означает " потеря н н ые обновлен ия не воз­ никнут", то вы столкнетесь с неприятны м сюрпризом при переносе приложения в базу данн ых, в которой не применяются разделяемые блокировки чтения в качестве лежащего в основе механизма управлен ия параллелизмом. На заметку! В среде, не поддерживающей состояние, такой как веб-приложение, потерян­ ные обновления, скорее всего, станут причиной проблем - даже при уровне изоляции REPEATABLE READ. Это объясняется тем , что единственный сеанс базы данных использу­ ется многи м и клиентами через пул подключений, а блокировки между вызовами не удер­ живаются . Уровень изоляции RE PEATABLE READ предотвращает потерянные обновления только в среде с поддержкой состояния вроде той , которую можно наблюдать в кл иент­ серверном приложении. Хотя это звучит неплохо, вы должны помнить, что оставление разделяемых бло­ кировок чтения на всех данных после их чтения, разумеется , всерьез ограничит воз­ можности параллельных операций чтения и модификации . Таким образом, хотя ука­ занный уровень изоля ции в этих базах дан н ых предназначен для предотвращения потерянных обновлений, это достигается полным исключением возможности выпол­ нения параллельных операций ! И меть мед и есть его ложкой можно не всегда. Уровень ИЗОЛЯЦИИ SERIALI ZAВLE Обычно S E R I AL I ZAB L E считается наиболее ограничивающим уровнем изоля­ ции транзакций, но он п редлагает максимальную степень изоля ц и и . Транзакция SERIAL I ZABLE работает в среде, которая позволяет сделать вид, будто бы в базе дан ­ н ы х нет других пользователей, изменяющих данные. Л юбая прочитанная строка га­ рантированно будет той же самой при ее повторном чтени и , и любой выполняем ы й запрос гарантирован но возвратит т е ж е самые результаты н а протяжен и и времен и жизни транзакции . Например, если выполнить приведеин ые н иже запросы, т о отве­ ты, полученные из таблицы т, будут одинаковыми, хотя между ними прошло 24 часа (или может возни кнуть ошибка ORA- 0 1 5 5 5 : s napshot t o o o l d (ORA-0 1 555: уста­ ревши й снимок) , о которой речь пойдет в главе 8): 370 Глава 7 s elect * from Т ; begin dbms_loc k . s leep ( 6 0 * 6 0 * 2 4 ) ; end ; s e l ect * from Т ; Уровень изоляции SE R IAL I ZAB LE гарантирует, что эти два запроса будут всегда возвращать те же самы е результаты . П обочные эффекты (изме нения ) , сделанные другими транзакц ия м и , для этого запроса остаются невиди мыми независимо от того, сколько времени он выполнялся . В Oracle транзакция S E R I AL I ZABL E реализована так, что согласованность чте­ ния, которую мы обыч но получаем на уровне оператора, расширяется до уровня транзакции. Н а заметку! Как отмечалось ранее, в Oracle также существует уровень изоляци и , обоз­ нач е н н ы й как R E A D O N L У . Он обладает всеми характеристиками уровня изоляции S E R I A L I ZAB L E , но запрещает модификацию. Следует отметить, что пользователь SYS ( ил и пол ьзовател ь, подключенный с при вилегией S Y S DBA) не может иметь транзак­ ци ю READ ONLY или S E R I AL I ZAB L E . В этом отношении пользователь S Y S является особенным . Вместо обеспечен ия согласованности результатов на момент запуска оператора это делается для момента начала транзакции . Другим и словам и , Oracle применяет сегменты отката для воссоздания дан н ых в том виде , в каком они существовали, когда начиналась транзакция , а не оператор. Здесь скрыта довольно глубокая м ысль: база данных уже знает ответ на любой вопрос, которы й вы можете задать, еще до того, как вы спросите . Уровень изоляции S ERIAL I ZABLE обходится не бесплатно, и ценой является возможность возн и кновения следующей ошибки : ERROR at l i ne l : ORA- 0 8 1 7 7 : can ' t s er i al i z e acce s s for this transaction ОПМБКА в строке 1 : ORA - 0 8 1 7 7 : не уда ется сериализова тЪ доступ для этой транза кции В ы будете получать это сообщен ие при каждой попытке обновлен ия строки , ко­ торая изме н илась с момента начала транзакции. Н а заметку! СУБД Oracle пытается делать это исключительно на уровне строки, но вы може­ те получить ошибку ORA - о 8 1 7 7 , даже когда строка, которую вы хотите модифицировать, не была изменена. Ошибка ORA- 0 8 1 7 7 может возникнуть из-за того, что была модифици­ рована какая-то другая строка ( или строки ) из блока, в котором находится интересующая вас строка. В Oracle принят оптимистически й подход к сериализации - ставка делается на тот факт, что данные, которые ваша транзакция собирается обновить, не будут обновлен ы какой -то другой транзакцией. Обычно так и происходит, поэтому став­ ка выигры вает, особен н о в системах типа OLTP с быстрыми транзакциям и . Если н и кто другой не обновляет дан ные во время вашей транзакции , то этот уровень изоляции, которы й обычно будет снижать степень параллелизма в остальных сис­ темах, предоставит здесь ту же самую степень параллелизма, что и без транзакций S ERIALI ZABLE. П араллел изм и м н о г оверси о н н ость 371 Недостаток заключается в том , что можно получить ошибку O RA - 0 8 1 7 7 , если ставка оказалась проиrрыш ной . Однако если подумать, то такой риск вполне оп­ равдан. Если вы испол ьзуете транзакци и S E R I AL I ZAB L E , то не должны ожидать обновлений и нформаци и , с которой работают другие транзакц и и . В п роти вном случае необходимо применять S E L E C T . . . FOR U P DAT E , как было оп исано в гла­ ве 1 , и это сериализирует доступ . Таким образом , испол ьзование уровня изоля ции SERIAL I ZABLE достижимо и эффективно, если соблюдаются следующие условия. • Высока вероятность того, что никто другой не модифицирует те же самые данные. • Требуется согласованность чтения на уровне транзакции. • Транзакции будут короткими (что поможет сделать реальным первое условие ) . В Orac\e считают этот метод достаточн о масштабируемым для прогона всех и х эталонных тестов ТРС-С (этал он н ы й тест O LT P, соответствующий и ндустриал ь­ ным стандартам; подробн ые сведения доступны по адресу http : 1 / www . tpc . o r g ) . В о многих других реализациях вы обнаружите , что т е ж е самые цел и дости гаются посредством разделяемых блокировок чте н ия с присущими им взаимоблокировка­ ми и блокированием. В Oracle мы не столкнемся с каким-либо блокированием, но получим ошибку ORA- 0 8 1 7 7 , если другие сеансы будут модифицировать данн ые , которые мы также хотим изменять. Однако эта ошибка возн икает не так часто, как взаимоблокировки и блокирование в других системах. Но - всегда есть какое-то " но " - вы должн ы четко понимать разн и цу между уровнями изоляции и их реализация ми. Помните, что при установке уровня изоля­ ции в S ERIAL I ZABLE вы не увидите н и каких изменений, внесенных в базу дан н ых после запуска вашей транзакци и - вплоть до ее фиксации. П р иложения, которые пытаются поддержи вать собственные ограничения целостности дан н ых, такие как планировщик ресурсов, оп исан ный в главе 1 , в связи с эти м должны п редпри н и ­ мать дополнительные меры предосторожности. Если помните, в главе 1 была оп иса­ на проблема, которая заключалась в невозможности принудительного применения огран ичения целостности в многопол ьзовательской системе из-за того, что мы не могли видеть изменения , сделан ные незафиксированными сеансами . В случае ис­ пользования уровня S ER I AL I ZAB L E мы по-прежнему не увидим незафиксирован­ ных изменен и й , но также не увидим и зафиксирован ных измене н и й , произведен ­ ных после начала нашей транзакции! Н аконец, имейте в виду, что уровень изоляции S E RIAL I ZABLE вовсе не означает, что все транзакции , запущенные пользователями, будут вести себя так, как будто они выполняются друг за другом в последовательной манере. Это не подразумевает на­ личие какого-то последовательного упорядочения транзакций, что приведет к тому же самому результату. Феномен ы , ранее описанные в стандарте SQL, не позволяют такому случиться . П оследнее утверждение отражает часто неправильно пони мае­ мую концепцию, которую поможет прояснить небол ьшая демонстрация . В табл . 7.7 представлены два сеанса, выпол ня ющие работу на протяжени и некоторого времени. Изначально пустые таблицы базы данных А и в создаются следующим образом: EODA@ ORA1 2CR1> create table а Table created . Та блица создана . ( х int ) ; 372 Глава 7 EODA@ ORA 1 2 CR 1> create taЬle Ь ( х int ) ; ТаЬlе created . Та блица создана . М ы и меем последовательность событий , описанную в табл. 7.7. Таблица 7 . 7 . Пример транзакции SERIALIZAВLE Момент времени Де йствия в сеансе 1 Т1 a l te r s e s s ion s et i solation_level=seri a l i z aЬle ; alter sess ion set i solation_level=seri a l i z aЬle ; Т2 тз insert into а select count ( * ) frorn Ь ; insert into Ь se lect count ( * ) frorn а ; Т4 Т5 Де йствия в сеансе 2 cornrni t ; Тб cornrni t ; Теперь, когда все показан ное сделано, таблицы А и в будут содержать строку со значением О каЖдая . Если бы существовало некоторое последовательное упорядоче­ н ие транзакци й , присутствие значен ия О в обеих табли цах было бы невозможным. Есл и бы сеанс 1 выпол нялся во всей своей полноте перед сеансом 2 , то таблица в и мела бы строку со значен ием 1 в ней . Если бы сеанс 2 выполнялся полностью пе­ ред сеансом 1 , то таблица А содержала бы строку со значен ием 1. Однако на самом деле мы получили строки со значением О в обеих таблицах. КаЖдая транзакция вы­ полнялась так, как будто в конкретны й момент времени она была единственной в базе дан н ых. Н езависимо от того, сколько раз сеанс 1 выдавал запросы к таблице в, и независимо от состояния фиксации сеанса 2, счетчик получит значение, которое было зафиксировано в базе данных на момент времени T l . Аналогично, не и грает рол и , сколько запросов к табли це А производил сеанс 2 - счетчик имеет значение, которое было в момент Т2. Уровень ИЗОЛЯЦИИ READ ONLY Транзакции READ ONL Y очен ь похожи на транзакции S E R I AL I ZABLE с единс­ твенным отличием: они не допускают модификаций , поэтому не восприимч ивы к ошибке ORA- 0 8 1 7 7 . Транзакции READ ONLY предназначены для подiJ.ержки потреб­ ностей, возникающих при формировании отчетов, когда содержимое отчета должно быть согласовано с состоянием н а определенн ы й момент времени. В других систе­ мах вам придется применять транзакцию RE PEATAB LE READ и страдать от последс­ тви й , вызванн ых разделяемой блокировкой чтения. В Oracle вы будете использовать транзакцию READ O N L У. В этом режиме вывод, генерируемый в отчете , который применяет 50 операторов S ELECT для сбора данных, будет согласованным по состо­ я н и ю на еди нствен н ы й момент времени - момент начала транзакции . Вы получите возможность делать это, не блокируя ни единой порции дан ных. П араллелизм и мно г оверсионность 373 Эта цель достигается использованием той же самой многоверсионности , которая применялась для и ндивидуальных операторов. Дан н ые реконструируются из сег­ ментов отката по мере необходимости и предоставляются в том виде , в каком они пребы вали на начало формирования отчета. Тем не менее, транзакции READ ONL У не лишены недостатков. В то время как в транзакциях S ERIAL I ZABLE можно стол­ кнуться с ошибкой ORA- 0 8 1 7 7 , в транзакциях READ ONLY следует ожидать ошибки ORA- 0 1 5 5 5 : s n ap s ho t t o o o l d (ORA-0 1 555: устаревший снимок) . Это будет про­ исходить в системах, где другие пользователи активно модифицируют информацию, которую вы читаете . И зменения , вносимые в эту информацию , сохраняются в сег­ ментах отката. Но сегменты отката испол ьзуются в цикл ическом режиме - почти так же , как журнальные файлы повторения действи й . Ч е м дольше требуется времени н а формирование отчета, тем в ы ш е вероятность, что какая-то операция отката, необходимая для воссоздания ваших данных, уже не сможет найти необходимых сведе н и й в сегменте отката. Сегмент отката начи нает перезаписываться другой транзакцие й , и нужная вам ч асть и нформац и и утрач и ­ вается . В этот момент в ы получаете ош ибку O RA- 0 1 5 5 5 и вынужде н ы начи нать заново. Единствен ное решение этой неприятной проблемы предусматривает корректную установку размера табличного пространства отката для системы. Я постоян но стал ­ киваюсь с людьми , которые п ытаются сэкономить несколько мегабайт дискового пространства, создавая табличное пространство отката с м и нимально возможным размером ( " Зачем тратить пространство на то, в чем я действительно не нужда­ юсь? " - примерно так они думают) . Проблема в том , что табличное пространство отката я вляется ключевым ком ­ понентом п р и работе базы данных, и если его размер определе н неправильно, в ы обязательно столкнетесь с упомянутой в ы ш е ош ибко й . В течение многих л е т ра­ боты с версиями Orac1e 6 , 7, 8, 9, 1 0, 1 1 и 1 2 я н икогда н е сталкивался с ошибкой ORA- 0 1 5 5 5 за пределами тестовой системы или системы разработки . В случае воз­ никновения такой ошибки вы должн ы знать, что некорректно задали размер таб­ личного пространства отката, и это необходимо исправить. М ы вернемся к этой теме в главе 9 . Последствия м н ого вер е и о н н о й согласованн о сти чтен ия До настоя щего времени мы видели , каким образом многоверсионность обес­ печивает возможность неблокирующего чте н ия , и я подчеркивал, что это хорошая вещь: согласован н ые (корректн ые) ответы при высокой степени параллелизма. Что же в этом может быть плохого? Есл и вы четко не понимаете весь механизм и его последствия, то вполне вероятно, что спроектируете некоторые из своих транзакций неправильно. Вспомните пример с планированием ресурсов из главы 1 , в котором мы п ыта­ лись задействовать ряд приемов ручной блокировки (через S ELECT FOR U P DATE для сериал изации модифи каций записей о ресурсах в табл и це S C H E D U L E S ) . Но может ли Это затронуть нас другими путями? Однозначно может. В последующих разделах приведены соответствующие детали . 374 Глава 7 Распрос траненный прием организа ц и и хранили щ данных, который не работает Распространенный прием организации хранилищ дан ных, применяемый многи­ ми л юдьми, выглядит следующим образом. 1 . Они испол ьзуют три ггер для поддержки столбца LAS T _U P DAT E D в исходной таблице , что очен ь похоже на метод, описанный в разделе " Оптимистическая блокировка" в предыдущей главе. 2. Для начального наполнения табл ицы хранилища они запом инают те кущее время, выбирая S Y S DAT E в исходной системе. Н апример, предположим , что прямо сейчас ровно 9:00. 3. Затем они извлекают все строки из транзакционной системы, т.е. выполняют полный запрос SELECT * FROM < ТАБЛИЦА> , чтобы провести начальное запол­ нение хранили ща данных. 4. Для обновления хран или ща дан ных они опять запом и нают те кущее время . Н апример, предположим, что прошел час и теперь в исходной системе 1 0:00. Они запоминают этот факт. Затем они извлекают все изменения , накопившие­ ся после 9:00 (момента перед началом первого извлечения ) , и объединяют их. На заметку! При таком подходе одна и та же запись может быть извлечена дважды в двух последовательных обновлениях. Это неизбежно из-за степени детализации часов. На операцию MERGE данный факт (т.е. обновление существующей записи в хранилище или вставка новой записи) не повлияет. Эти л юди верят в то, что после описанных выше действий имеют в хран или ще дан ных все записи, которые был и модифи цированы после первоначального их из­ влечения. Они действительно могут и меть все записи , но точно так же могут и не иметь. Такой прием работает с рядом других баз данных - тем и , что применяют систему блокирован ия, посредством которой операци и чте н ия блокируются опе­ рациям и зап иси и наоборот. Н о в системе с неблакирующими чтениями подобная логи ка ущербна. Чтобы увидеть слабую сторону в этом при мере, вполне достаточно предполо­ жить, что в 9 :00 оставалась, по крайней мере, одна открытая , незафиксированная транзакция . В 8 : 59 : 30 она обновила в табли це строку, которую мы скоп ировал и . В 9:00, когда мы начи наем извлекать данные, ч итая и х и з этой таблицы , м ы н е уви­ дим модифи кации этой строки , а только ее последнюю зафи ксированную версию. Если она заблокирована в момент ее обработки запросом, то мы прочитаем ее в об­ ход бло кировки . Если она зафиксирована ко времен и , когда мы ее достигли, мы по­ прежнему будем ч итать ее в обход бло кировки , поскольку согласованность чтения позволяет производить чтение только дан ных, которые бьш и зафиксированы в базе к моменту начала нашего оператора. Мы не прочитаем н и новую версию строки во время начальной загрузки в 9 :00, ни модифицированную версию во время обновле­ ния хранил и ща в 1 0:00. В чем причина? При обновлении в 1 0:00 извлекаются толь­ ко записи , модифи цированные после 9 :00, но эта запись бьша модифицирована в 8:59:30. М ы н икогда не получи м эту измененную строку! Параллел изм и мно г оверсионность 375 Во многих других базах данных, где операции чтения блокируются операция м и записи и реализованы зафиксирован ные, но несогласованные чтения, этот процесс обновления будет работать прекрасно. Если в 9:00 при выполнен и и начального из­ влечения данных мы столкнулись с этой строкой, и она оказалась заблокированной, мы будем ожидать ее освобождения и прочитаем зафиксированную версию. Если строка не заблокирована, то мы просто читаем то, что есть в строке и зафиксиро­ вано. Итак, озн ачает л и это, что оп исан н ая выше логи ка не может использовать­ ся? Нет, это значит, что мы должны получать "текущее" время слегка по-другому. Необходимо запросить представление V $ T RANSACT I ON и выясн ить, что было рань­ ше - текущий момент времени или время , зап исанное в столбце S TART T IME этого представления . Понадобится извлечь все записи, измененные после времен и начала самой старой транзакции (или текущего значен ия S Y S DATE, если акти вных транзак­ ций нет) : _ select nvl ( min ( to_date ( s tart_time , ' mm/dd / r r hh2 4 : mi : s s ' ) ) , s ysdate ) from v$ transaction ; На заметку! Приведенный выше запрос работает независимо от наличия каких-либо данных в V$TRANSACT I ON . То есть, даже если представление V$ TRANSACT I ON оказывается пус­ тым (из-за того, что в настоящий момент транзакции отсутствуют) , этот запрос возвратит запись. Запрос с агрегированием без конструкций WHERE всегда возвращает, по крайней мере, одну строку и не более одной строки . В рассматриваемом примере этим моментом будет 8:59:30, т.е. запуск транзакции, модифи цирующей эту строку. Когда м ы переходим к обновлению дан ных в 1 0: 00, то извлекаем все изменения , которые произошли после того момента; в результате слияния их с хранилищем данн ых м ы получи м все необходим ые записи . Объяснен ие неожиданно высокой активности ввода-вывода в " горячих " таблицах Еще одна ситуация , где жизненно важно понимать согласованность чтения и многоверсионность, связана с запросом , который в производственной среде с высо­ кой нагрузкой инициирует намного больше операций ввода- вывода, чем вы наблю­ дали в тестовой системе или системе разработки , и вы не и меете н икакой возмож­ ности объяснить это. Вы просматриваете сведения по вводу-выводу, выполненному запросом, и замечаете , что он значительно и нтенсивнее, чем вы когда-либо виде­ ли - намного выше, чем казалось возможным. Вы восстанавливаете производствен ­ н ы й экземпляр базы дан ных в тестовой системе и обнаруживаете , что ввод- вывод снизился . Однако в производственной среде он по-прежнему очень высок (но варь­ ируется : иногда выше, иногда ниже , а иногда где-то посередине ) . Причина, как мы увидим, заключается в том , что в тестовой системе, в изоляции, вам не приходится отменять изменения, вносимые другими транзакциям и . Тем не менее, в производе­ твен ной среде при чтении определенного блока может возни кать необходимость в отмене (откате) изменений, произведенных многими транзакциями, и каждый откат предусматривает выпол нение операций ввода-вывода для извлечения данных отме­ ны и их применения. 376 Глава 7 Вероятно, это может быть запрос к таблице, которая подвержена многочислен ­ ным параллельным модификациям . Вы можете видеть это по факту чтений сегмента отката - работе, которую Oracle выполняет для восстановления блока в состоянии, в котором он пребывал, когда ваш запрос начинался. Эти эффекты легче всего уви­ деть в единственном сеансе, просто чтобы понять, что происходит. Начнем с очень мален ькой таблицы: EODA@ORA12 CR1 > create taЬl e t ТаЬlе created . Та блица создана . ( х int ) ; EODA@ORA1 2 CR 1 > insert into t values ( 1 ) ; 1 row created . 1 строка создана . EODA@ORA 1 2 CR 1 > ехес dЬms_s tats . gather_taЬle_s tats ( use r , PL/ SQL p rocedure succe s s fu 1 1 y completed . Процедура PL/SQL успешно завершена . ' Т' ) ; EODA@ORA 1 2 CR 1 > select * from t ; х 1 Теперь настроим сеанс на использование уровня изоляции S E RIAL I ZABLE, так что независимо от того, сколько раз мы запускаем запрос в сеансе , результат будет таким , как на момент старта транзакции: EODA@ORA 12CR 1> alter s e s s i on s et i so1ation_level=seriali zaЬle ; S e s s i on altered . Сеанс изменен . Выполним запрос к маленькой таблице и понаблюдаем за объемом ввода-вывода: EODA@ORA 1 2 CR l > set autot race on stati s t i cs EODA@ORA 12CR 1> se1ect * from t ; х 1 Stati s t i cs О recurs ive cal1s О dЬ Ьlock get s 7 con s i stent gets Итак, этому запросу для завершения потребовалось семь операций ввода-вывода. Далее мы многократно модифицируем эту табли цу в другом сеансе: EODA@ORA1 2 CR 1 > begin 2 for i i n 1 . . 1 0 0 0 0 3 l oop 4 update t s e t х = х+ 1 ; 5 commi t ; б end loop ; 7 end; 8 1 PL/SQL p rocedu re succe s s fu l l y completed . Процедура PL/SQL успешно завершена . П араллел изм и мно г оверси о н н ость 377 Возвратившись в сеанс S ERIAL I ZABLE, запустим тот же самы й запрос еще раз: EODA@ORA12CR1 > select * f rom t ; х 1 Stati stics О recursive cal l s О db Ыосk gets 1 0 0 0 4 con s i s tent gets На этот раз понадобилось 10 004 операций ввода-вывода - разн и ца заметна. Откуда взялись все эти операции? Дело в том , что Orac1e выпол няет откат измене­ ний, внесенных в этот блок данных. Когда м ы запускаем второй запрос, Oracle из­ вестно, что все блоки , извлеченные и обработанные запросом, должн ы быть такими, какими они были в момент запуска транзакции . Когда м ы обращаемся к буферному кешу, то обнаруживаем, что блок в кеше просто "сл и ш ком новы й " - другой сеанс модифицировал его 10 000 раз. Наш запрос не видит изменений, поэтому он начи­ нает просматривать информацию отката и отменять последнее изменение. Затем он выясняет, что этот блок после отката по-прежнему является сли ш ком новым, и про­ изводит еще один откат блока. Процедура повторяется до тех пор, пока, наконец, не будет найдена версия блока, которая была зафиксирована в базе в начале транзак­ ции . Этот блок можно использовать - и он испол ьзуется. На заметку! Интересно отметить, что если вы повторно запустите SELECT * FROM т , то ко­ личество операций ввода-вывода, скорее всего, снизится до 7 или около того; оно уже не будет составлять 10 004. В чем причина? СУБД Oracle обладает способностью хранить в бу­ ферном кеше несколько версий одного и того же блока. Когда вы отменили изменения в этом блоке для запроса, который выполнял 1 0 004 операции ввода-вывода, то оставили в кеше данную версию, и при последующих запусках запроса к ней будет производиться доступ. Сталкиваемся ли мы с этой проблемой только в случае применения уровня изо­ ля ции SERIAL I ZABLE? Вовсе нет. Рассмотри м запрос, который выпол няется в тече­ ние пяти м инут. За это время он извлекает блоки из буферного кеша. При каждом извлечении блока запрос выясняет следующее: " Этот блок сли ш ком новый? Если да - откатить его! " . И помн ите: чем дольше работает запрос, тем выше шансы, что нужный ему блок со временем окажется модифицированным. Теперь база данных ожидает, что такая проверка может произойти (т. е. проверка, не является ли блок "сл и ш ком новы м " , с последующим откатом изменений), и по этой причине буферный кеш может действительно содержать множество версий од­ ного и того же блока в памяти . Таким образом, есть шанс, что требуемая версия бу­ дет находиться в буферном ке ше, полностью готовая к испол ьзованию, поэтому ее не придется материализавывать с применением информации отката. Для просмотра этих блоков можно использовать запрос, подобный показанному н иже: sel ect f i l e # , Ыосk# , count ( * ) from v$bh group Ьу file# , Ьlock# having count ( * ) > 3 orde r Ьу 3 1 378 Глава 7 Вообще говоря , в л юбой момент времен и вы найдете не более примерно шести версий блока в кеше, но эти версии могут применяться любым запросом , который в них нуждается . Обычно с таким и маленьки м и горячими таблицами часто возникает проблема за­ вышен ного количества операций ввода-вывода из-за обеспечен ия согласованности чтения . Другим и запросам и , наиболее часто подверженными такой проблеме, явля­ ются длительно работающие запросы в отношении изменчивых таблиц. Чем дольше они фун кционируют, тем бол ьше они работают, потому что со временем им может понадобиться выпол нять все больше действи й по извлечен и ю блока из буферного кеш а. С огласованность записи Д о с и х пор м ы рассматри вали согласованность чтения: способность Oracle ис­ пользовать информацию отката для обеспечения неблакирующих запросов и со­ гласованн ых (корректных) чте ний. Мы разобрались с тем , что когда СУБД Oracle ч итает блоки для запросов из буферного кеша, она гарантирует, что версия блока достаточно "стара" , чтобы быть видимой данному запросу. Н о это подводит к следующим вопросам. Как насчет зап иси/модификации? Что произойдет в ситуации , если вы запустили при веденный н иже оператор U P DAT E , но в о время его выполнения кто-то обновил строку, которую этот оператор должен прочитать, изменив У=5 на У= б и тут же зафиксировав изменен ие? update t s e t х = 2 whe re у = 5 ; То есть, когда оператор U P DAT E начинается , некоторая строка имеет значение У= 5 . П оскольку оператор U P DAT E читает табл и цу с применен ием согласованных чте н и й , он видит, что эта строка и мела У=5 на момент начала его работы . Но теку­ щее значение У теперь равно 6 , а не 5 , и перед обновлением Х база данных Oracle проверит, что У по-прежнему имеет значение 5 . Что случится? Как это повлияет на обновлен ия? Очевидно, м ы не можем модифицировать старую версию блока; когда мы со­ бираемся изме нять строку, то должны модифицировать текущую версию блока. Вдобавок Oracle не может просто пропустить данную строку, т. к. это было бы не­ согласован н ы м чтен ием и непредсказуемой ситуацие й . Как мы вскоре убедимся , в таких случаях Oracle будет перезапускать модификацию посредством записи с нуля . Согласованные чтения и текущие чтения П ри обработке модифицирующего оператора Oracle использует два способа по­ лучения блока: • согласованные чтения - при " поиске" строк для модификации; • текущие чтения - при получении блока для действител ьного обновления ин­ тересующей строки . М ы можем легко увидеть это с помощью утилиты TKPROF. Рассмотрим следую­ щий небольшой однострочный пример, в котором производится чтение и обновле­ ние единственной строки в ранее представлен ной табл ице т : П араллели з м и мно г оверси о н н ос т ь 379 EODA@ORA1 2CR1 > ехес dЬms_monitor . se s s ion_t race еnаЫе PL/ SQL procedure succe s s fu l l y completed . Процедура PL/SQL успешно завершена . EODA@ORA1 2 CR1 > se lect * f rom t ; х 10001 EODA@ORA 12CR1 > update t t 1 s e t х = х+ 1 ; 1 row updated . 1 строка обновлена . EODA@ORA1 2CR1 > update t t2 set х = х+ 1 ; 1 row updated . 1 строка обновлена . Запустив T KPROF, мы увидим примерно такие результаты (обратите внимание, что из этого отчета исключен ы столбцы ELAPSED, CPU и D I S K) : se1ect * f rom t call count query ------- Parse Execute Fetch 1 1 2 о о 7 4 7 ------- total current rows ---------- ---------- о о о о о 1 ---------- ---------- о 1 update t t 1 s e t х = х+ 1 call count query ------- Parse Execute Fetch 1 1 о о 7 о 2 7 ------- total current rows ---------- ---------- о 3 о о 1 о ---------- ---------- 3 1 update t t2 set х = х+1 cal l ------- Parse Execute Fetch ------- total count que ry 1 1 о о 7 о 2 7 current rows ---------- ---------- о 1 о о 1 о ---------- ---------- 1 1 Итак, во время вполне нормального запроса м ы имеем семь получений в режиме (согласованного) запроса. Для первого оператора U P DATE мы имеем те же семь опе­ раций ввода-вывода (поисковый компонент операции обновления в дан ном случае предусматривает поиск всех строк, находящихся в таблице на момент начала обнов­ ления ) и три получения в текущем режиме. П олуче н ия в текущем режиме (cuгrent mode gets) выполняются для того, чтобы извлечь табличный блок в том виде, в ка­ ком он существует прямо сейчас, вместе с нужной строкой в нем. Это необходимо для получен ия блока сегмента отмены, чтобы начать транзакцию, и блока отмены. 380 Глава 7 Второй оператор U P DATE имеет в точности одно получение в текущем режиме; так как выпол нять снова работу по откату не требуется , есть только одно текущее полу­ чение дЛЯ блока со строкой, поллежащей обновлению. И менно присутствие получе­ н и й в текущем режиме говорит о том, что имела место модификация определенного рода. П режде чем СУБД Oracle модифицирует блок с применен ием новой информа­ ции, она должна получить наиболее свежую его копию. Каким же образом согласованность чтения влияет на модификацию? Представьте, что вы запускаете следующий оператор U P DATE в отношении какой-то таблицы базы дан н ых: update t set х = х+1 where у = 5 ; М ы пони маем, что компонент WHERE Y = S (согласован ная по чтению фаза за­ проса) будет обработан с использованием согласованного чтения (получения в ре­ жиме запроса в отчете T K P RO F ) . Н абор записей WHERE У= 5 , зафиксирован ный в табли це в начале выполнения оператора - это те записи, которые он будет видеть ( предполагается применение уровня изоляции READ COMM I T T E D ; в случае уровня S ERIAL I ZABLE это был бы набор записей WHERE Y=S , которые существовали, когда начиналась транзакция ) . Это означает, что если бы оператору UPDATE поиадабилось пять минут на обработку от начала до кон ца, и кто-то добавит в таблицу и зафик­ сирует новую запись со значением 5 в столбце У, то оператор U P DAT E ее не увидит, поскольку ее не должно видеть согласованное чтение. Поведение является ожида­ емы м и нормальным. Но вопрос в том , что произойдет, если два сеанса выполнят следующие операторы по порядку: update t set у = 1 0 whe re у = 5 ; update t s e t х = х+1 where у = 5 ; Временная ш кала приведена в табл . 7.8. Таблица 7 . 8 . Последовательность обновлений М омент времени Сеанс 1 Т1 update t set у= 1 0 where у=5 ; comrni t ; Комментарии Обновит одну строку, которая со­ ответствует критерию upda te t set х=х+ 1 whe re у=5 ; Т2 тз Сеанс 2 Используя согласованные чтения, найдет запись, модифицированную в сеансе 1 , но не сможет обновить ее, т. к. сеанс 1 ее заблокировал. Сеанс 2 будет заблокирован и ожи­ дать освобождения этой строки Освобождает сеанс 2: сеанс 2 становится разблокированным . Наконец, можно выполнить теку­ щее чтение блока, содержащего эту строку, где У было равно 5 , когда сеанс 1 начинал обновление. Текущее чтение покажет, что У те­ перь равно 1 0 , а не 5 Паралл ел и зм и мно г оверси о н н ость 381 Таким образом , запись, в которой значен ие У было равно 5 на момент н ачала оператора UPDATE, больше не содержит У=5 . Компонент согласованного чтен ия опе­ ратора UPDATE говорит: " вы хотите обновить эту запись, потому что У было равно 5 , когда м ы начинал и " , н о текущая версия блока заставляет подумать: " нет, я н е могу обновить эту строку, поскольку У больше не равно 5 - это было бы неправильно" . Если в этой точке мы просто пропустим данную строку и проигнорируем ее, то получим недетерминированное обновление. Это может нарушить согласован ность и целостность данн ых исчезнет. Исход обновления (сколько строк было обновлено и какие именно) будет зависеть от порядка, в котором строки посещались в таблице, и какие другие действия происходили в ходе работ. В ы можете взять оди н и тот же набор строк в двух разных базах данных, в которых выполняются транзакции в том же самом порядке , и получить отличающиеся резул ьтаты л и ш ь потому, что строки были по-разному расположены на диске . В этом случае Oracle решит перезапустить обновление. Обнаружив, что строка, которая в начале имела У= 5 , теперь содержит Y= l O , СУБД Oracle молча выполнит откат обновления (тол ько этого обновления, но н икакой другой части транзак­ ции) и перезапустит его заново, предполагая использование уровня изоляции READ COMM I Т T E D . В случае применения уровня изоляции S E RIAL I ZAB L E в этот момент возни кнет ошибка ORA- 0 8 1 7 7 : can ' t s e r i a l i z e a c ce s s f o r t h i s t r a n s a c t i on (ORA-08 1 77: не удается сериализировать доступ для этой транзакции ) . В режиме READ COMM I T T E D после отката транзакцией обновлен ия база данн ых перезапустит обновление (т.е. измен ит точку во времен и , которой соответствует обновление), а затем вместо повторного обновления дан ных войдет в режим S E LECT FOR U P DAT E и попытается заблокировать для сеанса все строки , имеющие У= 5 . Сделав это, база данных запустит оператор U P DAT E на заблокированном наборе данных, тем самым гарантируя , что на этот раз она сможет завершить операцию без перезапуска. Продолжая думать в стиле "что случ ится , если . . . ", возникает вопрос: что про­ изойдет, если после перезапуска обновлен ия и перехода в режим S E L E C T F O R UPDATE (который связан с теми же лолучениями блока операциями согласованного чтения и текущего чтения при выполнен и и обновления) обнаружится , что строка, которая имела У=5 при запуске S E LECT FOR U P DAT E , содержит Y= l l в своей теку­ щей версии? Этот оператор S ELECT FOR U P DATE будет перезапущен и цикл начнет­ ся сначала. Здесь возни кает множество интересных вопросов. Можем ли м ы это наблюдать? Можем ли мы выяснить, что это действительно произошло? И если да, что из этого следует? Что это означает для разработчи ков? Давайте ответим на эти вопросы по очереди . Н аблюдение за перезапуском Перезапуск увидеть проще, чем может лоначалу казаться. Фактически его можно наблюдать, используя простую однострочную табли цу. Вот таблица, которая будет применяться при тестирован и и : EODA@ORA 1 2 CR1> create t а Ы е t ТаЫе created . Таблица создана . ( х int , у 1nt ) ; 382 Глава 7 EODA@ORA12CR1> insert into t va 1ues ( 1 , 1 ) ; 1 r ow created . 1 строка создана . EODA@ORA1 2 C R 1 > commi t ; Commit comp1ete . Фиксация завершена . Для наблюдения за перезапуском понадобится всего лишь триггер, выводящий не­ которую информацию. Мы будем использовать триггер BEFORE UPDATE FOR ЕАСН ROW, чтобы выводить образ строки до и после обновления: EODA@ORA 1 2 C R 1 > create or rep1ace t r igger t_bu fe r 2 before update on t for each row 3 begin 4 dЬms_output . put_1 ine ( 1 01d . x = 1 1 1 : o1 d . x 1 1 5 б 1 , old . у = 1 1 1 : o1d . у ) ; 7 dЬms_output . put_l ine 8 ( 1 new . х = 1 1 1 : new . х 1 1 1 , new . у = 1 1 1 : new . у ) ; 9 1 0 end ; 11 1 T r i gge r created . Триггер создан . Теперь обновим строку: EODA@ORA12CR1> s e t s e rve routput on EODA@ORA 1 2 C R 1 > update t set х = х+ 1 ; old . x = 1 , old . y = 1 new . x = 2 , new . y = 1 1 row updated . 1 строка обновлена . До сих пор все идет вполне ожидаемо: триггер запустился один раз, и мы видим старые и новые значения . Однако обратите внимание, что мы пока еще не произ­ вели фиксацию - строка по-прежнему заблокирована. Выполним в другом сеансе следующее обновление: EODA@ORA12CR1> set s erve routput on EODA@ORA12CR1> update t set х = х+1 where х > О ; Конечно, второй сеанс будет немедленно блокирован, т.к. первый сеанс имеет бло кировку на этой строке. Если теперь мы вернемся в первый сеанс и зафиксируем транзакцию, то во втором сеансе увидим такой вывод (для ясности оператор обнов­ ления повторен ) : EODA@ORA1 2 CR 1 > update t s et х = х + 1 where х > О ; o1d . x = 1 , o1d . y = 1 new . х = 2 , new . у = 1 old . x = 2 , o1d . y = 1 new . х = 3 , new . у = 1 1 row updated . 1 строка обновлена . Параллел изм и м н о г оверси о н н ость 383 Как видите , три ггер строки увидел здесь две версии строки. Три ггер был активи­ зирован дважды : первый раз с исходной версией строки, а также данными, на кото­ рые мы пытались изменить эту версию, и второй раз с финальной строкой, которая действительно была обновлена. П оскольку это был триггер BE FORE FOR ЕАСН ROW , база данных Oracle видит согласованную по чтению верси ю строки и модификации , которые мы хотели в н е й провести. Однако Oracle извлекает блок в текущем режиме мя выполнения обновления после срабатывания три ггера BE FORE FOR ЕАСН ROW. База данных ожидает окончания работы три ггера, чтобы получить блок в текущем режиме, т. к. три ггер может модифицировать значения : NEW. П оэтому Oracle не мо­ жет изменять блок до тех пор, пока триггер не заверш ит работу, а это может занять довольно мительное время . П оскол ьку удерживать блокировку в текущем режиме может только один сеанс за раз, Oracle приходится ограничивать время пребыван ия в этом режиме. После запуска триггера Огасlе извлекает блок в текущем режиме и отмечает, что столбец, применявши йся для поиска этой строки (Х) , был модифицирован . Так как для нахождения этой записи использовался столбец Х, и он был изменен, база дан­ ных решает перезапустить наш запрос. Обратите внимание, что изменение значения х с 1 на 2 не выносит эту строку за рамки области действия ; мы по-прежнему будем обновлять ее с помошью этого оператора U P DATE . Взамен мы имеем ситуацию, при которой для поиска строки применялея столбец Х, и полученное посредством со­ гласованного чтения значение этого столбца ( 1 ) отличается от значения, прочитан­ ного в текушем режиме ( 2 ) . Теперь, после перезапуска, три ггер видит значение Х=2 (вследствие модификации в другом сеансе) как : OLD и значение Х=З - как : NEW. Итак, мы убедил ись, что случаи перезапуска был и . Благодаря триггеру мы уви ­ дели и х в действии ; по-другому их обычно обнаружить невоЗАюжно. Это не значит, что вы не заметите другие симптомы, такие как крупный оператор U P DAT E, выпол ­ няющи й откат работы после обновления многих строк и затем находяший строку, которая стала прич и ной его перезапуска; просто трудно сказать определенно, что какой-то конкретны й симптом обусловлен именно перезапуском. И нтересным наблюдением является то, что три ггеры сами могут стать причиной перезапуска, даже если собственно оператор не гарантирует этого. Обычно столб­ цы, упоминаемые в конструкции WHERE оператора U P DAT E или DELETE, использу­ ются для определения того, нуждается ли модификация в перезапуске . СУБД Oracle выполнит согласованное чтение с применением таких столбцов и при извлечен и и блока в текущем режиме перезапустит оператор, если обнаружит, что любой из этих столбцов измен ился . Как правило, другие столбцы в строке не инспектируются . Например, давайте просто перезапустим предыдущи й пример и воспользуемся конс­ трукцией WHERE У> О , чтобы найти строки в обоих сеансах. В первом сеансе (блоки­ рован ном) мы увидим следующий вывод: EODA@ORA12CR1> update t set х = х + 1 where у > О ; o1d . x = 1 , o1d . y = 1 new . x = 2 , new . y = 1 old . x = 2 , old . y = 1 new . x = 3 , new . y = 1 1 row updated . 1 строка обновлена . 384 Глава 7 Так почему же база данн ых Oracle дважды запускала триггер, когда искала зна­ чение У? П роверяла ли она цели ком всю строку? Как видно в выводе , обновление дей ствительно было перезапущено и три ггер снова сработал дважды, хотя мы вы­ полняли поиск по условию У>О и вообще не модифицировали столбец У. Но если переписать три ггер так, чтобы он просто сообщал о факте своего запуска, не ссы­ лаясь н а значения : OLD и : NEW, а затем снова войти во второй сеанс и запустить обновление, то мы будем наблюдать, что оно заблокировано (естественно) : EODA@ORA12CR1> create or replace trigger t bufe r 2 before update on t for each row 3 begin dЬms_output . put_l ine ( ' fi red ' ) ; 4 5 end ; б 1 Trigger created . Триггер создан . EODA@ORA12CR1> update t s e t х = х+ 1 ; f i red 1 row updated . 1 строка обновлена . После фиксации блокирующего сеанса мы увидим такой результат: EODA@ORA12CR1> updat e t s e t х = х+ 1 where у > О ; f i red 1 row updated . 1 строка обновлена . Н а этот раз триггер сработал только один раз, а не два. Таким образом , знач� ния столбцов : OLD и : NEW, когда он и присутствуют в триггере, также задействованы Oracle при п роверке необходимости перезапуска. Когда мы ссылаемся в триггере на : OLD . Х и : NEW . Х, значения согласованного чтения и текущего чтения х сравнива­ ются и оказываются разными. Перезапуск произойдет. Когда мы удалили ссылку на этот столбец из три ггера, перезапуска не будет. Итак, правило заключается в том , что набор столбцов в конструкции WHERE, ис­ пользуемых для нахожден ия строк, плюс столбцы , участвующие в триггерах строк, будут сравни ваться . Версия строки , полученная при согласован ном чтении, будет сравниваться с версией , полученной с помощью текущего чтения , и если они отли­ чаются , то оператор модификации перезапустится. На заметку! Эта и нформация способствует дальнейшему пониманию причин, по которым применение триггера AFTER FOR ЕАСН ROW более эффекти вно, чем три ггера BE FORE FOR ЕАСН ROW . Триггер AFTER не обеспечит тот же самый результат - к этому моменту блок уже извлечен в текущем режиме. Все это приводит к вопросу: почему нас это заботит? Параллел и зм и мно г оверси о н н ость 385 П очему перезапуск важен дл я нас ? Первая реакция должна быть такой : наш триггер сработал дважды! У нас есть таблица с еди нственной строкой и триггером BE FORE FOR ЕАСН ROW. Мы обновил и одну строку, а триггер вызывался два раза. Подумайте о потенциальн ых п оследствиях этого факта . Если три ггер делает что-нибудь нетранзакционное, то это может стать довол ьно серьезной проблемой . Например, рассмотрим триггер, который отправляет обновление, когда в теле со­ общения электронной почты присутствует фраза "This is what the data used to look like. It has Ьееп modified to look like this поw ("Так выглядят испол ьзуемые дан ные . Они были модифицированы , чтобы теперь вы глядеть подобным образом . " ) . Если вы отправляете сообщение электронной почты прямо из триггера с помощью пакета UTL_SMT P в Oracle9i или пакета UT L_MA I L в Огасlе I Og и последующих версиях, то пользователь получит два сообщения , одно из которых уведомит об обновлении, ко­ торое на самом деле никогда не происходило. Перезапуск будет оказы вать влияние на все, что делается в триггере и не являет­ ся транзакционным. Рассмотрим перечисленные н иже последствия . • Представим триггер, который поддержи вает ряд глобал ь н ы х перемен н ы х PL/SQL, таких как количество обработанных строк. Когда производится откат перезапускающегося оператора, модификации в переменных PL/SQ L откату не подвергаются . • Почти любую функцию, которая нач и нается с U T L_ {UTL_F I L E , UT L_HT T P , UTL_SMT P и т.д.) следует считать восприимч и вой к перезапуску оператора. При перезапуске оператора функци и UTL_ F I LE не смогут отмен ить то, что они за­ писали в файл . • Любой три ггер, я вляющи йся частью автономной транзакции, должен ставить­ ся под сомнение. Когда оператор перезапускается и происходит откат, авто­ номные транзакци и не могут быть отменены. ." Все эти последствия должны обрабатываться осторожно с надеждой на то, что триггеры могут быть иници ирован ы более одного раза на строку ил и запущены для строки, которая вообще не будет обновлена оператором. Вторая причина, по которой вы должны заботиться о потенциальном перезапус­ ке , связана с производительностью. М ы продемонстрировали однострочн ы й при­ мер, но что случится , если вы начнете круп ное пакетное обновление, и оно переза­ пустится после обработки первых 1 00 000 записей? Ему придется выпол н ить откат 1 00 000 изменений строк, перезапуститься в режиме S E LECT FOR U P DAT E и затем снова обновить эти 1 00 000 строк. Вы можете заметить, что после ввода в действие такого простого три ггера аудита (который читает значения : O L D и : NEW) производительность стала намного хуже , чем можно было бы объяснить, хотя кроме добавления триггера ничего не измени­ лось. Это может происходить из-за перезапуска запросов, которые ни когда ранее не использовались. Или же добавление крошечной программы , обновляющей еди нс­ твенную строку в нескольких местах, приводит к тому, что пакетный процесс, ранее выполнявшийся за час, неожиданно стал работать м ного часов из-за перезапуска, который раньше никогда не случался. Это не новая особен ность Oracle она присутствует в базе данн ых, нач иная с версии 4.0, когда была введена согласованность чтения. До лета 2003 года я сам не - 386 Глава 7 вполне ориентировался , каким образом она работает, и после того как разобрался, на что эта особен ность влияет, то смог ответить на массу вопросов типа " как это могло случиться?" из собственной практики . Я дал зарок почти ни когда не приме­ нять автономные транзакции в триггерах, и мне пришлось пересмотреть способ ре­ ализации некоторых своих ранних приложен ий. Н апример, я ни в коем случае не стану отправлять сообщения электронной почты напрямую из триггера; вместо это­ го я всегда буду испол ьзовать DBMS _ JOB или подобн ы й пакет, чтобы производить отправку после фиксации транзакции . Это сделает процедуру отправки электрон­ ной почты транзакционной, т.е . есл и оператор, иници ировавший запуск три ггера и отправку электрон ной почты , будет перезапуюен , то откат, который при этом про­ изойдет, заодно отменит и запрос DBMS _ JOB. Почти все нетранзакционные действия , которые выполнялись в триггерах, были модифицированы , чтобы делать всю работу после факта фи ксации , обеспечивая согласованность в отношении транзакций. Р ез ю ме В настоя щей главе м ы представил и множество сведен и й , которые иногда мог­ ли быть не особен но очевидн ы м и . Тем не менее, пон имать все это очень важно. Например, есл и вы не осведомлены о перезапуске на уровне операторов, то не смо­ жете разобраться , что служит причиной ряда загадоч ных ситуаций. То есть вы не сможете объяснить некоторые ежедневные эмпирически е наблюдения. Фактически , если вы не знаете о перезапуске , то можете строить неверные предположения о при­ ч инах сбоев или ошибках конечных пользователей. Это может оказаться одной из невоспроизводимых проблем , когда случаются м ногие события, причем в специ­ фичном порядке. М ы ознакомились со смыслом уровней изоляции согласно формулировкам в стан­ дарте SQL и посмотрели , как они реализованы в Oracle; временами мы проводили сравнение их реализации в Oracle с реализациями в других СУБД. Бьvю показано, что в других реализациях (т.е. тех, которые задействуют блокировки чтения для обеспече­ н ия согласованности данных) существует крупный компромисс между параллелизмом и согласованностью. Чтобы получать доступ к данным с высокой степенью паралле­ лизма, приходится понижать требования к согласованности ответов. Чтобы получать согласованные и корректные ответы , необходимо смириться с меньшей степенью па­ раллелизма. Благодаря средству м ноговерсионности Oracle это не касается . В табл. 7.9 подведены итоги того, что можно ожидать от базы данных, в которой применяется блокировка чтения , в сравнении с подходом многоверсионности Oracle . Управление параллелизмом и особен ности его реал изации в базе дан ных опреде­ ленно следует пон и мать. Я восхвалял м ноговерсионность и согласованность чтения , н о , как и все в этом мире, о н и имеют оборотную сторону. Если в ы н е понимаете многоверсионность и ее работу, то неизбежно будете допускать ош ибки при про­ ектировании приложе н и й . Вспомните пример планировщика ресурсов из главы 1 . В базе данных, н е обладающей многоверсионностью и ассоциированными с ней не­ блоки рующим и чтениями, исходная логика программы должна быть очень тщатель­ но п роработана. Однако эта логика потерпела бы неудачу при реал изаци и в среде Огасlе. Она могла бы при вести к нарушени ю целостности дан ных. Если вы не знае­ те , как работает многоверсионность, то будете писать программы, которые разруша­ ют дан ные. Это так просто. Таблица 7 . 9 . Сравнение уровней изоляции транзакций и поведения блокировки в Oracle и базах данных, в которых используется блокировка чтения Ч тение блокирует з апис ь Чу вствительное к взаимоблокировка м чтение Некорре кт ные результаты запросов Потерянные обновл ения Э скалация блокировок или ограничения Уровен ь ИЗОЛЯЦИИ Реализация Запис ь блокирует чтение READ UNCOММITTED Не Oracle Нет Нет Нет Да Да Да READ СОММIТТЕD Не Oracle Да Нет Нет Да Да Да READ СОММIТТЕD Oracle Нет Н ет Нет Нет Н ет Нет RЕ РЕАТАВLЕ READ Не Oracle Да Да Да Нет Н ет Да SERIALI ZAВLE Не Oracle Да Да Да Нет Н ет Да SERIALI ZABLE Oracle Нет Н ет Нет Нет Нет Нет * С оператором S E LECT FOR UPDATE NOWAI T . ГЛ А В А 8 Тр ан з акц и и т ранзакции - это одно из средств, которые отличают базы дан ных от файловых систем. Есл и вы находитесь на середине записи файла и операционная система аварийно завершается , то этот файл, скорее всего, будет поврежден . Надо сказать, что суmествуют файловые системы с ведением журналов, которые могут восстано­ вить файл на какой-то момент времен и в прошлом . Тем не менее, если нужно удер­ живать два файла в синхронизированном состоя н и и , то такие системы в этом не помогут - если вы обновите один файл , а в системе произойдет отказ, прежде чем будет завершено обновление второго файла, файлы не будут синхронизированы. В этом и заключается основное предназначение транзакций - они переводят базу данных из одного согласованного состояния в другое . Это их фун кция . Когда вы фиксируете работу в базе данных, то можете быть уверены, что будут сохранены либо все внесенные изменения , л ибо н и одного из них. Более того, гарантируется реализация разнообразных правил и проверок, защищающих целостность данных. В предыдущей главе мы обсуждали транзакции в терминах управления п арал­ лелизмом и говорили о том , как в результате испол ьзования многовереионной со­ гласован ной по чте н и ю модели Oracle транзакции кажды й раз могут обеспеч ить непротиворечи вость данных в условиях доступа к данн ы м с высокой степенью па­ раллел изма. Транзакции в Oracle удовлетворяют всем обязательны м характеристи ­ кам AC I D : • атомарность (atomicity) - выполняются л ибо все действия , произведенные в транзакции, либо ни одного; • согласованность (consistency) - транзакция перемешает базу данн ых из одного согласованного состоян ия в другое; • изоля ция (isolation) результаты транзакции могут быть не видны другим транзакциям до тех пор, пока она не будет зафиксирована; • постоянство (durabllity) - как только транзакция зафиксирована, она остается постоянной . - В частности , в предыдущей главе было показано, каким образом Oracle обеспе­ чивает согласованность и изоляцию. Здесь м ы сосредоточи м основное внимание на концепции атомарности и ее применении в Oracle. В настоящей главе речь пойдет о последствиях атомарности и о том , каки м обра­ зом она влияет на операторы в Oracle . Мы рассмотрим операторы управления тран ­ закциям и , такие как COMM I T , SAVE PO I NT и ROLLBACK, и обсудим способы прину- 390 Глава 8 дительного применения ограничений целостности в транзакциях. Кроме того, мы посмотрим, почему могут вырабатываться определенные плохие привычки в отно­ шении транзакций, есл и вы зан имались разработкой приложений в других СУБД. Мы также взглянем на распределенные транзакци и и двухфазную фиксацию (Two Phase Commit 2 РС). Н аконец, м ы исследуем автономные транзакции - что они собой представляют, и какую и грают роль. - Операторы уп равления транзак ц ия м и В Oracle нет необходимости в операторе типа "начать транзакцию". Транзакция начинается неявно с первым оператором , который модифицирует данные (первым оператором , получающим блокировку ТХ) . Транзакци ю можно начать я вно с ис­ пользованием оператора S E T T RAN SACT I ON или пакета DBMS _T RAN SAC T I ON, но в Oracle этот шаг не обязателе н в отл ичие от ряда других СУБД. Оператор COMM I T или ROLLBACK явно завершает транзакцию. На заметку! Не все операторы ROLLBAC K создаются идентичными. Следует отметить, что команда ROLLBACK то SAVE POI N T не завершает транзакцию! Это делает только надле­ жащий полный оператор ROLLBACK. В ы должны всегда я вн о заверш ать свои транзакц и и с помощью оператора сомм r т или ROLLBACK, иначе применяемы й и нструмент или среда самостоятельно выберет тот или другой оператор. Если вы нормально выходите из сеанса SQL*Pius без фиксации или отката, то SQL* Pius предполагает, что вы хотите зафиксировать проделанную работу, и делает это. С другой стороны , если вы выходите из програм­ мы на Pro*C, то производится неявный откат. Н и когда не полаrайтесь на нея вное поведение, потому что в будущем оно может измен иться . Всегда завершайте я вно СВОИ транзакции с ПОМОЩЬЮ COMM I T ИЛ И ROLLBACK. На заметку! В качестве примера того, что меняется с течением времени: SQL* Plus в Oracle 1 1 g Release 2 и последующих версиях содержит настройку exi t commi t, которая управ­ ляет тем , какую команду SQL*Pius выдаст при выходе сомм r т или ROLLBACK. Таким образом, когда вы используете версию Oracle 1 1 g Release 2, стандартное поведение, ко­ торое было характерно для средства SQL* Pius с момента его появления, вполне может оказаться другим ! - Транзакции в Oracle являются атомарными в том смысле, что каждый опера­ тор, составляющий транзакцию, фиксируется (делается постоянным) или же проис­ ходит откат всех операторов. Эта защита распространяется также на и ндивидуал ь­ ные операторы . Весь оператор либо полностью успешен, либо полностью неудачен. Обратите внимание н а сказанное : производится откат "оператора" . Отказ одного оператора не вызывает автоматического отката ранее выполненных операторов. Их работа предохраняется и должна быть л ибо зафиксирована, л ибо отменена (путем отката) вами . Прежде чем мы углубимся в детали того, что в точности означает ато­ марность для оператора и транзакции , давайте посмотрим на разнообразные опера­ торы управлен ия транзакция м и , имеющиеся в нашем распоряжении. - Тран закци и 39 1 • сомм r т . Простейшая форма этого оператора выглядит просто как COMM I T . М ожно применить более м ногословную форму и выдать сомм r т WORK, н о эти две формы экви валентны . Оператор сомм r т заверш ает транзакцию и делает любые изменения постоянными (сохраняет их) . Сушествуют расширения опе­ ратора сомм r т , испол ьзуемые в распределенных транзакциях, которые дают возможность снабжать сомм r т (помечать транзакцию) некоторым осмыслен­ ным комментарием и при нудител ьна фиксировать сомнительную распреде­ ленную транзакцию. Есть также расш ирения, которые позволя ют выполнять асинхрон ную фиксацию - фиксаци ю, которая в де йствительности нарушает кон цепцию постоянства. М ы слегка коснемся этого момента и посмотр и м , когда подобное может пригодиться . • ROLLBACК. Простей шая форма этого оператора выглядит как ROLLBACК. Опять­ таки , суmествует более многословный вариант ROLLBACK WORK, но эти формы эквивалентн ы. Откат (rollback) завершает транзакцию и отменяет все незафик­ сированные изменения . Это делается путем чтения информ ации, хранящейся в сегментах отката/отмены (далее я буду называть их сегментами отмен ы (undo segments) , как это принято в терминологии Oracle l Og и последующих версий) и восстановления блоков базы дан н ых в состояние, в котором они пребывали до начала транзакци и . • SAVE PO I N T . Оператор SAVE P O I N T позволяет создать маркирован ную точку внутри транзакци и . В одной транзакци и можно и меть множество таких точек. • ROLLBACK то < SAVE PO I NT > . Этот оператор применяется вместе с командой SAVE PO I N T . Транзакцию можно откатить к желаемой маркированной точ ке , не откатывая работу, выполнен ную до н е е . Таким образом , можно выдать два оператора U P DAT E , за которы м и следует SAVE PO I N T , и затем два оператора DELET E . Если во время выпол нения операторов DELETE происходит ош ибка либо исключительная с итуация определенного вида, а вы перехватываете ис­ ключение и выдаете команду ROL LBACK т о SAVE PO I N T , то транзакция будет подвержена откату к именованной точ ке сохранения , отменяя всю работу, ко­ торая была выполнена операторами DELETE, но оставляя незатронутым то, что сделано операторами UPDATE. • SET TRANSAC T I ON. Этот оператор позволяет устанавли вать различные атрибу­ ты транзакци и , такие как уровень изоляции и то, предназначена она только для чтения или для чтения-зап иси . Оператор S E T T RAN SAC T I ON можно так­ же использовать для и нструктирован ия транзакции о необходимости работы со специфически м сегментом отмен ы , когда применяется ручное управление отменой , но поступать так не рекомендуется . Автоматическое и ручное управ­ ление отменой более подробно обсуждается в главе 9. Выше были перечислены все операторы управления транзакция м и . Наиболее часто используемыми из них я вля ются COMM I T и ROLLBACK. Оператор SAVE POINT имеет до некоторой степени специальное назначен ие. Внутри Oracle он применяет­ ся часто; фактически он используется всякий раз, когда вы запускаете любой опе­ ратор SQL ил и PL/