Re[9]: Как организовать «Очередь» запросов в MS SQL
От: alexey.kostylev Новая Зеландия http://alexeykostylev.livejournal.com/
Дата: 24.06.10 11:53
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, alexey.kostylev, Вы писали:


AK>>Здравствуйте, Аноним, Вы писали:


А>>>Здравствуйте, alexey.kostylev, Вы писали:


AK>>>>Здравствуйте, Аноним, Вы писали:


А>>>>>Здравствуйте, kvasya, Вы писали:


K>>>>>>>>
K>>>>>>>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>>>>>>>>


А>>>>>>>Что-то сомневаюсь я (не примите за сарказм), в чём преимущество такой перестановки?


K>>>>>>То, чего вы добиваетесь — гарантированная атомарность операции.


А>>>>>Не убедили, оба пользователя одновременно выполнят этот запрос и данные разъедутся.


AK>>>>На апдейте таблица заблокируется — уже очередность получается. А очередность выстраивается блокирующими транзакциями.


А>>>Заблокируется на чтение? Так что чуть припоздавший запрос второго пользователя уже не сможет сделать select count(*)?


AK>>я вот не знаю точно, объединятся ли вложенный селект с апдейтом в одну блокировку, по идее должны. Если да, то проблемы нет, поскольку апдейт наложит эклюзивную блокировку и все остальные будут курить.

AK>>А если нет, то принудительно начать транзакцию перед апдейт.

А>Я думаю от уровня изоляции зависит (как минимум в худшую сторону), если поставить Read Uncommited или Read Commited, то получим разрушение данных, оба запроса вне зависимости от каких бы то ни было «атомарностей» будут выполнятся на своих «копиях» данных, что является решающим моментом и приводит к нежелательным действиям.


А>Вопрос что нужно поставить (и где) чтобы гарантировать.


блокировка на апдейт не зависит от выбранного уровня изоляции, если принудительно не выставлять.
Re[4]: Как организовать «Очередь» запросов в MS SQL
От: ksg71 Германия  
Дата: 24.06.10 12:27
Оценка: 1 (1)
Здравствуйте, ksg71, Вы писали:


итого

BEGIN TRAN

SELECT @r = count(*) FROM T WITH (TABLOCKX)

if 1 = dbo.Четное(@r) 
begin
 INSERT INTO T ([поле]) VALUES (5)
end

COMMIT TRAN
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re[11]: Как организовать «Очередь» запросов в MS SQL
От: alexey.kostylev Новая Зеландия http://alexeykostylev.livejournal.com/
Дата: 24.06.10 12:38
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, alexey.kostylev, Вы писали:


AK>>блокировка на апдейт не зависит от выбранного уровня изоляции, если принудительно не выставлять.


А>Вполне вероятно, что я не понимаю Вас.


А>Если update пользователя А не блокирует ЧТЕНИЕ данных пользователем Б, то пользователь Б прочтет их ещё до завершения update А и примет решение ВноситьИзменения. Ясно что сделать Update Б не сможет пока есть блокировка А. Но как только А блокировку снимет, Б выполнит свой update, руководствуясь принятым не вовремя решением, которое, если бы принималось не во время, а после снятия блокировки А, было бы другим.


фишка в том что апдейт А как раз блокирует чтение для Б
Re: Как организовать «Очередь» запросов в MS SQL
От: kvasya  
Дата: 24.06.10 10:43
Оценка: +1
Здравствуйте, Аноним, Вы писали:


А>Наглядный пример


А>
А>SELECT @r = count(*) FROM T

А>if 1 = dbo.Четное(@r) 
А>begin
А> UPDATE T SET [поле] = 5;
А>end
А>


Однозначного ответа не имею, но два слова: Посмотреть уровни изоляций транзакции и обратить внимание на возможность исключить такой стиль программирования в SQL (тем более в многопользовательском). Имею в виду, что приведенный код должно выглядеть как:


