510 likes | 1.08k Views
Oracle Database 12c: Transaction Guard и Application Continuity. Игорь Мельников Oracle CIS. План. Введение Transaction Guard Application Continuity Заключение. Сбой БД во время выполнения транзакции. Текущая ситуация. Разрыв соединения с БД может привести к потере данных
E N D
Oracle Database 12c: Transaction Guard и Application Continuity Игорь МельниковOracle CIS
План • Введение • Transaction Guard • Application Continuity • Заключение
Сбой БД во время выполнения транзакции Текущая ситуация • Разрыв соединения с БД может привести к • потере данных • двойному вводу данных • необходимости перезагрузки серверов приложений • потере пользователей • Как следствие: • жалобы пользователей • потеря их доверия к приложению • сложность обработки ошибок при разработке приложений Пользователь Серверы приложений Серверы БД
Неизвестное состояние транзакции Текущая ситуация Пользователь выбирает товар и оплачивает его через web Пользователь Транзакция пользователя отправляется через сервер приложений в БД, где создаётся транзакция БД Серверы приложений Серверы БД
Неизвестное состояние транзакции Текущая ситуация Пользователь Транзакция пользователя отправляется через сервер приложений в БД, где создаётся транзакция БД Серверы приложений Транзакция фиксируется в БД и результат возвращается серверу приложений. Сбой в инфраструктуре может привести к тому, что сервер приложений никогда не получит ответ от БД. Серверы БД
Неизвестное состояние транзакции Текущая ситуация Пользователь Серверы приложений Приложение находится в неопределённом состоянии. Приложение возвращает пользователю ошибку, который может заказать товар второй раз, или даже оплатит дважды. Серверы БД
Transparent Application Failover (TAF) • Появилась в Oracle Database Client 8.0.6 Успешнопроизошло подключение к СУБД
TAF Transparent Application Failover (TAF) • Переключает приложение на другой узел Oracle RAC Сбой узла: приложение автоматически переключилось на второй узел
Возможности TAF • TAF сохраняет или восстанавливает: • Соединение между клиентом и сервером • Подготовленные SQL команды • Активные курсоры (команда select), начавшие возвращать результат выполнения • TAF не сохраняет и не защищает: • Активные транзакции (ORA-25402 transaction must roll back) • Серверные переменные PL/SQL пакетов • Состояние сессии пользователя (команды alter session)
Решения для разработчиков Новое в Oracle Database 12c
Transaction Guard Предоставляет информацию о результате выполнения COMMIT • API , который «знает» о каждой транзакции • Без Transaction Guard повтор транзакции может привести к логическим ошибкам • С Transaction Guard приложение корректно обрабатывает ситуацию возникновения ошибки • Прозрачно используется для Application Continuity Пользователь Серверы приложений Серверы БД
Application Continuity Маскирует запланированное/незапланированное отключение • Повторяет все вызовы к БД • Маскирует большинство ошибок ПО, систем хранения, сети,«железа» • Не требуется трудоёмкая разработка обработки ошибок приложения Пользователь Серверы приложений Серверы БД Транзакция повторяется
План • Введение • Transaction Guard • Application Continuity • Заключение
Что такое Transaction Guard? • Технология для получения надежной информации о фиксации последней (до сбоя) транзакции • Transaction Guard включает в себя поддержку как с стороны сервера, так и стороны клиента: • Клиент должен быть версии 12.1 и выше! • API доступен в всех интерфейсах программирования: OCI/OCCI, JDBC Thin, ODP.Net • Без Transaction Guard практически невозможно определить факт успешной фиксации транзакции – требуется сложное программирование, и автоматический повтор может привести к нарушению логической целостности данных • TG прозрачно используется в Application Continuity, но может быть использован и независимо от AC
Transaction Guard API для разработчиков Время Database Client Driver SQL, PL/SQL или RPC Start Transaction Транзакция Resultset SQL, PL/SQL или RPC Commit? Commit Communication failed
Transaction Guard for Java public class transactionGuardExample { ... OracleConnectionoconn = (OracleConnection) ods.getConnection(); // Получаем LTXID первой транзакции после подключения LogicalTransactionIdfirstLtxid = oconn.getLogicalTransactionId(); // Обновление LTXID происходит вызовом нашего callback-а oconn.addLogicalTransactionIdEventListener(this); } public class LtxidListenerImpl implements LogicalTransactionIdEventListener { ... public void onLogicalTransactionIdEvent(LogicalTransactionIdEventltxidEvent) { LogicalTransactionIdnewLtxid = ltxidEvent.getLogicalTransactionId(); // ЗапоминаемnewLtxidв глобальной переменной .... } }
Transaction Guard – server side APIПакет DBMS_APP_CONT ПроцедураGET_LTXID_OUTCOME • GET_LTXID_OUTCOME (client_ltxid IN RAW, committed OUT BOOLEAN, user_call_completed OUT BOOLEAN) где: • committed – TRUE, если транзакция с номером client_ltxidбыла зафиксирована, FALSE – НЕ была зафиксирована • user_call_completed – была ли вся информация после фиксации передана клиенту (например: число строк после autocommit)
Transaction Guard Сценарий использования Получаем событие FAN об отказе узла Если можно восстановиться после ошибки: Получаем LTXID последней транзакции в “погибшей”сесcиис помощьювызова getLogicalTransactionId Открываем новую сессиию Определяем факт фиксации с помощью вызова DBMS_APP_CONT.GET_LTXID_OUTCOME Если транзакция успела зафиксироваться Возвращаем управление: приложение может продолжать работу eсли транзакция НЕ успела зафиксироваться Генерируем исключение: приложение НЕ может продолжать работу
Transaction Guard for .Net (ODP.Net) class TransactionGuardDemo { static void Main(string[] args) { string txnConStr = "user id=hr;password=hr;data source=oracle"; OracleConnectiontxnCon = new OracleConnection(txnConStr); txnCon.Open(); byte[] logicalTransactionId = txnCon.LogicalTransactionId; try { OracleTransactiontxn = txnCon.BeginTransaction(); OracleCommandcmd = new OracleCommand( "update employees set salary=salary+10 where employee_id=100", txnCon); cmd.ExecuteNonQuery(); txn.Commit(); } finally { string statusConStr = "user id=hr;password=hr;data source=oracle"; OracleConnectionstatusCon = new OracleConnection(statusConStr); statusCon.Open(); OracleLogicalTransactionStatus status = statusCon.GetLogicalTransactionStatus(logicalTransactionId); Console.WriteLine("Has the transaction been committed? " + status.Committed); Console.WriteLine("Has the user call been completed? " + status.UserCallCompleted); } } } • В ODP.Netинкапсулирует вызов DBMS_APP_CONT. GET_LTXID_OUTCOME
Transaction Guard Поддержка широкого спектра технологий в СУБД • На стороне клиента • JDBC-thin, OCI, OCCI, ODP.net • На стороне сервера СУБД • Используется логический номер транзакции (logical transaction ID - LTXID) • Поддерживаются все виды фиксаций (commit-а) • Локальный commit (вызов команды COMMIT) • Auto-commit, • Commit внутри PL/SQL-объекта • DDL, DCL, Parallel DDL • Remote, Distributed • Не работает: впроцедурах использующих XA-интерфейси dblinks на read/write c ADG-базы
Transaction Guard Настройка Добавлены два новых атрибута сервиса: COMMIT_OUTCOME Значения: TRUE and FALSE По умолчанию: FALSE Применяется к всем сессиям подключенным к данному сервису RETENTION_TIMEOUT Единица измерения – секунды По умолчанию – 24 часа (86400 сек.) Максимальное значение – 30 дней (2592000 сек.) Пользователь должен иметь привилегию на выполнение пакета DBMS_APP_CONT
Transaction Guard Настройка – пример Новые параметры в утилите srvctl: • srvctl add service -d racdb -s OLTP -commit_outcome TRUE -retention 604800 -notification TRUE … … • Через пакет DBMS_SERVICE (для single-instance БД): declare v_xParamsdbms_service.svc_parameter_array; begin v_xParams(‘COMMIT_OUTCOME') := 'true'; v_xParams(‘RETENTION_TIMEOUT‘) := 604800; dbms_service.create_service('oltp',‘oltp',v_xParams); commit; end;
Transaction Guard Оптимизация производительности • История транзакций (значения LXID) сохраняется в таблице LTXID_TRANS • Расположена в табличном пространстве SYSAUX • Секционирована по номеру узла, при добавлении нового узла добавляется новая секция (ее storage-параметры берутся из последней секции) • При больших нагрузках рекомендуется перенести ее в табличное пространство на быстром носителе: ALTER TABLE ltxid_trans MOVE PARTITION ltxid_trans_4 TABLESPACE ssd_tbs STORAGE (INITIAL 25G NEXT 50G); Source: Gartner Top Five Trends for Private Cloud Computing, February 2012, Thomas J Bittman
Transaction Guard Особенности программирования • Вызов GET_LTXID_OUTCOME для текущей сессии будет возвращать ошибку • Вызов GET_LTXID_OUTCOME для “живой” сессии будет блокировать ее фиксацию • Вызов GET_LTXID_OUTCOME для другого пользователя будет возвращать ошибку • GET_LTXID_OUTCOME должен вызываться только для “погибшей” сессии!
План • Введение • Transaction Guard • Application Continuity • Заключение
Application Continuity Скрывает плановые и внеплановые простои • Повторяет транзакции восстанавливая приложение от ошибки • Когда это возможно: маскирует ошибки железа, ПО, систем хранения • Освобождает от трудоемкого программирования перехвата ошибок • Повышает продуктивность работы пользователей Транзакция 5. Ответ приложению 2. Вызовы к БД 4. Повтор операций 3. Ошибка Oracle Database12c
Application Continuity Поддержка как на стороне клиента, так и сервера СУБД • На стороне клиента • Пока только JDBC-Thin драйвер поддерживает Application Continuity • UCP, WebLogic Server, любые приложения сторонних разработчиков • Перехват JDBC-вызовов, сохранение вызов в очереди повтора • На стороне сервера БД • Поддерживаются все виды вызовов - SQL, PL/SQL, JDBC RPC • Select, ALTER SESSION, DML, DDL, COMMIT/ROLLBACK/SAVEPOINT • Поддерживаются все типы транзакций • Local, Parallel, Remote, Distributed • Cохранение результатов недетерминированных функций (sysdate, sequence, sys_giud)
RDBMS Instance1 Instance2 Instance3 Proxy 1 Proxy 2 Connection Replay Context Application ContinuityКак работает AC JDBC Driver Call 1 Call 2 Application
Включение Application Continuity для сервисаНастройка – пример 2. Модифицируем атрибуты сервиса: • 1. Включаем для сервиса Transaction Guard • srvctl modify service -d racdb -s demo_ac -failovertypeTRANSACTION -replay_init_time 1800 -failoverdelay 10 -failoverretry 30
Внутренняя архитектура Application Continuity
Включение Application Continuity Изменить тип соединения • Без поддержки Application Continuity (как до Oracle Database12с) PoolDataSourcepds = PoolDataSourceFactory.getPoolDataSource(); pds.setConnectionFactoryClassName(oracle.jdbc.pool.OracleDataSource); • Включить Application Continuity (только в Oracle Database12с) pds.setConnectionFactoryClassName(oracle.jdbc.replay.OracleDataSourceImpl);
Единица работы - “Database Request”Пул соединений: неявное определение границ повтора Начало • PoolDataSourcepds = GetPoolDataSource(); • Connection conn = getConnection(pds); • PreparedStatementpstmt = … • … • SQL, PL/SQL, local calls, RPC • … • conn.commit(); • conn.close(); Блок работы; обычно заканчиваетсяCOMMIT Конец
Единица работы - “Database Request”Явное определение границ повтора c помощью AC API Начало • ((oracle.jdbc.replay.ReplayableConnection) conn).beginRequest(); • PreparedStatementpstmt = … • … • SQL, PL/SQL, local calls • … • conn.commit(); • ((oracle.jdbc.replay.ReplayableConnection) conn).endRequest(); • … • Для non-pool соединений нужно явно выставлять границы повтора • Дляпулов соединений – опционально Блок работыопределен явно Конец
Application Continuity Три типа ограничений, для которых AC не поддерживается
Application Continuity Возможные побочные эффекты (side-effects) • Когда повтор включен, некоторые вызовы могут быть повторены,а для некоторых вызовов нужно отключать автоматический повтор: • Вызовы с автономными транзакциями • Обращения к пакетам • UTL_HTTP – обращение квеб-cерверу по HTTP • UTL_URL– • UTL_FILE, UTL_FILE_TRANSFER – работа с файлами • UTL_SMPT, UTL_TCP, UTL_MAIL – отправка сообщений по email • DBMS_PIPE – интеграция с внешними системами • DBMS_ALERT
Отключение повтораОтключение повтора для нетранзакционных вызовов • PreparedStatementpstmt = … • ((oracle.jdbc.replay.ReplayableConnection) conn).disableReplay(); • … вызов UTL_FILE • ((oracle.jdbc.replay.ReplayableConnection) conn).enableReplay(); • … • conn.commit; • conn.close(); • Для небезопасных вызовов повтор явно отключается: при ошибке исключение не перехватывается, а “пробрасывается” приложению • После прохождения соотв. части кода – снова включается Отключение повтора для группы операций
Application Continuity – sequence, sysdate, sysguidСохранение результата недетерминированных функций для повтора Владелец последовательности просто выполняет либо: SQL> GRANT [KEEP DATE TIME | KEEP SYSGUID].. [to USER] SQL> GRANT KEEP SEQUENCE.. [to USER] on [sequence object]; SQL> REVOKE KEEP SEQUENCE [from USER] on [sequence object]; SQL> ALTER SEQUENCE.. [sequence object] [KEEP|NOKEEP]; SQL> CREATE SEQUENCE.. [sequence object] [KEEP|NOKEEP];
Согласованное состояние сессии Session State Consistency • Выполнение вызова может зависеть от НЕтранзакционого контекста: • NLS-установки • Значение в application context (SYS_CONTEXT) • Глобальные переменные в PL/SQL-пакетах • Временные таблицы • Сообщения в очереди AQ
Согласованное состояние сессии Динамическое или статическое • Dynamic • Вызовы меняют нетранзакционный контекст (Напр: меняют значение глобальной переменной в PL/SQL-пакета) • Невозможно безопасно повторить вызов – нужно восстановить контекст, который был сформирован предыдущими вызовами • Static • Контекст постоянный для всех request-ов • Весь контекст необходимый для сессии может быть восстановлен как часть инициализации в request-е • Вызовы не меняют этот контекстдля других request-ов
Согласованное состояние сессии Новый атрибут сервиса - SESSION_STATE_CONSISTENCY • SESSION_STATE_CONSISTENCY • По умолчанию имеет значение DYNAMIC • Невозможно безопасно повторить вызов – нужно восстановить контекст, который был сформирован предыдущими вызовами • В утилите srvctlдобавлен новый параметр • -session_state {STATIC | DYNAMIC} • В пакете DBMS_SERVICEдобавлен атрибут • session_state_consistency для Parameter_Array
Функция установки контекстаConnection Inizialization Callback Регистрация функции обратного вызова, которая отвечает за инициализацию контекста • PoolDataSourcepds = GetPoolDataSource(); • pds.registerConnectionInitializationCallback(cbk); • Connection conn = getConnection(pds); • PreparedStatementpstmt = … • … • SQL, PL/SQL, local calls, RPC • … • conn.commit(); • conn.close(); • Интегрирован с UCP Labeling • Для однократного “разогрева” соединения
Ограничения Когда повтор не работает?
Как правильно “убить” сессию • alter system kill session 'sid, serial#, @inst' noreplay; • alter system disconnect session 'sid, serial#, @inst'noreplay; • В процедуре DBMS_SERVICE.DISCONNECT_SESSION • Опция NOREPLAY в параметре disconnect_option
WebLogic Server с Application Continuity Generic, Active GridLinkData Source Application Улучшение в доступности 1. Request 7. Response WebLogicServer • Простая конфигурация. • Тесты показывают доп. ~5% нагрузки CPU на клиентеи нет увеличения время отклика на клиентепри использовании AC • Интеграция с Transaction Guard дает непрерывность работы • Преимущество: маскирование ошибок отказа узла RAC 2. Request 3. Node 1 Down 4. New Connection 6. Response Listener 5. Replay Listener Listener FAN FAN FAN RACNode 1 RACNode 2 RACNode 3 RAC Cluster
TAF и Application Continuity В чем различие между TAF и Application Continuity? • Application Continuity • Пока только в JDBC Thin • Повторяет все виды запросов (SQL, PL/SQL) • Интегрирован с Transaction Guard • Для контекста нужно определять callback • Сохранение результатовнедерминированных функций для безопасного повтора • TAF • OCI, OCCI, JDBC Thin/OCI • Повторяет только операторы SELECT • Для контекста нужно определять callback • Все проверки и действия происходят только на клиенте