|
Программирование >> Oracle
5. Создать в списке новую запись, фиксирующую факт блокирования строки. 6. Разблокировать список. Теперь, когда строка заблокирована, ее можно изменять. При последующей фиксации изменений необходимо: 7. Снова подключиться к диспетчеру. 8. Заблокировать список блокировок. 9. Найти в списке и снять все установленные блокировки. 10. Разблокировать список. Как видите, чем больше установлено блокировок, тем больше времени потребуется для изменения данных и фиксации этих изменений. Поэтому сервер Oracle поступает примерно так: 1. Находит адрес строки, которую необходимо заблокировать. 2. Переходит на эту строку. 3. Блокирует ее (ожидая снятия блокировки, если она уже заблокирована и при этом не используется опция NOWAIT). Вот и все. Поскольку блокировка хранится как атрибут данных, серверу Oracle не нужен традиционный диспетчер блокировок. Транзакция просто переходит к соответствующим данным и блокирует их (если они еще не заблокированы). Иногда при обращении данные кажутся заблокированными, хотя фактически они уже не заблокированы. При блокировании строки данных в Oracle с блоком данных связывается идентификатор транзакции, причем остается там после снятия блокировки. Этот идентификатор уникален для нашей транзакции и задает номер сегмента отката, слот и номер изменения (sequence number). Оставляя его в блоке, содержащем измененную строку, мы как бы говорим другим сеансам, что эти данные принадлежат нам (не все данные в блоке, только одна строка, которую мы меняем). Когда другой сеанс обращается к блоку, он видит идентификатор блокировки и, зная , что он представляет транзакцию, определяет, активна ли еще транзакция, установившая блокировку. Если транзакция уже закончена, сеанс может получить данные в собственность . Если же транзакция активна, сеанс попросит систему уведомить его о завершении транзакции. Таким образом, имеется механизм организации очереди: сеанс, нуждающийся в блокировке, будет помещен в очередь в ожидании завершения транзакции, после чего получит возможность работать с данными. Вот небольшой пример, демонстрирующий, как это происходит. Чтобы увидеть, как работает сервер, используют три таблицы* динамической производительности V$: V$TRANSACTION, содержащую запись о каждой активной транзакции; V$SESSION, которая показывает действующие сеансы; V$LOCK, содержащую записи обо всех блокировках, с указанием сеансов, ожидающих их снятия. *На самом деле это представления, но мы вслед за автором будем называть их таблицами. Прим. иаучн. ред. Во-первых, начнем транзакцию: tkyte@TKYTE816> update dept set deptno 4 rows updated. deptno + 10; Теперь рассмотрим состояние системы в этот момент: tkyte@TKYTE816> select username, 2 v$lock.sid, 3 trunc(id1/power(2,16)) 4 bitand(id1,power(2,16)-l)+0 5 id2 seq, 6 lmode, 7 request 8 from v$lock, v$session 9 where v$lock.type = TX 10 and v$lock.sid = v$session.sid 11 and v$session. username = USER 12 / rbs, slot, USERNAME SID RBS SLOT SEQ LMODE REQUEST TKYTE 8 2 46 160 6 0 tkyte@TKYTE816> select XIDUSM, 2 from v$transaction XIDSLOT, XIDSQN XIDUSN XIDSLOT XIDSQN Обратите внимание на следующее: Значение столбца LMODE в таблице V$LOCK равно 6, а значение столбца REQUEST - 0. Обратившись к описанию таблицы V$LOCK в руководстве Oracle Server Reference Manual, можно узнать, что LMODE=6 означает исключительную блокировку. Значение 0 в столбце REQUEST означает, что мы не запрашиваем блокировку, а удерживаем ее. В таблице только одна строка. Таблица V$LOCK содержит не сами блокировки, а очередь на них. Можно ожидать найти в таблице V$LOCK четыре строки, поскольку мы заблокировали именно такое количество строк. Надо, однако, помнить, что сервер Oracle не хранит список заблокированных строк. Чтобы узнать, не заблокирована ли строка, надо ее прочитать. Возьмем значения столбцов ID1 и ID2 и выполним с ними определенную ма- нипуляцию. Серверу Oracle необходимо хранить три 16-битов1х числа, но для этого имеется только два столбца. Поэтому первый столбец, ID1, хранит два из этих чисел. Разделив значение столбца на 216 с использованием конструкции trunc(id1/power(2,16)) rbs и замаскировав старшие биты с помощью bitand(id1,power(2,16)-1)+0 slot, получаем два числа, хранящиеся в виде одного значения. Значения RBS, SLOT и SEQ сопоставляются с информацией в таблице V$TRANSACTION. Это - идентификатор нашей транзакции. Теперь откроем другой сеанс от имени того же пользователя, поменяем ряд строк в таблице ЕМР, а затем попытаемся изменить таблицу DEPT: tkyte@TKYTE816> update emp set ename = upper(ename); 14 rows updated. tkyte@TKYTE816> update dept set deptno = deptno-10; Сеанс окажется заблокированным. Выполнив запросы к таблицам V$ снова, можно увидеть следующее: tkyte@TKYTE816> select username, 2 v$lock.sid, 3 trunc(idl/power(2,16)) 4 bitand(id1,power(2,16)-1)+0 5 id2 seq, 6 lmode, 7 request 8 from v$lock, v$session 9 where v$lock.type = TX 10 and v$lock.sid = v$session.aid 11 and vSsession.username = USER 12 / rba. slot,
3 / XIDUSN from v$transaction XIDSLOT XIDSQN 82 46 163 160 Итак, понятно, что начата новая транзакция с идентификатором (3,82,163). Наш сеанс, SID=9, теперь имеет две строки в таблице V$LOCK. Одна строка представляет удерживаемые им блокировки (та, где LMODE=6). Там же есть строка, содержащая значение 6 в столбце REQUEST. Это запрос исключительной блокировки. Интересно отметить, что значения RBS/SLOT/SEQ в этой строке запроса представляют идентификатор транзакции сеанса, удерживающего блокировку. Транзакция сеанса со значением SID=8 блокирует транзакцию сеанса со значением SID=9. Это можно явно увидеть, выполнив соединение таблицы V$LOCK с самой собой:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |