12 мар. 2012 г.

TAF метод SELECT

В общем случае TAF, переключив приложение на другой узел кластера, не может прозрачно продолжить работу этого приложения, поскольку у погибшей сессии был контекст который неоткуда взять (активные транзакции, значения переменных PL/SQL, параметры сессии установленне с помощью команд ALTER SESSION). Однако существуют приложения, для которых это возможно прозрачно сделать. Это DSS-приложения, то есть приложения ориентированные на получение отчетов. В процессе работы приложения этого типа в основном выполняют SQL- запросы.
В отличие от типа SESSION, при использовании метода SELECT Oracle Client помимо создания новой сессии производит восстановление открытых курсоров “погибшей” сессии.

Проверим, как работает метод SELECT, предварительно определив в файле tnsnames.ora следующий алиас:
RACDB_SELECT =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac-scan.cluster.us.oracle.com)(PORT = 1521))
    (FAILOVER = yes)
    (CONNECT_DATA =
      (FAILOVER_MODE =
        (TYPE = SELECT)
        (METHOD = BASIC)
      )
      (SERVICE_NAME = racdb.us.oracle.com)
    )
  ) 

Откроем сессию в sqlplus с помощью вышеприведенного дескриптора соединения и по традиции проверим, к какому узлу кластера мы имеем соединение:

C:\RACDD4D\v4.1>sqlplus rscott/rtiger@racdb_select
SQL*Plus: Release 11.2.0.3.0 Production on Sat Jan 28 16:58:19 2012
Copyright (c) 1982, 2011, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production
With the Partitioning, Real Application Clusters and Automatic Storage Management options

SQL> SELECT dbms_utility.current_instance FROM dual;

CURRENT_INSTANCE
----------------
               2

Таблица accounts в схеме rscott содержит 200 тыс. записей. Поле acc_id этой таблицы было заполнено с помощью генерации последовательных значений последовательности (sequence).
SQL> SELECT COUNT(*) FROM accounts;

  COUNT(*)
----------
    200000

SQL>DESC accounts
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ACC_ID                                    NOT NULL NUMBER(6)
 ACC_NUM                                            VARCHAR2(20)
 ACC_CUR                                            VARCHAR2(3)
 ACC_BAL                                            NUMBER
 CUS_ID                                             NUMBER(6)
 ACC_STATUS                                         VARCHAR2(3)
 ACC_DATE_CREATED                                   DATE

SQL>

Запустим на выполнение простой запрос к этой таблице. После начала его выполнения подключимся непосредственно на второй узел и аварийно завершим экземпляр, на котором выполняется запрос, с помощью команды SHUTDOWN ABORT:
SQL> SELECT acc_id FROM accounts ORDER BY 1;
    151619
    151620
    151621
    151622
    151623
    151624

    ACC_ID
----------
    151625
    151626
    151627
    151628


В момент сбоя выполнение запроса “замораживается” на несколько секунд, а потом продолжается со следующей записи как ни в чем ни бывало!
151629
    151630
    151631
    151632
    151633
... ... ...
    199998
    199999
    200000

200000 rows selected.

   SQL> SELECT dbms_utility.current_instance FROM dual;

CURRENT_INSTANCE
----------------
               3


Как вы видите, с использованием типа SELECT, технология TAF позволяет помимо сессии также восстановить и состояние курсоров приложения. При этом продолжение выполнения запроса произошло абсолютно прозрачно для приложения: оно и не подозревало, что запрос завершил свое выполнение на другом (в данном случае третьем) узле.
На самом деле для того, чтобы обеспечить такую “магию”, Oracle Client производит большую работу. До момента сбоя, выполняя запрос, Oracle Client хранит в памяти клиентского компьютера:
  • текст запроса и значение его параметров (переменных привязки);
  • SCN на момент начала запроса;
  • количество прочитанных строк до момента сбоя;
  • рассчитанную контрольную сумму прочитанных строк.

Рис. 1 Иллюстрация алгоритма работы типа SELECT


После сбоя, переключившись на другой узел, Oracle Client производит следующие действия:
  • выполняет на этом узле запрос на момент времени заданный SCN на начало запроса;
  • незаметно для приложения прочитывает столько же строк результата запроса, сколько было прочитано до сбоя;
  • снова рассчитывает контрольную сумму прочитанных строк.
  • сравнивает полученную контрольную сумму с той, которая была до момента сбоя;
  • если значения старой и новой контрольных сумм совпадают, то продолжает чтение следующих строк и возвращает их приложению;
  • если значения старой и новой контрольных сумм не совпадает, то приложению выдается исключение “ORA-25408: can not safely replay call”, и выполнение запроса прерывается.
SCN на момент начала запроса нужен для того, чтобы гарантировать неизменность содержимого выборки после переключения на другой узел, поскольку за время прошедшее от начала выполнения до момента сбоя, содержимое запроса могло измениться.
Расчет контрольной суммы прочитанных строк необходим для проверки того, что порядок возвращаемых строк в запросе не изменился. Как вы помните, Oracle Database не гарантирует порядок результирующих строк запроса, если конечно это явно не определено фразой ORDER BY. Поэтому может получиться так, что после переключения, строки будут возвращены в другом порядке.

Часто и в OLTP-приложениях имеются модули формирования отчетности, поэтому применение метода SELECT также может быть востребовано и в транзакционных системах.