# 25

Аноним Funnybluejeans

Блокировка - это механизм, используемый для управления одновременным досту-

пом к общему ресурсу.

Проблемы блокирования:

Потерянное изменение - классическая проблема баз данных. Если коротко, поте-

рянное изменение возникает, когда происходят следующие события (в указанном по-

рядке).Блокирование и одновременный доступ

1. Пользователь 1 выбирает (запрашивает) строку данных.

2. Пользователь 2 выбирает ту же строку.

3. Пользователь 1 изменяет строку, обновляет базу данных и фиксирует изменение.

4. Пользователь 2 изменяет строку, обновляет базу данных и фиксирует изменение.

Пессимистическое блокирование

Этот метод блокирования должен использоваться непосредственно перед изменени-

ем значения на экране. Приложение передает значения для связываемых переменных в соответствии с данными на экране (в нашем случае - 7934, MILLER и 1300) и повторно запрашивает ту же самую строку из базы данных, но в этот раз блокирует ее изменения другими сеансами. Вот почему такой подход называется пессимистическим блокированием. Мы бло-

кируем строку перед попыткой изменения, поскольку сомневается, что она останется

неизменной.

Оптимистическое блокирование

Второй метод, который называют оптимистическим блокированием, состоит в том,

чтобы сохранять старое и новое значения в приложении и использовать их при измене-

нии следующим образом:

Update table

Set column1 = :new_column1, column2 = :new_column2, ....

Where column1 = :old_column1

And column2 = :old_column2

Заблокированные вставки

Единственный случай блокирования операторами INSERT друг друга, - когда име-

ется таблица с первичным ключом или ограничением уникальности и два сеанса одно-

временно пытаются вставить строку с одним и тем же значением.

Заблокированные изменения и удаления

В интерактивном приложении, которое запрашивает данные из базы, позволяет

пользователю манипулировать ими, а затем возвращает их в базу данных, заблокиро-

ванные операторы UPDATE или DELETE показывают, что в коде может быть проблема

потерянного изменения. Вы пытаетесь изменить с помощью UPDATE строку, которую

уже изменяет другой пользователь, другими словами, которая уже кем-то заблокирова-

на. Этого блокирования можно избежать с помощью запроса SELECT FOR UPDATE

NOWAIT, позволяющего:

∙ проверить, не изменились ли данные с момента их прочтения (для предотвраще-

ния потерянного изменения);

∙ заблокировать строку (предотвращая ее блокирование другим оператором изме-

нения или удаления).

Взаимные блокировки

Взаимные блокировки возникают, когда два сеанса удерживают ресурсы, необходи-

мые другому сеансу.

Эскалация блокирования

Когда происходит эскалация блокирования, система увеличивает размер блокируемых

объектов. Примером может служить блокирование системой всей таблицы вместо 100

отдельных ее строк. В СУБД Oracle никогда не применяется эскалация блокирования, однако выполняется преобразование блокировок (lock conversion) или распространение блокировок (lock

promotion). Эти термины часто путают с эскалацией блокирования.

Типы блокировок

Первые три - общие (используются во всех базах данных Oracle), а две остальные - только в OPS (Oracle Parallel Server - параллельный сервер).

∙ Блокировки ЯМД (DML locks). ЯМД означает язык манипулирования данными

(Data Manipulation Language), т.е. операторы SELECT, INSERT, UPDATE и

DELETE. К блокировкам ЯМД относятся, например, блокировки строки данных

или блокировка на уровне таблицы, затрагивающая все строки таблицы.

∙ Блокировки ЯОД (DDL locks). ЯОД означает язык определения данных (Data

Definition Language), т.е. операторы CREATE, ALTER и так далее. Блокировки

ЯОД защищают определения структур объектов.

∙ Внутренние блокировки (internal locks) и защелки (latches). Это блокировки, исполь-

зуемые сервером Oracle для защиты своих внутренних структур данных. Напри-

мер, разбирая запрос и генерируя оптимизированный план его выполнения, сер-

вер Oracle блокирует с помощью защелки библиотечный кэш, чтобы поместить в

него этот план для использования другими сеансами. Защелка - это простое

низкоуровневое средство обеспечения последовательности обращений, использу-

емое сервером Oracle, и по функциям аналогичное блокировке.

∙ Распределенные блокировки (distributed locks). Эти блокировки используются сер-

вером OPS для согласования ресурсов машин, входящих в кластер. Распределен-

ные блокировки устанавливаются экземплярами баз данных, а не отдельными

транзакциями.

∙ Блокировки параллельного управления кэшем (PCM - Parallel Cache Management

Locks). Такие блокировки защищают блоки данных в кэше при использовании их

несколькими экземплярами.

Блокировки ЯМД

Блокировки ЯМД позволяют гарантировать, что в каждый момент времени только

одному сеансу позволено изменять строку и что не может быть удалена таблица, с ко-

торой работает сеанс.

ТХ - блокировки транзакций

Блокировка ТХ устанавливается, когда транзакция инициирует первое изменение, и

удерживается до тех пор, пока транзакция не выполнит оператор COMMIT или

ROLLBACK.

Поскольку блокировка хранится как атрибут данных, серверу Oracle не

нужен традиционный диспетчер блокировок. Транзакция просто переходит к соответ-

ствующим данным и блокирует их (если они еще не заблокированы).

Каждая измененная или выбранная с помощью SELECT

FOR UPDATE строка будет "указывать" на соответствующую блокировку ТХ.

ТМ - блокировки очередности ЯМД

Такие блокировки позволяют быть уверенным, что структура таблицы не изменится

при изменении ее содержимого. Рассмотрим такой пример. При изменении таблицы на

нее устанавливается блокировка ТМ; это предотвращает применение к ней операторов

DROP или ALTER другим сеансом.

Блокировки ЯОД

Блокировки ЯОД автоматически устанавливаются на объекты в ходе выполнения

операторов ЯОД для защиты их от изменения другими сеансами. Например, при вы-

полнении оператора ЯОД ALTER TABLE Т на таблицу Т будет установлена исключи-

тельная блокировка ЯОД, что предотвращает установку блокировок ЯОД и ТМ на эту

таблицу другими сеансами. Блокировки ЯОД удерживаются на период выполнения опе-

ратора ЯОД и снимаются сразу по его завершении. Это делается путем помещения опе-

раторов ЯОД в неявные пары операторов фиксации (или фиксации и отката).

Имеется три типа блокировок ЯОД:

∙ Исключительные блокировки ЯОД. Они предотвращают установку блокировок

ЯОД или ТМ (ЯМД) другими сеансами. Это означает, что можно запрашивать таб-

лицу в ходе выполнения оператора ЯОД, но нельзя ее изменять.

∙ Разделяемые блокировки ЯОД. Они защищают структуру соответствующего объек-

та от изменения другими сеансами, но разрешают изменять данные.

∙ Нарушаемые блокировки разбора (breakable parse locks). Они позволяют объекту,

например плану запроса, хранящемуся в кэше разделяемого пула, зарегистриро-

вать свою зависимость от другого объекта. При выполнении оператора ЯОД, зат-

рагивающего заблокированный таким образом объект, сервер Oracle получает

список объектов, зарегистрировавших свою зависимость, и помечает их как не-

действительные. Вот почему эти блокировки - "нарушаемые": они не предотвра-

щают выполнение операторов ЯОД.

Большинство операторов ЯОД устанавливает исключительную блокировку ЯОД.

Защелки - это блокировки, удерживаемые в течение очень непродолжительного вре-

мени, достаточного, например, для изменения структуры данных в памяти. Они исполь-

зуются для защиты определенных структур памяти, например буферного кэша или биб-

лиотечного кэша в разделяемом пуле. Защелки выделяются случайным образом по принципу "кому повезет". Сеанс, запросивший установку защелки сразу после освобождения ресурса, установит ее. Нет очереди ожидающих освобождения защелки - есть просто "толпа" пытающихся ее получить.

Внутренние блокировки - более сложное средство обеспечения очередности досту-

па, используемое, например, при изменении строк в таблице базы данных. В отличие

от защелок, они позволяют запрашивающему "встать в очередь" в ожидании освобожде-

ния ресурса. Запрашивающий защелку сразу уведомляется, возможно ли это. В случае

внутренней блокировки запрашивающий блокируется до тех пор, пока не сможет эту

блокировку установить.

Блокирование вручную. Блокировки,определяемые пользователем.

∙ блокирование данных вручную с помощью оператора SQL;

∙ создание собственных блокировок с помощью пакета DBMS_LOCK.

Блокирование вручную:

Основным методом явного блокирования данных вручную является использование оператора SELECT...FOR UPDATE.

Заблокировать вручную с помощью оператора LOCK TABLE. Этот оператор блокирует таблицу, а не строки в ней.

Создание собственных блокировок

В таких случаях как раз и пригодится пакет DBMS_LOCK.

Прежде чем открывать файл, записывать в него и закрывать, можно устанавливать бло-

кировку с именем, соответствующим имени файла, в исключительном режиме, а после

закрытия файла вручную снимать эту блокировку.

Средства управления одновременным доступом - это набор функций, предоставля-

емых сервером баз данных для обеспечения одновременного доступа к данным и их

изменения множеством пользователей.

Уровни изолированности транзакции:

Три явления допускаемые для изолированных транзакций:

∙ Грязное чтение (dirty read). Результат настолько же плох, как и название. Допус-

кается чтение незафиксированных, или "грязных", данных. Это случается при от-

крытии обычного файла операционной системы, данные в который записывают-

ся другим процессом, и чтении содержимого этого файла. При этом нарушается

как целостность данных, так и требования внешнего ключа, а требования уни-

кальности игнорируются.

∙ Неповторяемость при чтении (non-REPEATABLE READ). Это означает, что если

строка читается в момент времени T1, а затем перечитывается в момент времени

T2, то за этот период она может измениться. Строка может исчезнуть, может быть

обновлена и т.д.

∙ Чтение фантомов (phantom read). Это означает, что если выполнить запрос в мо-

мент времени T1, а затем выполнить его повторно в момент времени Т2, в базе

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

повторяемости при чтении это явление отличается тем, что прочитанные данные

не изменились, но критериям запроса стало удовлетворять больше данных, чем

прежде.

Уровень изолированности READ UNCOMMITTED

Уровень изолированности READ UNCOMMITTED разрешает грязное чтение. Сер-

вер Oracle не использует грязного чтения, и не допускает его. Основное назначение

уровня изолированности READ UNCOMMITTED - стандартное определение не бло-

кирующего чтения. Как уже было показано, Oracle пo умолчанию обеспечивает не бло-

кирующее чтение.

Уровень изолированности READ COMMITTED

Уровень изолированности READ COMMITTED требует, чтобы транзакция читала

только данные, зафиксированные до ее начала. Никаких грязных чтений. Неповторя-

мость при чтении допускается (повторное чтение той же строки в транзакции может дать

другой результат), как и чтение фантомов (по запросу могут возвращаться вновь встав-

ленные строки, невидимые ранее для транзакции). READ COMMITTED, вероятно, -

наиболее часто и повсеместно используемый в приложениях уровень изолированности

транзакции.

Уровень изолированности REPEATABLE READ

Целью включения REPEATABLE READ в стандарт SQL92 было обеспечение уровня

изолированности транзакций, дающего согласованные, корректные результаты и пре-

дотвращающего потерю изменений.

Уровень изолированности SERIALIZABLE

Этот уровень изолированности транзакции обычно считают наиболее ограничиваю-

щим, но он обеспечивает самую высокую степень изолированности. Транзакция с уров-

нем изолированности SERIALIZABLE работает в среде, где как бы нет других пользователей, изменяющих данные в базе данных; база данных "замораживается" на момент

начала транзакции. Для транзакции база данных выглядит согласованной, в виде своего

рода моментального снимка.

Транзакции только для чтения

Транзакции только для чтения очень похожи на транзакции с уровнем изолирован-

ности SERIALIZABLE. Единственное отличие в том, что они не разрешают изменять

данные, поэтому не подвержены ошибке ORA-08177. Транзакции только для чтения

предназначены для создания отчетов, когда данные отчета должны быть согласованы по

отношению к определенному моменту времени.