|
Программирование >> Проектирование баз данных
к сведению Каждый внешний ключ, который ссылается на таблицу, подверженную изменениям, должен индексироваться отдельно или находиться в лидирующей части индекса. Взаимоблокировки Рано или поздно любое сложное многопользовательское приложение сталкивается со взаимоблокировкой. Хотя в Oracle есть исключительно хорошие средства обнаружения взаимоблокировок, разрешение взаимоблокировок полностью возлагается на пользователя. Проектировщик и программист могут либо разрешить эту проблему в приложении (это правильный подход), либо оставить ее конечному пользователю (что связано с неприятностями). Проблема заключается в том, что когда Oracle генерирует ошибку DEADLOCK DETECTED, единственно возможное действие - вьшолнить откат текущей транзакции и повторить попытку. Крайняя мера - задержать повторение попытки на несколько секунд. Если взаимоблокировка встречается в одной транзакции более чем, скажем, три раза, мы рекомендуем, чтобы приложение сообщало об этом как о фатальной ошибке. Одно время внутренние стагвдарты на проектирование Oracle предусматривали установку стандартного порядка блокировки, который, как утверждалось, препятствовал бы возникновению взаимоблокировок. Это отличный принцип, но на практике он по ряду причин просто-напросто не работает: 1. Может быть, очень трудно написать код, обеспечивающий блокировку в установленном порядке, а код, который трудно писать, обычно дорого обходится и сложен в сопровождении. 2. В некоторых случаях, например в многострочных формах, порядок обновления, по сути дела, контролируется пользователем. Эту проблему можно обойти программно, но это достаточно утомительно. 3. Иногда Oracle сталкивается со слабыми взаимоблокировками, которые являются результатом соперничества за внутренние ресурсы. Одна из причин возникновения такой ситуации рассмотрена в главе 14. К сведению Рекомендуем, чтобы все фрагменты, в которых выполняется обновление, содержали простой код, необходимый для проверки наличия взаимоблокировок и немедленного отката транзакции. В зависимости от обстоятельств, можно выдавать сообщение об ошибке или повторять попытку выполнения транзакции установленное число раз, прежде чем обнаружится, что все плохо и требуется сообщение об ошибке. К сожалению, действие механизма обнаружения взаимоблокировок в Oracle не распространяется на распределенные взаимоблокировки. Вместо этого используется параметр экземпляра DISTRIBUTED LOCK TIMEOUT. Он указывает серверу Oracle, как долго он должен ждать ответа другого сервера на запрос блокировки перед тем, как просто сдаться и возвратить пользователю ошибку. Важно, чтобы весь код, который может понадобиться для установки распределенных блокировок, тоже учитывал эту ошибку . С ериализация По умолчанию Oracle не обеспечивает сериализацию, т.е. не может гарантировать, что при выдаче одних и тех же транзакций в одном и том же порядке по одному и тому же начальному содержимому данных всегда будет получен один и тот же ответ. Описание причин этого удивительного явления выходит за рамки нашей книги. Тем не менее, вам придется решать эту проблему, если вы по какой-то причине попробуете построить логику восстановления или перезапуска базы данных на повторном применении транзакций, а не на журналах Oracle. Наш опыт показывает, что проектировщики, избирающие этот путь, неизбежно терпят неудачу, отчасти из-за проблемы с сериализацией. Если же вам ну очень нужно воспользоваться этим методом (а мы советуем сделать почти все, чтобы избежать встречи с этой проблемой), то необходимо будет работать с параметром SERIALIZABLE=TRUE файла INIT.ORA и, вопреки нашему предыдущему совету, блокировать много и блокировать раньше. Каждый запрос перед началом выполнения будет устанавливать разделяемую блокировку на уровне таблицы. В версии 7.3 этот уровень изоляции можно установить на уровне транзакций, но с другим эффектом. Вместо того чтобы устанавливать разделяемые блокировки на уровне таблиц, не позволяющие другим пользователям обновлять таблицы, которые вы запрашиваете, запрос, выдавший команду SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; закончится неудачей с выдачей соответствующей ошибки, если посетит строку в блоке, который был изменен с момента начала транзакции. Наверняка это не то, что вам нужно. Другие вопросы проектирования в этом разделе содержится информация еще о некоторых проблемах, связанных с блокировкой, которые могут повлиять на ход проектирования. Пользовательские блокировки Процедурная опция Oracle включает мало используемый, но исключительно полезный пакет DBMS LOCK, позволяющий проектировщику реализовать стратегию кооперативной блокировки, которая может быть основана на чем угодно. С помощью этого пакета процессы могут соперничать за блокировки на 32-разрядных числах, значения которым присваивает приложение. Важная особенность этих блоюировок заключается в том, что они не обязательно должны быть транзакционными, т.е. они могут сохраняться после фиксации, тогда как все установленные сеансом пользовательские блоюировки после его завершения снимаются. Пользовательские блоюировки - эффективный способ резервирования ресурсов приложением. Мы применяли их для резервирования первичного ключа для последуюшего использования в транзакции, а также в качестве сигнала о том, что определенную таблицу нельзя использовать, потому что происходит реорганизация первичного ключа (охватывающая несколько транзакций). Эффективность блокировок: очистка блоков и блокировки на уровне таблиц Когда пользователь устанавливает блокировку на уровне строк в таблице Oracle, в заголовке блока этот факт отражается посредством создания ITE (interested transaction entry - записи о заинтересованной транзакции). Одна ITE в заголовке блока позволяет пользователю заблоюировать любое число строк в этом блоке, и для этой цели в заголовке каждого блока по умолчанию имеется одна ITE (INITRANS 1). Если один пользователь уже заблокировал в блоке какую-то строку, а другой пользователь хочет заблокировать в нем другую строку, то последний сможет продолжать работу только в том случае, если в блоке осталось достаточно места для создания второй ITE. В противном случае этому пользователю придется подождать, пока завершится первая транзакция. Впрочем, настояшие проблемы начинаются при фиксации, потому что в версиях до 7.3 блокировки не удаляются, а просто остаются на месте. Даже в версии 7.3 блокировки удаляются только в том случае, если содержащие их блоки все еще находятся в SGA, а параметр DELAYEDLOG-GING BLOCK CLEANOUTS в файле INIT.ORA установлен в значение FALSE. В оперативном режиме блокировки, как правило, остаются в SGA, но при выполнении длинных пакетных программ это менее вероятно. Пользователь, который будет следующим по какой-то причине посещать данный блок, понесет затраты на проверку блоюировюи на предмет того, действует ли она еще, и ее удалению, если она действует. На узлах, где ресурсы ЦП оплачивает пользователь, эта ситуация может вызвать возмущение, поскольку пользователям, вьщающим нерегламентированные запросы, придется в конечном итоге оплачивать счета за очистку блоков. Прег)1]11реждеш1е Очистка блоков замедляет первое обращение к данным после DML-операций над этими блоками. В этом причина многих неверных выводов о производительности Oracle, которые делаются в случае, когда специалист по производительности загрузит какие-то данные, а затем пробует получить к ним доступ двумя разными методами. Первый метод наверняка будет медленнее второго - просто из-за затрат, связанных с очисткой блоков.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |