2014-08-08 8 views
0

Я не могу понять, как будет действовать выбор, пока его часть эксклюзивной транзакции. Пожалуйста, обратите внимание следующие сценарии -эксклюзивная блокировка и общая блокировка для оператора select - SQL Server

Сценарий 1 Шаг 1,1

create table Tmp(x int) 
insert into Tmp values(1) 

Шаг 1,2 - Сессия 1

begin tran 
set transaction isolation level serializable 
select * from Tmp 

Шаг 1,3 - сессия 2

select * from Tmp 

Даже первая сессия не была завершена, сессия 2 будет иметь возможность читать TMP таблицу. Я думал, что Tmp будет иметь исключительную блокировку, а совместная блокировка не должна выдаваться для выбора запроса в сеансе 2. И этого не происходит. Я удостоверился, что уровень изоляции по умолчанию - READ COMMITED.

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

EDIT: Почему мне нужно выбрать эксклюзивную блокировку?

У меня есть SP, который фактически генерирует последовательные значения. Таким образом, поток -

  1. чтение максимальных значений из таблицы и сохранять значение переменных
  2. Обновления таблицы заданного значения = значение +-

Этой ИП выполняется параллельно несколько тысяч экземпляров. Если два экземпляра выполняют SP одновременно, они будут читать одно и то же значение и будут обновлять значение + 1. Хотя я хотел бы иметь последовательное значение для каждого исполнения. Я думаю, что это возможно только в том случае, если select также является частью эксклюзивной блокировки.

+0

Это связано с некоторой оптимизацией, которую делает sql, обратитесь к этой ссылке. Http: //sqlblog.com/blogs/louis_davidson/archive/2006/12/13/does-xlock-always-prevent-reads-by -others.aspx. Если вы хотите, чтобы он правильно работал, используйте 2 вкладки. – Aflred

ответ

0

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

Но даже если вы исправите порядок инструкций, он все равно не получит эксклюзивную блокировку для простого заявления SELECT.


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

select * from Tmp with (XLOCK) 

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

update Tmp set x = x 

Ваш первый сеанс не нужен эксклюзивный замок, потому что он не меняет данные.Если ваш первый (сериализуемый) сеанс завершился и был откат или завершен, перед началом второго сеанса результаты этого сеанса будут все те же, потому что ваш первый сеанс не изменил данные - и поэтому «сериализуемый» характер сделки был правильным.

+0

У меня есть SP, который фактически генерирует последовательные значения. Таким образом, поток равен - 1. прочитайте максимальные значения из таблицы и сохраните значение в переменных 2. Значение таблицы обновления = значение + 1 Этот SP выполняется параллельно несколькими тысячами экземпляров. Если два экземпляра выполняют SP одновременно, они будут читать одно и то же значение и будут обновлять значение + 1. Хотя я хотел бы иметь последовательное значение для каждого исполнения. Я думаю, что это возможно только в том случае, если select также является частью эксклюзивной блокировки. –

+0

Это феноменально дорого, с точки зрения использования ресурсов, фактически генерировать последовательные числа без пробелов, особенно перед несколькими соединениями. Вот почему * встроенные генераторы (например, столбцы «IDENTITY» и, начиная с 2012 года, не предоставляют такую ​​гарантию). Вы уверены, что вам нужна такая гарантия и вы не можете просто использовать встроенные функции? –

+0

Я согласен с вами, мы сталкиваемся с проблемами, но сейчас его невозможно изменить дизайн. Но, тем не менее, мне кажется правильным вопрос, почему я не могу использовать эксклюзивную блокировку для выбранного оператора? –

Смежные вопросы