Несколько пользователей могут примерно одновременно вызывать процедуру:
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
А>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[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, Вы писали:
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
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, kvasya, Вы писали:
K>>>>
K>>>>update T set [поле] = 5 where 1 = dbo.Четное(select count(*) from T)
K>>>>
А>>>Что-то сомневаюсь я (не примите за сарказм), в чём преимущество такой перестановки?
K>>То, чего вы добиваетесь — гарантированная атомарность операции.
А>Не убедили, оба пользователя одновременно выполнят этот запрос и данные разъедутся.
На апдейте таблица заблокируется — уже очередность получается. А очередность выстраивается блокирующими транзакциями.
Здравствуйте, Аноним, Вы писали:
А>Подскажите как сделать такую «монолитную транзакцию»?
Посредством пессимистической блокировки. Определить ключевой ресурс (строка или таблица в целом), блокировать его в несовместимом режиме одновременно с чтением.
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
Здравствуйте, Аноним, Вы писали:
AK>>На апдейте таблица заблокируется — уже очередность получается. А очередность выстраивается блокирующими транзакциями.
А>Заблокируется на чтение? Так что чуть припоздавший запрос второго пользователя уже не сможет сделать select count(*)?
А тут вообще-то чтение отдельно невозможно. Как только SQL Server увидит, что пытаются сделать апдейт заблокированной таблицы T, она поставит этот запрос в очередь и никакой SELECT в подзапросе не выполнится, пока таблица не разблокируется, потому что это атомарная команда. Так что вам предложили очень верное решение проблемы.
Re[7]: Как организовать «Очередь» запросов в MS SQL
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, 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[9]: Как организовать «Очередь» запросов в MS SQL
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, 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
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[10]: Как организовать «Очередь» запросов в MS SQL
Здравствуйте, alexey.kostylev, Вы писали:
AK>блокировка на апдейт не зависит от выбранного уровня изоляции, если принудительно не выставлять.
Вполне вероятно, что я не понимаю Вас.
Если update пользователя А не блокирует ЧТЕНИЕ данных пользователем Б, то пользователь Б прочтет их ещё до завершения update А и примет решение ВноситьИзменения. Ясно что сделать Update Б не сможет пока есть блокировка А. Но как только А блокировку снимет, Б выполнит свой update, руководствуясь принятым не вовремя решением, которое, если бы принималось не во время, а после снятия блокировки А, было бы другим.
Здравствуйте, Аноним, Вы писали:
А>Подскажите как сделать такую «монолитную транзакцию»?
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[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, Вы писали:
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[4]: Как организовать «Очередь» запросов в MS SQL