Действительно, есть особенность поведения TAF связанная с тем, что оператор COMMIT, помимо выдачи исключения ORA-25405, дополнительно еще и сбрасывает маркер активной транзакции на клиенте - собственно начинает новую транзакцию.
Но обо все по порядку...
Как вы хорошо знаете, при сбое текущего узла Oracle Client (конечно если была включена поддержка TAF в дескрипторе в файле tnsnames.ora), прозрачно для приложения открывает новую сессию на другой узел.
Если сессия до сбоя имела некоторый контекст либо активную транзакцию, то при обращении к Oracle Call Interface возникает исключение. Этих исключений несколько - все они начинаются с префикса ORA-254xx.
Самый распространенный случай - на клиенте была активная транзакция; в этом случае приложение получает исключение "ORA-25402 transaction must rollback".
Используем вот такой дескриптор соединения в tnsnames.ora
racdb_taf =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(host = rac-scan)(PORT = 1521))
(FAILOVER = true)
)
(CONNECT_DATA =
(failover_mode=
(type=session)
(method=basic)
(retries=2)
)
(SERVICE_NAME = racdb.rac.com)
)
)
Подключаемся к кластеру по алиасу racdb_taf:
[oracle@racc ~]$ sqlplus rscott/rtiger@racdb_taf
SQL*Plus: Release 11.2.0.2.0 - Production on Sun Aug 28 19:07:27 2011
Copyright (c) 1982, 2010, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
SQL> select dbms_utility.current_instance from dual;
CURRENT_INSTANCE
----------------
1
SQL>rem Мы подключены к первому узлу
Выполняем вставку записей, но НЕ фиксируем транзакцию:
SQL> insert into taf_demo values(1);
1 row created.
SQL>
Подключаемся напрямую на узел, на котором "живет" наша сессия (в данном случае на первый узел), и аварийно завершаем экземпляр:rac2-> ssh rac1
Last login: Sun Aug 28 18:38:50 2011 from 192.168.1.95
rac1-> sqlplus / as sysdba
SQL*Plus: Release 11.2.0.2.0 Production on Sun Aug 28 19:13:45 2011
Copyright (c) 1982, 2010, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
SQL> shutdown abort;
ORACLE instance shut down.
SQL>
Возвращаемся в нашу сессию, которая была подключена к "погибшему" узлу, и пытаемся продолжить работу:
SQL> insert into taf_demo values(2);
insert into taf_demo values(2)
*
ERROR at line 1:
ORA-25402: transaction must roll back
SQL> select * from taf_demo;
select * from taf_demo
*
ERROR at line 1:
ORA-25402: transaction must roll back
SQL>
Все происходит согласно теории: маркер активной транзакции был установлен, но сессии уже нет, вернее есть (TAF автоматически произвел переключение на другой узел), - это уже другая сессия!
Попробуем сделать то, что сделал слушатель семинара: выдадим операцию commit:
SQL> commit;
commit
*
ERROR at line 1:
ORA-25405: transaction status unknown
SQL>
Мы получили другое исключение! Все верно - статус транзакции не определён, поскольку клиент имел незавершенную транзакцию и, незавершив ее, переключился на другой узел.
Теперь самое интересное: выдадим какой-нибудь DML-оператор:
SQL> insert into taf_demo values(2);
1 row created.
SQL> select * from taf_demo;
ID
----------
2
SQL> select dbms_utility.current_instance from dual;
CURRENT_INSTANCE
----------------
2
SQL>rem Мы автоматически переключились к второму узлу
SQL>
После оператора commit работа может быть продолжена!
То есть оператор commit, помимо выдачи исключения, производит то, что он обычно делает - начинает новую транзакцию.
Поэтому, если в TAF после сбоя текущего узла первым будет выполнен оператор commit, то нужно обрабатывать другое исключение, и при этом делать rollback уже НЕ обязательно!
Комментариев нет:
Отправить комментарий