Блокировки в MS SQL Server 2000
Информация - Компьютеры, программирование
Другие материалы по предмету Компьютеры, программирование
usСтатус процесса SQL Server. Может принимать значения: GRANT, WAIT, CNVRT.Эта процедура возвращает данные о блокировках из системной таблицы syslockinfo, которая находится в базе данных master.
ПРИМЕЧАНИЕ
Информация именно из этой таблицы используется менеджером блокировок для определения совместимости блокировок при запросе ресурсов транзакциями.Во всех примерах используется таблица test, которая создается следующим скриптом:
create table test(i int, n varchar(20))
insert into test values(1,alex)
insert into test values(2,rosa)
insert into test values(3,dima)Во-первых, давайте действительно убедимся, что при чтении данных с уровнем изоляции ниже REPEATABLE READ разделяемые блокировки снимаются сразу же после извлечения данных:
print @@spid
begin tran select * from testМы начали транзакцию, но оставили ее открытой. Для того чтобы посмотреть, какие блокировки наложены предыдущим скриптом, вызовем процедуру sp_lock (в другой сессии) с параметром, выведенным print @@spid (у меня это 54).
СОВЕТ
Текущее значение идентификатора процесса сервера можно увидеть в строке состояния программы Query Analizer.
sp_lock 54Результат приведен в таблице 3.
spdidbidObjIdIndIdTypeResourceModeStatus54800DBSGRANTМы видим стандартную блокировку, которая создается для каждого соединения с базой данных. Никакой дополнительной блокировки установлено не было.
Другим способом проверки того, что блокировка снимается сразу после извлечения данных, является использование трассировки. Попробуйте выполнить следующую команду:
dbcc traceon(3604,1200)
select * from test
dbcc traceoff(3604,1200)Флаг трассировки 3604 заставляет сервер передавать отладочную информацию в текущее соединение непосредственно клиенту, а 1200 выводить информацию о блокировках. В результате мы получим следующее:
Process 54 acquiring S lock on DB: 8 (class bit0 ref1) result: OK
Process 54 acquiring IS lock on TAB: 8:1993058136 [] (class bit0 ref1) result: OK
Process 54 acquiring IS lock on PAG: 8:1:31 (class bit0 ref1) result: OK
i n
----------- --------------------
1 alex
2 rosa
3 dima
(3 row(s) affected)
Process 54 releasing lock on PAG: 8:1:31
Process 54 releasing lock on TAB: 8:1993058136 []Хорошо. В первой сессии зафиксируйте транзакцию:
--print @@spid
--begin tran select * from test
commitПовторный вызов sp_lock приводит к тем же результатам. Это подтверждает, что предыдущим запросом никаких блокировок не устанавливалось. Теперь попробуем наложить блокировку обновления. Делается это с помощью хинта updlock (хинты подробно будут рассмотрены далее):
begin tran select * from test with (updlock)Теперь вызов sp_lock 54 дает более интересный результат (таблица 4):
spdidbidObjIdIndIdTypeResourceModeStatus54800DBSGRANT54819930581360RID1:29:2 UGRANT54819930581360RID1:29:0UGRANT54819930581360PAG1:29IUGRANT54819930581360TABIXGRANT54819930581360RID1:29:1UGRANTКак видно, на три строки была наложена блокировка обновления, что означает невозможность обновления этих строк другими транзакциями. Кроме этого, были наложены еще две блокировки, которые относятся к типу блокировок намерения (intent locks) блокировка на страницу и на таблицу. Пусть вас не смущает колонка Resource ее содержание я опишу позже. Поле ObjId представляет собой идентификатор объекта, имя которого можно получить с помощью функции object_name. IndId идентификатор индекса, в данном примере всегда равен 0, так как в таблице test индексов не используется.
Блокировки намерений
Блокировки намерений всегда устанавливаются на таблицу или страницу, но никогда на строку. Для чего они нужны? Блокировки намерений относятся к специальным типам блокировок и предназначены для повышения производительности работы менеджера блокировок.
Предположим, некая транзакция пытается изменить какую-либо строку в таблице test. Чтобы определить, что эту транзакцию необходимо заблокировать, менеджеру транзакций (в отсутствие блокировок намерения) пришлось бы сканировать всю таблицу syslockinfo для проверки всех строк таблицы test. Чтобы избежать этой неблагодарной работы, менеджер блокировок сразу устанавливает на страницу и таблицу блокировку намерения обновления (Intent Update) и монопольную блокировку намерения (Intent Exclusive) соответственно, и проверяет уже только их. Таким образом, блокировки намерений это хинт менеджеру блокировок, который дает значительный выигрыш в производительности при проверке совместимости блокировок.
Рассмотрим блокировки намерений более подробно:
Разделяемая блокировка намерений (обозначается IS). Этот тип блокировки предназначен для того, чтобы вместо проверки множества разделяемых блокировок для каждой строки в момент обновления данных, или установки множества разделяемых блокировок для каждой строки в момент чтения данных, можно было установить одну блокировку намерений для страницы или всей таблицы. Этот тип блокировки совместим со всеми остальными режимами, кроме монопольной блокировки. Другими словами, если транзакция пытается обновить данные, на которые наложена разделяемая блокировка намерений, ее выполнение заблокируется до момента завершения первой транзакции.
Монопольная блокировка намерений (обозначается IX). Монопольная блокировка намерений запрещает доступ к данным какого-либо вида (даже на чтение) и позволяет повысить эффективность работы при множественном обновлении данных. В отличие от простой монопольной блокировки она совместима сама с собой. Т.е. другая транзакция также может наложить монопольную блокировку намерений на те же ресурсы, что и первая транзакция.
Разделяемо-монопольная блокировка намерений (обозначается SIX). Подсказывает менеджеру блокировок, что транзакция в основном выполняет чтение данных и лишь частично, в очень небольшом объеме их изменение. Основное отличие данного типа блокировки от монопольной блокировки намерений