СТАТЬЯ |
16.04.01
|
Состав транзакции обычно контролируется инструментом Oracle или приложением; основной заботой конечного пользователя является выбор, подтвердить или откатить данную транзакцию.
В общем случае, лишь разработчики приложений, использующие программные интерфейсы с ORACLE, решают, какие типы действий должны быть сгруппированы вместе в одну транзакцию. Транзакции должны быть определены надлежащим образом, с тем, чтобы работа выполнялась в логических единицах, и данные оставались все время согласованными. Транзакция должна состоять из всех необходимых частей такой логической единицы работы, не больше и не меньше. Данные во всех адресуемых таблицах должны находиться в согласованном состоянии как перед началом транзакции, так и после ее окончания. Транзакции должны состоять лишь из тех предложений SQL, которые в совокупности осуществляют одно согласованное изменение данных.
Например, передача денег с одного счета на другой (транзакция, или логическая единица работы), должна включать вычитание суммы с одного счета (одно предложение SQL) и прибавление этой суммы к другому счету (одно предложение SQL). Оба эти действия должны быть либо успешно выполнены, либо не выполнены вместе, как единица работы; нельзя подтверждать кредит без дебета. Другие не связанные с этой единицей действия, скажем, новый депозит на один из счетов, не должны включаться в транзакцию перевода денег.
Помимо определения состава транзакции, при проектировании приложения вы должны также определить, имеет ли смысл вам использовать процедуру BEGIN_DISCRETE_TRANSACTION, чтобы улучшить производительность коротких нераспределенных ("дискретных") транзакций. Дискретные транзакции обсуждаются в приложении A.
Явное назначение транзакции сегменту отката
Каждая транзакция требует ассоциированного сегмента отката. Обычно сегмент отката назначается транзакции автоматически. Вы можете, однако, явно назначить транзакцию подходящему сегменту отката, используя команду SET TRANSACTION с параметром USE ROLLBACK SEGMENT. Транзакции явно назначаются сегментам отката со следующими целями:
Для явного назначения транзакции сегменту отката необходимо, чтобы этот сегмент отката был доступен (в онлайне), и чтобы предложение SET TRANSACTION USE ROLLBACK SEGMENT было первым предложением в транзакции. Если указанный сегмент отката не доступен, или предложение
SET TRANSACTION USE ROLLBACK SEGMENTне первое предложение в транзакции, то возвращается ошибка.
Например, предположим, что вы подтвердили предыдущую транзакцию и собираетесь начать транзакцию, содержащую значительный объем работы (больше, чем
в большинстве других транзакций). В этом случае вы можете назначить транзакцию большому сегменту отката:
SET TRANSACTION USE ROLLBACK SEGMENT large_rs1
После подтверждения этой транзакции, очередная транзакция будет назначена какому-либо сегменту отката автоматически. Вы должны сообщить администратору базы данных обо всех сегментах отката, которые ваше приложение явно запрашивает для своих транзакций.
Для подтверждения транзакции используйте команду COMMIT. Следующие предложения эквивалентны и потдтверждают текущую транзакцию:
COMMIT WORK; COMMIT;Команда COMMIT позволяет вам включать параметр COMMENT вместе с комментарием (до 50 символов), поставляющим информацию о подтверждаемой транзакции. Эта возможность полезна для того, чтобы указывать источник транзакции при подтверждении распределенных транзакций, например:
COMMIT COMMENT 'Dallas/Accts_pay/Trans_type 10B';
Обратитесь к главе 11 для дополнительной информации о подтверждении сомнительных распределенных транзакций.
Чтобы отменить всю транзакцию или ее часть (до точки сохранения), используйте команду ROLLBACK. Например, каждое из следующих предложений откатывает всю текущую транзакцию:
ROLLBACK WORK; ROLLBACK;
Опция WORK команды ROLLBACK не выполняет никакой функции.
Для отката к точке сохранения, определенной в текущей транзакции, должна использоваться опция TO команды ROLLBACK. Например, каждое из следующих предложений откатывает текущую трназакцию к точке сохранения с именем POINT1:
ROLLBACK TO SAVEPOINT point1; ROLLBACK TO point1;
Обратитесь к главе 11 для дополнительной информации об откате сомнительных распределенных транзакций.
Определение точки сохранения транзакции
Для определения точки сохранения транзакции используйте команду SAVEPOINT. Следующее предложение создает точку сохранения с именем ADD_EMP1 в текущей транзакции:
SAVEPOINT add_emp1;
Если вы создаете вторую точку сохранения с тем же именем, что у более ранней точки сохранения, то более ранняя точка сохранения стирается. После того как точка сохранения создана, вы можете выполнять откат к этой точке.
Не существует ограничения на количество АКТИВНЫХ ТОЧЕК СОХРАНЕНИЯ на сессию. Активная точка - это точка сохранения, которая была специфицирована после последнего COMMIT или ROLLBACK. Пример COMMIT, SAVEPOINT и ROLLBACK
Следующая серия предложений SQL иллюстрирует применение предложений COMMIT, SAVEPOINT и ROLLBACK внутри транзакции:
|
|
SAVEPOINT a; | Первая точка сохранения в транзакции. |
DELETE ... ; | Первое предложение DML в транзакции. |
SAVEPOINT b; | Вторая точка сохранения в транзакции. |
INSERT INTO ... ; | Второе предложение DML в транзакции. |
SAVEPOINT c; | Третья точка сохранения в транзакции. |
UPDATE ... ; | Третье предложение DML в транзакции. |
ROLLBACK TO c; |
Предложение UPDATE откатывается, точка сохранения C остается определенной. |
ROLLBACK TO b; |
Предложение INSERT откатывается, точка сохранения C теряется, точка сохранения B остается определенной. |
ROLLBACK TO c; | Ошибка - точка сохранения C больше не определена. |
INSERT INTO ... ; |
Новое предложение DML в транзакции. |
COMMIT; |
Подтверждает все действия, выполненные
первым предложением DML в транзакции (DELETE) и последним предложением DML (вторым предложением INSERT). Все прочие предложения (второе и третье предложения DML) в этой транзакции были подвергнуты откату перед этим COMMIT. |
Привилегии, требуемые для управления транзакциями
Никаких привилегий не требуется от вас для управления вашими транзакциями; любой пользователь может выдавать предложения COMMIT, SAVEPOINT и ROLLBACK внутри своих транзакций.
ORACLE автоматически обнаруживает, когда два или более приложений посылают в базу данных идентичные предложения SQL. ORACLE идентифицирует идентичные предложения, используя следующий алгоритм:
SELECT * FROM Emp;
SELECT * FROM emp
от этих пользователей НЕ считаются идентичными, так как они адресуют разные объекты.
При проверке на идентичность ORACLE рассматривает как предложения SQL, выданные явно пользователями и приложениями, так и рекурсивные предложения SQL, выдаваемые внутренне как результат исполнения предложения DDL.
Если найдено предложение, идентичное выданному, то разделяемая область SQL, использовавшаяся для обработки первого экземпляра этого предложения, РАЗДЕЛЯЕТСЯ,
т.е. используется для обработки последующих экземпляров этого предложения. Поэтому для всех идентичных предложений SQL существует всего одна разделяемая
область SQL. Разделяемые области SQL являются областями разделяемой памяти компьютера; процессы ORACLE умеют совместно использовать такие области. Использование
разделяемых областей SQL экономит память на сервере базы данных и улучшает пропускную способность системы.
При обработке предложения SQL SELECT, UPDATE, INSERT или DELETE ORACLE должен обращаться к данным, адресуемым в этом предложении. Часть ORACLE, называемая ОПТИМИЗАТОРОМ, определяет эффективный путь к адресуемым данным, с тем, чтобы минимизировать ввод-вывод и время, требуемое для исполнения этого предложения. Оптимизатор формулирует ПЛАНЫ ИСПОЛНЕНИЯ и выбирает самый эффективный план, перед тем как исполнять предложение. При формулировании планов исполнения для предложения SQL оптимизатор использует один из двух способов: регулярный подход или стоимостной подход. Оба подхода рассматриваются в главе 5 этого руководства.
PL/SQL неявно объявляет курсор для всех предложений SQL манипулирования данными, включая запросы, возвращающие ровно одну строку. Для запросов, возвращающих более одной строки, вы можете явно объявлять курсор, чтобы обрабатывать возвращаемые строки индивидуально.
КУРСОР - это указатель на конкретную личную область SQL. Иными словами, курсор можно представлять себе как имя конкретной личной области SQL. Хотя большинство пользователей ORACLE полагаются на автоматическое управление курсорами, обеспечиваемое утилитами ORACLE, программные интерфейсы
предлагают разработчикам приложений большую степень контроля над курсорами. При разработке приложения, курсор является поименованным ресурсом, доступным программе, который можно специально использовать для разбора предложений SQL, встроенных в приложение.
Объявление и открытие курсоров
Не существует абсолютного ограничения на число открытых
курсоров, которое приложение может иметь одновременно. Однако имеют место следующие неявные ограничения:
Использование курсоров для повторного исполнения предложений
После каждого этапа исполнения, курсор сохраняет достаточно информации о предложении SQL, чтобы можно было повторно исполнять это предложение, не начиная с начала, до тех пор, пока с этим курсором не будет ассоциировано другое предложение SQL. Это проиллюстрировано на рис.4-1 на странице 4-2. Заметим, что повторное исполнение предложения может начинаться, минуя первые две фазы.
Открыв несколько курсоров, можно сохранить разобранное представление нескольких предложений SQL. Благодаря этому, повторное исполнение этих предложений можно начинать с шага связывания (BIND) или исполнения (EXECUTE), экономя на стоимости открытия курсоров и разбора.
Закрытие курсора означает, что информация, которая находится в ассоциированной личной области SQL, теряется, а память этой области освобождается. Открытый курсор закрывается в следующих случаях:
Явное (ручное) блокирование данных
ORACLE всегда выполняет необходимое блокирование, чтобы обеспечить одновременный доступ к данным, их целостность и согласованность по чтению на уровне предложения. Однако существуют опции, позволяющие перекрывать механизмы умалчиваемой блокировки. Ситуации, когда может быть выгодным перекрыть умалчиваемое блокирование ORACLE, следующие:
Механизмы автоматических блокировок ORACLE могут быть перекрыты на двух уровнях:
на уровне транзакции |
Умалчиваемые блокировки ORACLE перекрываются транзакциями, содержащими следующие предложения SQL: команду LOCK TABLE (которая блокирует либо таблицу, либо базовые таблицы указанного обзора), команду SELECT с фразой FOR UPDATE, а также команду SET TRANSACTION с опцией READ ONLY. Блокировки, получаемые этими предложениями, освобождаются по концу (подтверждению или откату) транзакции. |
на уровне |
Можно запустить инстанцию с отличным от системы умалчиваемого поведением блокировок, настроенным с помощью параметров инициализации SERIALIZE и ROW LOCKING. |
Следующие секции описывают все возможности перекрытия умалчиваемых блокировок ORACLE. Параметр инициализации DML_LOCKS определяет максимальное количество разрешенных блокировок DML (за обсуждением параметров обратитесь к документу ORACLE7 Server Administrator's Guide). Умалчиваемого значения должно быть достаточно; однако, если вы используете дополнительные ручные блокировки, вам может понадобиться увеличить это значение.
[!] Если вы перекрываете умалчиваемые блокировки ORACLE на любом уровне, то вы должны обеспечить, чтобы процедуры блокировок работали корректно. Эти процедуры должны удовлетворять следующим критериям: гарантируется целостность данных, степень одновременного доступа к данным приемлема, а захваты исключаются или обрабатываются должным образом.
Явное получение блокировок таблиц
Транзакция явно получает указанные блокировки таблицы, когда она выдает предложение LOCK TABLE. Предложение LOCK TABLE вручную перекрывает умалчиваемое блокирование. Когда предложение LOCK TABLE выдается для обзора, блокируются базовые таблицы этого обзора. Следующее предложение запрашивает монопольные блокировки для таблиц EMP и DEPT от имени содержащей транзакции:
LOCK TABLE emp, dept IN EXCLUSIVE MODE NOWAIT;
Вы можете указать несколько таблиц или обзоров, которые требуется заблокировать в одном и том же режиме; однако на одно предложение LOCK TABLE может быть специфицирован лишь один режим блокировки.
Вы можете также указать, хотите ли вы ждать получения блокировки. Если вы специфицируете опцию NOWAIT, то вы получите блокировку лишь в том случае, если она доступна немедленно. В противном случае возвращается ошибка, указывающая, что блокировка в данный момент недоступна. В этом случае вы можете повторить попытку заблокировать ресурс позже. Если опция NOWAIT опущена, то транзакция не будет продолжена, пока не получит запрошенную блокировку. Если ожидание блокировки таблицы 3 становится слишком долгим, вы можете захотеть снять операцию блокирования и повторить ее позже; вы можете предпочесть закодировать эту логику в ваших приложениях.
Замечание: Для распределенной транзакции, ожидающей блокировки таблицы, может иметь место таймаут, если истекшее время ожидания блокировки достигнет значения, установленного параметром инициализации DISTRIBUTED_LOCK_TIMEOUT. Обратитесь к секции "Сбои, препятствующие доступу к данным" на странице 11-7 для дополнительной информации об этом параметре.
Следующие параграфы предоставляют рекомендации о том, когда может быть выгодно получать тот или иной тип блокировки таблицы с помощью команды LOCK TABLE.
LOCK TABLE таблица IN ROW SHARE MODE; LOCK TABLE таблица IN ROW EXCLUSIVE MODE;
Блокировки ROW SHARE (разделяемая для строк) и ROW EXCLUSIVE (монопольная для строк) обеспечивают наибольшую степень одновременного доступа. Следующие условия могут оправдывать необходимость в получении таких блокировок:
LOCK TABLE таблица IN SHARE MODE;
Блокировка SHARE (разделяемая) является более ограничительной блокировкой таблицы. Следующие условия могут оправдывать необходимость в получении таких блокировок:
Хотя этот сценарий довольно нетипичен, его можно осуществить, заблокировав таблицу DEPT в режиме SHARE, как показано в следующем примере. Поскольку таблица DEPT не слишком изменчива, маловероятно, чтобы кому-либо из пользователей потребовалось обновить ее, пока она заблокирована для обновлений таблиц EMP и BUDGET.
LOCK TABLE dept IN SHARE MODE
UPDATE emp SET sal = sal * 1.1 WHERE deptno IN (SELECT deptno FROM dept WHERE loc = 'DALLAS') UPDATE dept SET totsal = totsal * 1.1 WHERE deptno IN (SELECT deptno FROM dept WHERE loc = 'DALLAS') COMMIT
LOCK TABLE таблица IN SHARE ROW EXCLUSIVE MODE;
Следующие условия могут оправдывать необходимость в получении блокировки SHARE ROW EXCLUSIVE (разделяемой для строк монопольной):
LOCK TABLE таблица IN EXCLUSIVE MODE;
Следующие условия могут оправдывать необходимость в получении блокировки EXCLUSIVE (монопольной для таблицы):
Привилегии, требуемые для явного получения блокировок таблиц
Вы можете автоматически получать блокировку таблицы любого типа по таблицам в вашей схеме. Чтобы получить блокировку таблицы в другой схеме, вы должны иметь либо системную привилегию LOCK ANY TABLE, либо любую объектную привилегию (например, SELECT, UPDATE) для этой таблицы.
предыдущая часть | содержание | следующая часть
Дополнительную информацию Вы можете получить в компании Interface Ltd.
Обсудить на форуме Oracle
Отправить ссылку на страницу по e-mail
Interface Ltd.Отправить E-Mail http://www.interface.ru |
|
Ваши замечания и предложения отправляйте
автору По техническим вопросам обращайтесь к вебмастеру Документ опубликован: 16.04.01 |