update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
Re[10]: Как организовать «Очередь» запросов в MS SQL
От: Аноним  
Дата: 24.06.10 12:03
Оценка: -1
Здравствуйте, alexey.kostylev, Вы писали:

AK>блокировка на апдейт не зависит от выбранного уровня изоляции, если принудительно не выставлять.


Вполне вероятно, что я не понимаю Вас.

Если update пользователя А не блокирует ЧТЕНИЕ данных пользователем Б, то пользователь Б прочтет их ещё до завершения update А и примет решение ВноситьИзменения. Ясно что сделать Update Б не сможет пока есть блокировка А. Но как только А блокировку снимет, Б выполнит свой update, руководствуясь принятым не вовремя решением, которое, если бы принималось не во время, а после снятия блокировки А, было бы другим.
Re: Как организовать «Очередь» запросов в MS SQL
От: ksg71 Германия  
Дата: 24.06.10 12:09
Оценка: :)
Здравствуйте, Аноним, Вы писали:

А>Подскажите как сделать такую «монолитную транзакцию»?



SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN

SELECT @r = count(*) FROM T

if 1 = dbo.Четное(@r) 
begin
 INSERT INTO T ([поле]) VALUES (5)
end

COMMIT TRAN
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re[10]: Как организовать «Очередь» запросов в MS SQL
От: alexey.kostylev Новая Зеландия http://alexeykostylev.livejournal.com/
Дата: 24.06.10 13:26
Оценка: :)
Здравствуйте, ksg71, Вы писали:

K>Здравствуйте, alexey.kostylev, Вы писали:


AK>>Здравствуйте, ksg71, Вы писали:


K>>>Здравствуйте, alexey.kostylev, Вы писали:


AK>>>>на мой взгляд TABLOCK тут лишний. все должно лочиться BEGIN TRAN, не говоря уж о том что можно залочить используя вложенный селект на инсерте


K>>>не TABLOCK а TABLOCKX, и далеко не лишний, важно не разрешить никому читать до записи результата


AK>>ну так эклюзивная транзакция на входе отсечет всех. Тем более что update and insert будут выполнятся как атомарная операция, тогда уж вешать блокировку на update. Если предполагать что будет лочится только селект, это не спасет ситуацию, поскольку после окончания первого селекта один процесс уйдет на апдейт, а другой встанет на селект и не селект этот пойдет скорее всего перед апдейтом.


K>select по умолчанию использует shared блокировку


ну так он идет в контексте апдейта. я думаю что весь запрос будет идти по одной максимальной блокировке от апдейта. Это для случая когда select будет вложенным запросом в апдейт
Re: Как организовать «Очередь» запросов в MS SQL
От: ZAMUNDA Земля для жалоб и предложений
Дата: 24.06.10 21:39
Оценка: +1
Здравствуйте, Аноним, Вы писали:

BEGIN TRAN
SELECT @r = count(*) FROM T  WITH ( UPDLOCK )
-- И будет UPDATE в другом процессе ждать пока снимется блокировка.

if 1 = dbo.Четное(@r) -- А почему не (0 = @r % 2) ?
begin
 UPDATE T SET [поле] = 5;
end

COMMIT TRAN

А если update с условием, то нужно сначала сделать SELECT с тем же условием.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Как организовать «Очередь» запросов в MS SQL
От: Аноним  
Дата: 24.06.10 10:29
Оценка:
Имею таблицу T

Несколько пользователей могут примерно одновременно вызывать процедуру:

1: select from T

2: if then update T


То есть решение об изменении данных в T строится на содержимом T.

Теперь предположим пользователь А вызвал эту процедуру и выполнился первый её шаг, когда процедуру вызвал пользователь Б, соответственно у обоих на втором шаге произойдет Update T. Если бы Б вызвал процедуру чуть позже (после шага 2 у пользователя А), то if then не сработал бы и результат был бы другой («Правильный» -- тот что надо).


Наглядный пример

SELECT @r = count(*) FROM T

if 1 = dbo.Четное(@r) 
begin
 UPDATE T SET [поле] = 5;
end



Подскажите как сделать такую «монолитную транзакцию»?
Re: Как организовать «Очередь» запросов в MS SQL
От: Аноним  
Дата: 24.06.10 10:34
Оценка:
С наглядным примером подкачал:

SELECT @r = count(*) FROM T

if 1 = dbo.Четное(@r) 
begin
 INSERT INTO T ([поле]) VALUES (5)
end
Re[2]: Как организовать «Очередь» запросов в MS SQL
От: Аноним  
Дата: 24.06.10 10:47
Оценка:
Здравствуйте, kvasya, Вы писали:

K>.. обратить внимание на возможность исключить такой стиль программирования в SQL (тем более в многопользовательском). Имею в виду, что приведенный код должно выглядеть как:


K>
K>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>


Что-то сомневаюсь я (не примите за сарказм), в чём преимущество такой перестановки?
Re[3]: Как организовать «Очередь» запросов в MS SQL
От: kvasya  
Дата: 24.06.10 11:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, kvasya, Вы писали:


K>>.. обратить внимание на возможность исключить такой стиль программирования в SQL (тем более в многопользовательском). Имею в виду, что приведенный код должно выглядеть как:


K>>
K>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>>


А>Что-то сомневаюсь я (не примите за сарказм), в чём преимущество такой перестановки?


То, чего вы добиваетесь — гарантированная атомарность операции.
Re[4]: Как организовать «Очередь» запросов в MS SQL
От: Аноним  
Дата: 24.06.10 11:08
Оценка:
Здравствуйте, kvasya, Вы писали:

K>>>
K>>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>>>


А>>Что-то сомневаюсь я (не примите за сарказм), в чём преимущество такой перестановки?


K>То, чего вы добиваетесь — гарантированная атомарность операции.


Не убедили, оба пользователя одновременно выполнят этот запрос и данные разъедутся.
Re[5]: Как организовать «Очередь» запросов в MS SQL
От: alexey.kostylev Новая Зеландия http://alexeykostylev.livejournal.com/
Дата: 24.06.10 11:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, kvasya, Вы писали:


K>>>>
K>>>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>>>>


А>>>Что-то сомневаюсь я (не примите за сарказм), в чём преимущество такой перестановки?


K>>То, чего вы добиваетесь — гарантированная атомарность операции.


А>Не убедили, оба пользователя одновременно выполнят этот запрос и данные разъедутся.


На апдейте таблица заблокируется — уже очередность получается. А очередность выстраивается блокирующими транзакциями.
Re: Как организовать «Очередь» запросов в MS SQL
От: wildwind Россия  
Дата: 24.06.10 11:20
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Подскажите как сделать такую «монолитную транзакцию»?


Посредством пессимистической блокировки. Определить ключевой ресурс (строка или таблица в целом), блокировать его в несовместимом режиме одновременно с чтением.
Re[6]: Как организовать «Очередь» запросов в MS SQL
От: Аноним  
Дата: 24.06.10 11:21
Оценка:
Здравствуйте, alexey.kostylev, Вы писали:

AK>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, kvasya, Вы писали:


K>>>>>
K>>>>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>>>>>


А>>>>Что-то сомневаюсь я (не примите за сарказм), в чём преимущество такой перестановки?


K>>>То, чего вы добиваетесь — гарантированная атомарность операции.


А>>Не убедили, оба пользователя одновременно выполнят этот запрос и данные разъедутся.


AK>На апдейте таблица заблокируется — уже очередность получается. А очередность выстраивается блокирующими транзакциями.


Заблокируется на чтение? Так что чуть припоздавший запрос второго пользователя уже не сможет сделать select count(*)?
Re[7]: Как организовать «Очередь» запросов в MS SQL
От: sunsquirel США  
Дата: 24.06.10 11:33
Оценка:
Здравствуйте, Аноним, Вы писали:

