Как Oracle выполняет код PL/SQL: на заметку программисту

Как Oracle выполняет код PL/SQL: на заметку программисту
Стас Белков

Стас Белков

Автор статьи. Известный специалист в мире IT. Консультант по продуктам и решениям Oracle. Практикующий программист и администратор баз данных. Подробнее.

Прежде чем переходить к описанию механизма выполнения программ PL/SQL, необходимо определить пару важных понятий:

  •  Исполняющее ядро PL/SQL (виртуальная машина PL/SQL). Так называется компонент Oracle, выполняющий байт-код программ PL/SQL, который при необходимости вызывает сервер базы данных и возвращает результаты вызывающей среде. Исполняющее ядро написано на языке C. Традиционно оно включалось в некоторые клиентские инструменты, например Oracle Forms, где оно открывает сеанс подключения к удаленной базе данных и взаимодействует с ядром SQL через сетевой протокол.
  • Сеанс (Oracle). Для большей части (серверного) кода PL/SQL сеансом называется процесс и пространство памяти, связанные с аутентифицированным пользователем. Каждый сеанс имеет собственную область памяти, в которой хранятся данные выполняемой программы. Сеансы начинаются с момента входа пользователя в систему и завершаются при выходе из нее. Для получения информации о текущих сеансах используется представление V$SESSI0N. Oracle поддерживает для сеанса различные виды памяти, включая PGA (Process Global Area), UGA (User Global Area) и CGA (Call Global Area); они будут рассматриваться далее в этом разделе.

Рассмотрим несколько способов выполнения простейшей программы из очень популярной клиентской среды SQL *Plus. Это прекрасный пример приложения, ориентированного на выполнение в рамках сеанса и предоставляющего доступ к окружению PL/SQL, которое входит в состав сервера базы данных. (Об SQL*Plus и его использовании для выполнения кода PL/SQL рассказывается в этом блоге.) Конечно, при желании к серверу можно обращаться с вызовами из других приложений (например, из клиентских программ Oracle и даже из таких языков, как Perl, C или Java). Происходящее на сервере практически не зависит от клиентского окружения.

При выполнении кода PL/SQL из SQI?Plus задействован анонимный блок верхнего уровня. Вы, вероятно, знаете, что команда EXECUTE в SQL *Plus преобразует вызов программы в анонимный блок, но известно ли вам, что команда SQL CALL тоже генерирует упрощенную разновидность анонимного блока? По сути, прежде чем в Oracle9i появилась возможность непосредственного вызова PL/SQL из SQL, все такого рода вызовы производились с использованием анонимных блоков.

 

Пример

Начнем с простейшего анонимного блока:

BEGIN
   NULL;
END;

Что происходит при его отправке серверу Oracle? Чтобы ответить на этот вопрос, об­ратимся к Рис. 1.

Проанализируем процесс, представленный на этом рисунке.

  1.  Пользователь вводит исходный код блока, а затем отдает SQLfPlus команду на выполнение (косая черта). Как следует из рисунка, SQLfPlus отправляет весь блок, за исключением косой черты, серверу. Передача осуществляется через соединение, установленное для текущего сеанса (например, через Oracle Net или механизм межпроцессных коммуникаций).

Выполнение тривиального анонимного блока

Рис. 1. Выполнение тривиального анонимного блока

 

  1. Компилятор PL/SQL пытается откомпилировать полученный анонимный блок в байт-код. На первом этапе компилятор проверяет синтаксис и убеждается в том, что программа соответствует грамматике языка. В нашем тривиальном примере код не содержит ни одного идентификатора, а только ключевые слова языка. Если компиляция проходит успешно, Oracle помещает байт-код блока в общую область памяти, а если нет — возвращает сообщения об ошибках сеансу SQLfPlus.
  2. Исполняющее ядро PL/SQL интерпретирует байт-код и возвращает сеансу SQLfPlus признак успешного или неудачного завершения сеанса.

Добавим в анонимный блок SQL-запрос и посмотрим, как изменится процесс его выполнения. На Рис. 2 показаны некоторые компоненты сервера Oracle, участвующие в выполнении команд SQL.

В этом примере значение столбца извлекается из встроенной таблицы DUAL.

Убедившись в том, что код PL/SQL не содержит синтаксических ошибок, компилятор PL/SQL передает код SQL компилятору SQL. Аналогичным образом при вызове программ PL/SQL из команд SQL компилятор SQL передает вызовы PL/SQL компилятору PL/SQL. Компилятор SQL приводит выражения к непосредственно исполняемому виду, анализирует возможности применения кэшированных результатов функций (начиная с Oraclellg), проверяет семантику и синтаксис, проводит разрешение имен и определяет оптимальный план выполнения. Все эти действия являются частью фазы разбора SQL-выражения и предшествуют подстановкам связанных переменных, выполнению и выборке команд SQL.

