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[11]: Как организовать «Очередь» запросов в MS SQL
От: alexey.kostylev Новая Зеландия http://alexeykostylev.livejournal.com/
Дата: 24.06.10 12:38
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

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


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


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


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


фишка в том что апдейт А как раз блокирует чтение для Б
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[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[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: Как организовать «Очередь» запросов в 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) Козьма Прутков
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...
Пока на собственное сообщение не было ответов, его можно удалить.