RAC PL/SQL API
Часто у PL/SQL-разработчиков возникают вопросы при программировании в среде RAC. Ниже я попытаюсь на них ответить.
1) Как программно определить: выполняется ли мой PL/SQL-код в RAC-database или в Single Node ?
Ответ: для этого в пакете DBMS_UTILITY есть логическая функция IS_CLUSTER_DATABASE; она возвращает значение ИСТИНА, если выполнение происходит в БД запущенной в кластере.
2) Как программно определить узел, на котором в данный момент времени выполняется мой PL/SQL-код?
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options
SQL> begin
2 if dbms_utility.is_cluster_database then
3 dbms_output.put_line('I am in cluster');
4 end if;
5 end;
6 /
I am in cluster
Ответ: Для этого можно применить функцию CURRENT_INSTANCE из того же пакета DBMS_UTILITY. Эта функция просто возвращает номер экземпляра БД, на котором работает ваша сессия.
SQL> exec dbms_output.put_line(dbms_utility.current_instance);Есть второй способ: прочитать значение переменной INSTANCE из стандартного контекста сессии USERENV.
1
Ну а как прочитать это значение, вы прекрасно знаете - с помощью вызова SYS_CONTEXT('USERENV','INSTANCE')
3) Как программно определить список "живых" узлов кластера ?
Ответ: Для этого в замечательном пакете DBMS_UTILITY есть процедура ACTIVE_INSTANCES, которая через out-переменные возвращает список активных в данный момент узлов кластера.
Обратите внимание, что в список попадут только "живые" узлы. Второй момент: имя узла возвращается в таком виде: полное имя хоста c именем экземпляра через символ двоеточия.
SQL> begin
2 v_xTable dbms_utility.instance_table;
3 v_xCount pls_integer;
4 begin
5 dbms_utility.active_instances(v_xTable,
6 v_xCount);
7
8 for v_xIndex in 1..v_xCount
9 loop
10 dbms_output.put_line(v_xTable(v_xIndex).inst_number ||
11 ' => ' ||
12 v_xTable(v_xIndex).inst_name);
13 end loop;
14 end;
15 /
1 => rac1.us.oracle.com:racdb1
2 => rac2.us.oracle.com:racdb2
3) Если я включу в свои хранимые PL/SQL-процедуры RAC-specific код, то мне нужно каждый раз переключаться между двумя ветками кода через IF-оператор и вызовы IS_CLUSTER_DATABASE. Это замедлит быстродейстивие и приведет к раздуванию кода ! Если же я сделаю два варианта хранимой процедуры: один - для Single Node, второй - для RAC, то это означает что мне одновременно придется поддерживать две версии моего кода.
Есть какое-нибудь решение этой проблемы ?
Ответ: Решение есть, и очень элегантное. Для этого используется условная компиляция.
Сначала вы создаете символ условной компиляции в виде логической константы спецификации пакета:
create or replace package RAC_SERVICE is
Is_RAC_Database constant boolean := true;
end;
Затем через условную компиляцию вы оформляете куски кода специфичные для RAC:
create or replace procedure create_my_pipe
x number;
begin
$if RAC_SERVICE.Is_RAC_Database $then
x := rac_pipe.create_pipe('MY_PIPE');
$else
x:= dbms_pipe.create_pipe('MY_PIPE');
$end
end;
Преимущества:
- не нужно сопровождать две версии исходного кода и устраняются проблемы связанные с этим;
- переключение кода в Single Node производится простой заменой константы Is_RAC_Database в пакете RAC_SERVICE, с последующей его перекомпиляцией; "реинкарнацию" остального кода в Single Node - режим автоматически будет произведена самой СУБД;
- в выполняемый код PVM (PL/SQL Virtual Machine) будут скомпилированы только те исходные тексты, которые специфичены для текущего режима работы (Single Instance или RAC).
а раздувание кода а последнем примере куда делось ? :)
ОтветитьУдалитьMichael
ps. откройте обратно чат!
pps. или, хотя бы - ответьте на почту
Я имел в виду раздувание выполняемго кода, а не исходного текста - от этого никуда не деться.
ОтветитьУдалить