AK>>На апдейте таблица заблокируется — уже очередность получается. А очередность выстраивается блокирующими транзакциями.


А>Заблокируется на чтение? Так что чуть припоздавший запрос второго пользователя уже не сможет сделать select count(*)?


А тут вообще-то чтение отдельно невозможно. Как только SQL Server увидит, что пытаются сделать апдейт заблокированной таблицы T, она поставит этот запрос в очередь и никакой SELECT в подзапросе не выполнится, пока таблица не разблокируется, потому что это атомарная команда. Так что вам предложили очень верное решение проблемы.
Re[7]: Как организовать «Очередь» запросов в MS SQL
От: alexey.kostylev Новая Зеландия http://alexeykostylev.livejournal.com/
Дата: 24.06.10 11:42
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, alexey.kostylev, Вы писали:


AK>>Здравствуйте, Аноним, Вы писали:


А>>>Здравствуйте, kvasya, Вы писали:


K>>>>>>
K>>>>>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>>>>>>


А>>>>>Что-то сомневаюсь я (не примите за сарказм), в чём преимущество такой перестановки?


K>>>>То, чего вы добиваетесь — гарантированная атомарность операции.


А>>>Не убедили, оба пользователя одновременно выполнят этот запрос и данные разъедутся.


AK>>На апдейте таблица заблокируется — уже очередность получается. А очередность выстраивается блокирующими транзакциями.


А>Заблокируется на чтение? Так что чуть припоздавший запрос второго пользователя уже не сможет сделать select count(*)?


я вот не знаю точно, объединятся ли вложенный селект с апдейтом в одну блокировку, по идее должны. Если да, то проблемы нет, поскольку апдейт наложит эклюзивную блокировку и все остальные будут курить.
А если нет, то принудительно начать транзакцию перед апдейт.
Re[8]: Как организовать «Очередь» запросов в MS SQL
От: Аноним  
Дата: 24.06.10 11:50
Оценка:
Здравствуйте, alexey.kostylev, Вы писали:

AK>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, alexey.kostylev, Вы писали:


AK>>>Здравствуйте, Аноним, Вы писали:


А>>>>Здравствуйте, kvasya, Вы писали:


K>>>>>>>
K>>>>>>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>>>>>>>


А>>>>>>Что-то сомневаюсь я (не примите за сарказм), в чём преимущество такой перестановки?


K>>>>>То, чего вы добиваетесь — гарантированная атомарность операции.


А>>>>Не убедили, оба пользователя одновременно выполнят этот запрос и данные разъедутся.


AK>>>На апдейте таблица заблокируется — уже очередность получается. А очередность выстраивается блокирующими транзакциями.


А>>Заблокируется на чтение? Так что чуть припоздавший запрос второго пользователя уже не сможет сделать select count(*)?


AK>я вот не знаю точно, объединятся ли вложенный селект с апдейтом в одну блокировку, по идее должны. Если да, то проблемы нет, поскольку апдейт наложит эклюзивную блокировку и все остальные будут курить.

AK>А если нет, то принудительно начать транзакцию перед апдейт.

Я думаю от уровня изоляции зависит (как минимум в худшую сторону), если поставить Read Uncommited или Read Commited, то получим разрушение данных, оба запроса вне зависимости от каких бы то ни было «атомарностей» будут выполнятся на своих «копиях» данных, что является решающим моментом и приводит к нежелательным действиям.

Вопрос что нужно поставить (и где) чтобы гарантировать.
Re[10]: Как организовать «Очередь» запросов в MS SQL
От: alexey.kostylev Новая Зеландия http://alexeykostylev.livejournal.com/
Дата: 24.06.10 12:00
Оценка:
http://msdn.microsoft.com/en-us/library/ms175519.aspx
[msdn]
Exclusive Locks

Exclusive (X) locks prevent access to a resource by concurrent transactions. With an exclusive (X) lock, no other transactions can modify data; read operations can take place only with the use of the NOLOCK hint or read uncommitted isolation level.

Data modification statements, such as INSERT, UPDATE, and DELETE combine both modification and read operations. The statement first performs read operations to acquire data before performing the required modification operations. Data modification statements, therefore, typically request both shared locks and exclusive locks. For example, an UPDATE statement might modify rows in one table based on a join with another table. In this case, the UPDATE statement requests shared locks on the rows read in the join table in addition to requesting exclusive locks on the updated rows.
[/msdn]

т.е. для таблицы это будет эклюзивная блокировка.

можно еще выставить блокировку уровня таблицы, чтобы блокировались не отдельные строки.
Re[2]: Как организовать «Очередь» запросов в MS SQL
От: Аноним  
Дата: 24.06.10 12:17
Оценка:
Здравствуйте, ksg71, Вы писали:

K>Здравствуйте, Аноним, Вы писали:


А>>Подскажите как сделать такую «монолитную транзакцию»?



K>
K>SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

K>BEGIN TRAN

K>SELECT @r = count(*) FROM T

K>if 1 = dbo.Четное(@r) 
K>begin
K> INSERT INTO T ([поле]) VALUES (5)
K>end

K>COMMIT TRAN
K>


Этот уровень не запрещает аналогичной транзакции Б читать данные одновременно с транзакцией А, насколько я понял из msdn. А это ключевой момент: они обе прочтут скажем одно и то же и обе решат Бомбить. И обе забомбят.
Re[3]: Как организовать «Очередь» запросов в MS SQL
От: ksg71 Германия  
Дата: 24.06.10 12:23
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, ksg71, Вы писали:


K>>Здравствуйте, Аноним, Вы писали:


А>>>Подскажите как сделать такую «монолитную транзакцию»?



K>>
K>>SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

K>>BEGIN TRAN

K>>SELECT @r = count(*) FROM T

K>>if 1 = dbo.Четное(@r) 
K>>begin
K>> INSERT INTO T ([поле]) VALUES (5)
K>>end

K>>COMMIT TRAN
K>>


А>Этот уровень не запрещает аналогичной транзакции Б читать данные одновременно с транзакцией А, насколько я понял из msdn. А это ключевой момент: они обе прочтут скажем одно и то же и обе решат Бомбить. И обе забомбят.



поправлюсь
SELECT @r = count(*) FROM T WITH (TABLOCKX)
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re[5]: Как организовать «Очередь» запросов в MS SQL
От: Аноним  
Дата: 24.06.10 12:32
Оценка:
Здравствуйте, ksg71, Вы писали:

K>Здравствуйте, ksg71, Вы писали:



K>итого


K>
K>BEGIN TRAN

K>SELECT @r = count(*) FROM T WITH (TABLOCKX)

K>if 1 = dbo.Четное(@r) 
K>begin
K> INSERT INTO T ([поле]) VALUES (5)
K>end

K>COMMIT TRAN
K>



Похоже на истину, спасибо, буду пробовать
Re[7]: Как организовать «Очередь» запросов в MS SQL
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.06.10 12:34
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, alexey.kostylev, Вы писали:


AK>>Здравствуйте, Аноним, Вы писали:


А>>>Здравствуйте, kvasya, Вы писали:


K>>>>>>
K>>>>>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>>>>>>


А>>>>>Что-то сомневаюсь я (не примите за сарказм), в чём преимущество такой перестановки?


K>>>>То, чего вы добиваетесь — гарантированная атомарность операции.


А>>>Не убедили, оба пользователя одновременно выполнят этот запрос и данные разъедутся.


AK>>На апдейте таблица заблокируется — уже очередность получается. А очередность выстраивается блокирующими транзакциями.


А>Заблокируется на чтение? Так что чуть припоздавший запрос второго пользователя уже не сможет сделать select count(*)?


Да, именно так.
Данные могут разъехаться только в случае уровня изоляции SNAPSHOT.
Re[6]: Как организовать «Очередь» запросов в MS SQL
От: alexey.kostylev Новая Зеландия http://alexeykostylev.livejournal.com/
Дата: 24.06.10 12:53
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, ksg71, Вы писали:


K>>Здравствуйте, ksg71, Вы писали:



K>>итого


K>>
K>>BEGIN TRAN

K>>SELECT @r = count(*) FROM T WITH (TABLOCKX)

K>>if 1 = dbo.Четное(@r) 
K>>begin
K>> INSERT INTO T ([поле]) VALUES (5)
K>>end

K>>COMMIT TRAN
K>>



А>Похоже на истину, спасибо, буду пробовать


на мой взгляд TABLOCK тут лишний. все должно лочиться BEGIN TRAN, не говоря уж о том что можно залочить используя вложенный селект на инсерте
Re[7]: Как организовать «Очередь» запросов в MS SQL
От: ksg71 Германия  
Дата: 24.06.10 13:17
Оценка:
Здравствуйте, alexey.kostylev, Вы писали:

AK>на мой взгляд TABLOCK тут лишний. все должно лочиться BEGIN TRAN, не говоря уж о том что можно залочить используя вложенный селект на инсерте


не TABLOCK а TABLOCKX, и далеко не лишний, важно не разрешить никому читать до записи результата
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re[8]: Как организовать «Очередь» запросов в MS SQL
От: alexey.kostylev Новая Зеландия http://alexeykostylev.livejournal.com/
Дата: 24.06.10 13:21
Оценка:
Здравствуйте, ksg71, Вы писали:

K>Здравствуйте, alexey.kostylev, Вы писали:


AK>>на мой взгляд TABLOCK тут лишний. все должно лочиться BEGIN TRAN, не говоря уж о том что можно залочить используя вложенный селект на инсерте


K>не TABLOCK а TABLOCKX, и далеко не лишний, важно не разрешить никому читать до записи результата


ну так эклюзивная транзакция на входе отсечет всех. Тем более что update and insert будут выполнятся как атомарная операция, тогда уж вешать блокировку на update. Если предполагать что будет лочится только селект, это не спасет ситуацию, поскольку после окончания первого селекта один процесс уйдет на апдейт, а другой встанет на селект и не селект этот пойдет скорее всего перед апдейтом.
Re[9]: Как организовать «Очередь» запросов в MS SQL
От: ksg71 Германия  
Дата: 24.06.10 13:23
Оценка:
Здравствуйте, alexey.kostylev, Вы писали:

AK>Здравствуйте, ksg71, Вы писали:


K>>Здравствуйте, alexey.kostylev, Вы писали:


AK>>>на мой взгляд TABLOCK тут лишний. все должно лочиться BEGIN TRAN, не говоря уж о том что можно залочить используя вложенный селект на инсерте


K>>не TABLOCK а TABLOCKX, и далеко не лишний, важно не разрешить никому читать до записи результата


AK>ну так эклюзивная транзакция на входе отсечет всех. Тем более что update and insert будут выполнятся как атомарная операция, тогда уж вешать блокировку на update. Если предполагать что будет лочится только селект, это не спасет ситуацию, поскольку после окончания первого селекта один процесс уйдет на апдейт, а другой встанет на селект и не селект этот пойдет скорее всего перед апдейтом.


select по умолчанию использует shared блокировку
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re[8]: Как организовать «Очередь» запросов в MS SQL
От: Аноним  
Дата: 24.06.10 13:28
Оценка:
Здравствуйте, sunsquirel, Вы писали:

S>Здравствуйте, Аноним, Вы писали:


AK>>>На апдейте таблица заблокируется — уже очередность получается. А очередность выстраивается блокирующими транзакциями.


А>>Заблокируется на чтение? Так что чуть припоздавший запрос второго пользователя уже не сможет сделать select count(*)?


S>А тут вообще-то чтение отдельно невозможно. Как только SQL Server увидит, что пытаются сделать апдейт заблокированной таблицы T, она поставит этот запрос в очередь и никакой SELECT в подзапросе не выполнится, пока таблица не разблокируется, потому что это атомарная команда. Так что вам предложили очень верное решение проблемы.


Дайте, пожалуйста, если это возможно, ссылку где почитать про атомарные команды.
Re[11]: Как организовать «Очередь» запросов в MS SQL
От: ksg71 Германия  
Дата: 24.06.10 13:34
Оценка:
Здравствуйте, alexey.kostylev, Вы писали:

AK>ну так он идет в контексте апдейта. я думаю что весь запрос будет идти по одной максимальной блокировке от апдейта. Это для случая когда select будет вложенным запросом в апдейт


в таком разе вполне достаточно залочить только обновляемые данные а прочитать по дефолту с shared локом, а нужно не дать вставлять/удалять строки, что влияет на count(*), кстати мой самый первый ответ топикстартеру
точно решает эту задачу, а второй еще и читать не дает
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re[12]: Как организовать «Очередь» запросов в MS SQL
От: alexey.kostylev Новая Зеландия http://alexeykostylev.livejournal.com/
Дата: 24.06.10 13:38
Оценка:
Здравствуйте, ksg71, Вы писали:

K>Здравствуйте, alexey.kostylev, Вы писали:


AK>>ну так он идет в контексте апдейта. я думаю что весь запрос будет идти по одной максимальной блокировке от апдейта. Это для случая когда select будет вложенным запросом в апдейт


K>в таком разе вполне достаточно залочить только обновляемые данные а прочитать по дефолту с shared локом, а нужно не дать вставлять/удалять строки, что влияет на count(*), кстати мой самый первый ответ топикстартеру

K>точно решает эту задачу, а второй еще и читать не дает

ну так такой конструкции вы не доверяете?

update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
Re[13]: Как организовать «Очередь» запросов в MS SQL
От: ksg71 Германия  
Дата: 24.06.10 13:53
Оценка:
Здравствуйте, alexey.kostylev, Вы писали:

AK>ну так такой конструкции вы не доверяете?


AK>
AK>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
AK>


эта конструкция к теме не относится, ибо на count(*) не влияет, но вставка не исключена во время выполнения
такого запроса, поэтому ответ — не доверяю, а вам советую учить матчасть
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re[14]: Как организовать «Очередь» запросов в MS SQL
От: alexey.kostylev Новая Зеландия http://alexeykostylev.livejournal.com/
Дата: 24.06.10 13:59
Оценка:
Здравствуйте, ksg71, Вы писали:

K>Здравствуйте, alexey.kostylev, Вы писали:


AK>>ну так такой конструкции вы не доверяете?


AK>>
AK>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
AK>>


K>эта конструкция к теме не относится, ибо на count(*) не влияет, но вставка не исключена во время выполнения

K>такого запроса, поэтому ответ — не доверяю, а вам советую учить матчасть

ок, курить матчасть когда не помешает. пока мне таки непонятно почему блокировка на апдейт не заблокирует чтение для 2-го процесса, ведь сначала таблица должная заблокироваться на апдейт, а потом уже селект будет делаться. Будет время почитаю доки и покручу эту штуку.
Re[15]: Как организовать «Очередь» запросов в MS SQL
От: ksg71 Германия  
Дата: 24.06.10 14:06
Оценка:
Здравствуйте, alexey.kostylev, Вы писали:


AK>ок, курить матчасть когда не помешает. пока мне таки непонятно почему блокировка на апдейт не заблокирует чтение для 2-го процесса, ведь сначала таблица должная заблокироваться на апдейт, а потом уже селект будет делаться. Будет время почитаю доки и покручу эту штуку.


так второй процесс может читать, нельзя давать вставлять в частности, а ваш запрос этого не гарантирует
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re: Как организовать «Очередь» запросов в MS SQL
От: rm822 Россия  
Дата: 24.06.10 20:54
Оценка:
А>Подскажите как сделать такую «монолитную транзакцию»?
Вообще для вашего конкретного примера лучше подошел бы триггер на T
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Как организовать «Очередь» запросов в MS SQL
От: Аноним  
Дата: 25.06.10 06:38
Оценка:
Здравствуйте, rm822, Вы писали:

А>>Подскажите как сделать такую «монолитную транзакцию»?

R>Вообще для вашего конкретного примера лучше подошел бы триггер на T


Не думал об этом. Не могли бы Вы продемонстрировать в общих чертах, сам не соображу что-то (утро/лето)?
Re[8]: Как организовать «Очередь» запросов в MS SQL
От: _d_m_  
Дата: 30.06.10 08:09
Оценка:
Здравствуйте, sunsquirel, Вы писали:

S>Здравствуйте, Аноним, Вы писали:


AK>>>На апдейте таблица заблокируется — уже очередность получается. А очередность выстраивается блокирующими транзакциями.


А>>Заблокируется на чтение? Так что чуть припоздавший запрос второго пользователя уже не сможет сделать select count(*)?


S>А тут вообще-то чтение отдельно невозможно.


Возможно. При версионных уровнях изоляции (read_committed_snapshot или snapshot)

S>Как только SQL Server увидит, что пытаются сделать апдейт заблокированной таблицы T, она поставит этот запрос в очередь и никакой SELECT в подзапросе не выполнится, пока таблица не разблокируется, потому что это атомарная команда.


select в апдейте выполнияется под updlock, поэтому не совсем обычное чтение.

S>Так что вам предложили очень верное решение проблемы.


Да.
Re[11]: Как организовать «Очередь» запросов в MS SQL
От: _d_m_  
Дата: 30.06.10 08:13
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, alexey.kostylev, Вы писали:


AK>>блокировка на апдейт не зависит от выбранного уровня изоляции, если принудительно не выставлять.


А>Вполне вероятно, что я не понимаю Вас.


А>Если update пользователя А не блокирует ЧТЕНИЕ данных пользователем Б, то пользователь Б прочтет их ещё до завершения update А и примет решение ВноситьИзменения. Ясно что сделать Update Б не сможет пока есть блокировка А. Но как только А блокировку снимет, Б выполнит свой update, руководствуясь принятым не вовремя решением, которое, если бы принималось не во время, а после снятия блокировки А, было бы другим.


Еще раз: чтение в update выполняется под updlock. И все корректно выполнится начиная с уровня изоляции read committed и выше. Два updlock-а не совместимы. Поэтому Б будет ждать пока полностью не выполнится update от А.
Re[8]: Как организовать «Очередь» запросов в MS SQL
От: _d_m_  
Дата: 30.06.10 08:15
Оценка:
Здравствуйте, gandjustas, Вы писали:

K>>>>>>>
K>>>>>>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>>>>>>>


А>>Заблокируется на чтение? Так что чуть припоздавший запрос второго пользователя уже не сможет сделать select count(*)?


G>Да, именно так.

G>Данные могут разъехаться только в случае уровня изоляции SNAPSHOT.

Разве? о_О
Re[9]: Как организовать «Очередь» запросов в MS SQL
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 30.06.10 08:25
Оценка:
Здравствуйте, _d_m_, Вы писали:

___>Здравствуйте, gandjustas, Вы писали:


K>>>>>>>>
K>>>>>>>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>>>>>>>>


А>>>Заблокируется на чтение? Так что чуть припоздавший запрос второго пользователя уже не сможет сделать select count(*)?


G>>Да, именно так.

G>>Данные могут разъехаться только в случае уровня изоляции SNAPSHOT.

___>Разве? о_О


Да. Версионность данных не обеспечивает сериализуемость транзакций.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.