Хотя PL/SQL использует компилятор SQL совместно с базой данных, это не означает, что в PL/SQL доступны все функции SQL. Например, SQL поддерживает функцию NVL2:

SELECT NVL2(NULL, 1, 2) FROM DUAL;

Однако попытка вызова NVL2 непосредственно из PL/SQL приводит к ошибке (PLS- 00201):

SQL> EXEC DBMS_OUTPUT.PUT_LINE(NVL2(NULL, 1, 2));
   2 BEGIN DBMS_OUTPUT.PUT_LINE (NVL2(NULL, 1, 2)); END;

*
ERROR at line 1:
ORA-06550: line 1, column 28:
PLS-00201: identifier 'NVL2' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

 

Выполнение анонимного блока, содержащего команду SQL

Рис. 2. Выполнение анонимного блока, содержащего команду SQL

При компиляции программы PL/SQL встроенные команды SQL подвергаются незначительным преобразованиям: из них удаляются секции INTO, на место локальных переменных программы подставляются связанные значения, удаляются комментарии, а многие идентификаторы (ключевые слова, имена столбцов, имена таблиц и т. д., но не рекомендации и литералы) преобразуются в верхний регистр. Например, если myvar является локальной переменной, PL/SQL преобразует команду select dummy into str from dual where dummy = myvar к следующему виду:

select dummy into str from dual where dummy = myvar

к следующему виду:

SELECT DUMMY FROM DUAL WHERE DUMMY = :B1

Из кода PL/SQL могут совершаться внешние вызовы двух типов:

  • Хранимые процедуры Java. Стандартная установка сервера баз данных включает не только виртуальную машину PL/SQL, но и виртуальную машину Java. Вы можете написать спецификацию вызова PL/SQL, логика которого реализуется в виде статического класса Java.
  •  Внешние процедуры. Исполняемую часть подпрограммы PL/SQL также можно реализовать в коде C. Во время работы база данных будет выполнять код в особом процессе и пространстве памяти, отделенных от главного сервера базы данных. Вы отвечаете за поддержку двоичных файлов и наличие копии у каждого узла RAS.

 

Ограничения компилятора

При компиляции очень большой программы PL/SQL от сервера можно получить сообщение об ошибке PLS-00123. Это означает, что компилятор вышел за пределы максимально допустимого количества узлов в дереве разбора. В таком случае программу проще всего разбить на несколько меньших подпрограмм или изменить ее архитектуру (например, использовать временную таблицу вместо 10 000 параметров). Трудно предсказать, сколько узлов понадобится для реализации программы, потому что не каждый узел соответствует какой-либо легко идентифицируемой единице исходного кода (лексеме, строке кода и т. д.).

По данным Oracle, «типичная» хранимая программа создает в среднем четыре узла на каждую строку кода, что дает следующие приблизительные ограничения:

Тип программы PL/SQL Приблизительный максимальный размер исходного кода в байтах
Тело пакета или типа; автономные функции и процедуры 256 Мбайт
Сигнатура (заголовок) отдельной функции или процедуры 128 Kбайт
Спецификация пакета или типа данных, анонимный блок 128 Kбайт

Приведенные значения весьма приблизительны; в реальных программах возможны значительные отклонения в обоих направлениях.

Некоторые из других документированных ограничений компилятора PL/SQL перечислены в следующей таблице.

Тип программы PL/SQL Максимальное значение
(приблизительное)
Уровни вложения блоков 255
Параметры, передаваемые процедуре или функции 65 536
Уровни вложения записей 64
Ссылки на объекты в программах 65 536
Количество обработчиков исключений в одной программе 65 536
Точность NUMBER (в знаках) 38
Размер VARCHAR2 (в байтах) 32 767

 

Вас заинтересует / Intresting for you:

Сопровождение объектных типов ...
Сопровождение объектных типов ... 3729 просмотров Максим Николенко Sun, 03 Nov 2019, 09:18:04
Oracle Text и PL/SQL: многоязы...
Oracle Text и PL/SQL: многоязы... 3498 просмотров Максим Николенко Fri, 18 Oct 2019, 12:41:03
Oracle IDE: JDeveloper, SQL De...
Oracle IDE: JDeveloper, SQL De... 4541 просмотров Ольга Потемкина Tue, 21 Nov 2017, 13:18:46
 Версии PL/SQL и Oracle 12c
Версии PL/SQL и Oracle 12c 3425 просмотров Александров Попков Tue, 21 Nov 2017, 13:28:01
Войдите чтобы комментировать

Oracle_Admin аватар
Oracle_Admin ответил в теме #9470 4 года 6 мес. назад
Профессиональный кодер просто обязан разбираться в таких тонкостях исполнения кода PL/SQL в базе данных Oracle. Ну а дилетанту лучше программировать на HTML (без обид, Веб-девелоперы).