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