|
Программирование >> Oracle
Теперь в каждой из таблиц имеется по строке со значением ноль. Если бы выполнялось последовательное упорядочение транзакций, мы не могли бы получить нулевые значения в обеих таблицах. Если бы сеанс 1 опережал сеанс 2, то в таблице В было бы значение 1. Если бы сеанс 2 выполнялся прежде сеанса 1, то в таблице А б1ло бы значение I. Однако при выполнении приведенной выше последовательности действий в обеих таблицах будут нулевые значения, т.е. транзакции выполняются так, будто других транзакций в базе данных в этот момент нет. Неважно, сколько раз сеанс 1 запрашивает таблицу В, - будет выдано количество строк, зафиксированных в базе данных на момент времени 0:00. Аналогично, независимо от количества запросов таблицы А, в сеансе 2 будет получено значение на момент времени 0:01. В Oracle последовательность достигается путем распространения согласованности по чтению, получаемой на уровне оператора, на уровень транзакции. Результаты не согласуются на момент начала выполнения оператора - они предопределены моментом начала транзакции. Весьма глубокая мысль: базе данных известен ответ на любой возможный ваш вопрос прежде, чем вы его зададите. вателей, изменяющих данные в базе данных; база данных замораживается на момент начала транзакции. Для транзакции база данных выглядит согласованной, в виде своего рода моментального снимка. Побочные эффекты (изменения) от других транзакций для такой транзакции невидимы, независимо от того, как долго она выполняется. Уровень изолированности SERIALIZABLE не означает, что все пользовательские транзакции дают такой же результат, как и при последовательном выполнении. Он не предполагает наличия физического порядка выполнения транзакций, дающего такой же результат. Это последнее утверждение часто понимают неправильно, и небольшой пример сейчас все прояснит. В следующей таблице представлены два сеанса, выполняющие определенную последовательность действий. Таблицы базы данных А и В первоначально пусты и созданы следующими операторами: tkyte@TKYTE816> create table a (x int) ; Table created. tkyte@TKYTE816> create table b (x int) ; Table created. Теперь происходят следующие события: Транзакции только для чтения Транзакции только для чтения очень похожи на транзакции с уровнем изолированности SERIALIZABLE. Единственное отличие в том, что они не разрешают изменять данные, поэтому не подвержены ошибке ORA-08177. Транзакции только для чтения предназначены для создания отчетов, когда данные отчета должны быть согласованы по отношению к определенному моменту времени. В других системах придется использовать уровень изолированности REPEATABLE READ, получая нежелательные последствия разделяемых блокировок чтения. В Oracle используется транзакция только для Этот уровень изолированности не дается даром: за него нужно платить сообщением об ошибке: ERROR at line 1: ORA-08177: cant serialize access for this transaction Это сообщение будет получено при любой попытке обновления строки, измененной после начала транзакции. Сервер Oracle придерживается при обеспечении последовательности оптимистического подхода; он предполагает, что данные, которые потребуется изменять вашей транзакции, не будут изменены другой транзакцией. Обычно именно так и происходит, и подобное предположение вполне оправдано, особенно в системах оперативной обработки транзакций (ООТ). Если в ходе транзакции ваши данные не изменяются другим сеансом, этот уровень изолированности, обычно снижающий степень параллелизма в других системах, обеспечит ту же степень параллелизма, что и при отсутствии транзакций с уровнем изолированности SERIALIZABLE. Вопрос лишь в том, не получите ли вы сообщения об ошибке ORA-08177, если предположение не оправдается. Однако поразмыслив, можно найти такой риск оправданным. Если уж используется транзакция с уровнем изолированности SERIALIZABLE, нет смысла ожидать изменения той же информации другими транзакциями. Если это возможно, используйте оператор SELECT ... FOR UPDATE, как было показано выше, который обеспечит требуемую последовательность доступа. Итак, если высока вероятность того, что данные не изменяет другой сеанс; необходима согласованность по чтению на уровне транзакций; транзакции будут непродолжительными (чтобы первое условие стало более реаль- то использование уровня изолированности SERIALIZABLE дает хороший эффект. Корпорация Oracle считает этот метод настолько масштабируемым, что выполняет на таком уровне изолированности все тесты TPC-C (стандартный набор тестов производительности систем ООТ; подробнее см. на сайте http: www.tpc.org). Во многих других реализациях это достигается путем использования разделяемых блокировок чтения со всеми соответствующими взаимными блокировками и ожиданием. В Oracle блокирования нет, но, если другие сеансы изменяют данные, необходимые вашему сеансу, будет получено сообщение об ошибке ORA-08177. Однако это сообщение об ошибке генерируется гораздо реже, чем происходят взаимные блокировки и ожидания снятия блокировок в других системах. чтения. В этом режиме результат, получаемый в отчете на основе данных, собранных 50 операторами SELECT, будет согласован по отношению к одному моменту - началу транзакции. Это можно сделать, не блокируя ни одного компонента данных, где бы то ни было. Достигается это с помощью того же многовариантного доступа, что и для отдельных операторов. Данные восстанавливаются при необходимости из сегментов отката и представляются в том виде, какой они имели до начала создания отчета. Однако использование транзакций только для чтения также не лишено проблем. Тогда как сообщение об ошибке ORA-08177 вполне вероятно для транзакций с уровнем изолированности SERIALIZABLE, при использовании транзакций только для чтения можно ожидать сообщений об ошибке ORA-1555 snapshot too old. Они будут выдаваться в системе, где другие сеансы активно изменяют считываемую нами информацию. Их изменения (данные отмены - undo) записываются в сегменты отката. Но сегменты отката используются циклически, аналогично журналам повторного выполнения. Чем более продолжительное время создается отчет, тем выше вероятность, что часть данных отмены, необходимых для восстановления данных, перестанет быть доступной. Сегмент отката будет использоваться повторно, и необходимая нам его часть окажется использованной другой транзакцией. В этот момент сеанс и получит сообщение об ошибке ORA-1555, и придется начинать все с начала. Единственное решение этой болезненной проблемы - сконфигурировать в системе сегменты отката адекватного размера. Постоянно приходится сталкиваться с ситуацией, когда, пытаясь сэкономить несколько мегабайт дискового пространства, создают сегменты отката минимально возможного размера (зачем тратить место на то, что мне фактически не нужно?). Проблема в том, что сегменты отката - ключевой компонент, обеспечивающий функционирование базы данных, и если их размер окажется меньше, чем нужно, - ошибка ORA-1555 гарантирована. За 12 лет использования Oracle 6, 7 и 8 я никогда не сталкивался с ошибкой ORA-1555 за пределами тестовой системы или среды разработки. При возникновении этих ошибок сразу становится понятно, что сегменты отката имеют недостаточный размер, но это легко исправляется. Мы еще вернемся к этой проблеме в главе 5. Резюме В этой главе мы рассмотрели большой объем материала, иногда трудного для понимания. Тогда как блокирование - тема весьма простая, некоторые его побочные эффекты понять сложнее. Однако знание всего этого жизненно важно. Например, если не знать о блокировке таблицы, используемой сервером Oracle для обеспечения требования внешнего ключа, когда он не проиндексирован, приложения будут иметь низкую производительность. Если не представлять себе, как определить по словарю данных, кто кого блокирует, трудно разобраться в причине происходящего. Просто покажется, что временами база данных зависает . Если бы я получал по доллару всякий раз, когда устранял неразрешимую проблему зависания с помощью запроса, выявляющего неин-дексированные внешние ключи и предлагающего соответствующий индекс, я бы уже был очень богатым человеком.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |