СТАТЬЯ
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 внутри транзакции:
    Предложение SQL
    Результаты
    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 внутри своих транзакций.

    Разделяемый SQL

    ORACLE автоматически обнаруживает, когда два или более приложений посылают в базу данных идентичные предложения SQL. ORACLE идентифицирует идентичные предложения, используя следующий алгоритм:

    1. Строка текста, составляющая предложение SQL, хэшируется. Если результирующее хэш-значение совпадает с хэш-значением для существующего предложения SQL, ORACLE переходит к шагу 2.
    2. Строка текста, составляющая предложение SQL, посимвольно сравнивается со всеми существующими предложениями, которые были идентифицированы на шаге 1, включая пробелы и комментарии. Прописные и строчные буквы различаются. Например, следующие два предложения НЕ идентичны: SELECT * FROM emp;
      SELECT * FROM Emp; 
    3. Объекты, адресуемые в выданном предложении, сравниваются с объектами, адресуемыми во всех существующих предложениях SQL, которые были идентифицированы на шаге 2. Например, если каждый из двух пользователей имеет свою таблицу EMP, то два экземпляра предложения:
      SELECT * FROM emp

      от этих пользователей НЕ считаются идентичными, так как они адресуют разные объекты.
    4. Типы связных переменных, используемых в предложениях SQL, должны совпадать. Заметим, что ORACLE не обязан выполнять разбор предложения, чтобы определить его идентичность другому предложению, находящемуся в разделяемом пуле.

    При проверке на идентичность 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, встроенных в приложение.

    Объявление и открытие курсоров

    Не существует абсолютного ограничения на число открытых

    курсоров, которое приложение может иметь одновременно. Однако имеют место следующие неявные ограничения:

  • Каждый курсор требует виртуальной памяти, так что общее количество курсоров лимитируется памятью, доступной данному процессу.
  • Общесистемный лимит на количество курсоров на сессию устанавливается параметром инициализации OPEN_CURSOR в файле параметров (таком как INIT.ORA). Параметры инициализации описаны в документе ORACLE7 Server Administrator's Guide. Явное создание курсоров для программ прекомпиляторов может предоставить некоторые преимущества при настройке таких приложений. Например, увеличение числа курсоров зачастую может сократить частоту разборов и улучшить производительность. Если вы знаете, сколько курсоров может потребоваться в каждый момент времени, вы можете обеспечить возможность одновременного открытия этого количества курсоров.
  • Использование курсоров для повторного исполнения предложений

    После каждого этапа исполнения, курсор сохраняет достаточно информации о предложении 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.

    ROW SHARE и ROW EXCLUSIVE

    LOCK TABLE таблица IN ROW SHARE MODE;  
    LOCK TABLE таблица IN ROW EXCLUSIVE MODE;   

    Блокировки ROW SHARE (разделяемая для строк) и ROW EXCLUSIVE (монопольная для строк) обеспечивают наибольшую степень одновременного доступа. Следующие условия могут оправдывать необходимость в получении таких блокировок:

    SHARE

    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 

    SHARE ROW EXCLUSIVE

    LOCK TABLE таблица IN SHARE ROW EXCLUSIVE MODE;    
    

    Следующие условия могут оправдывать необходимость в получении блокировки SHARE ROW EXCLUSIVE (разделяемой для строк монопольной):

    EXCLUSIVE

    LOCK TABLE таблица IN EXCLUSIVE MODE; 

    Следующие условия могут оправдывать необходимость в получении блокировки EXCLUSIVE (монопольной для таблицы):

    Привилегии, требуемые для явного получения блокировок таблиц

    Вы можете автоматически получать блокировку таблицы любого типа по таблицам в вашей схеме. Чтобы получить блокировку таблицы в другой схеме, вы должны иметь либо системную привилегию LOCK ANY TABLE, либо любую объектную привилегию (например, SELECT, UPDATE) для этой таблицы.

    предыдущая часть | содержание | следующая часть

    Дополнительную информацию Вы можете получить в компании Interface Ltd.

    Обсудить на форуме Oracle
    Отправить ссылку на страницу по e-mail


    Interface Ltd.

    Ваши замечания и предложения отправляйте автору
    По техническим вопросам обращайтесь к вебмастеру
    Документ опубликован: 16.04.01