Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 использование read uncommitted  [new]
Fire83
Member

Откуда: Гомель-Минск
Сообщений: 474
Всем привет, коллеги!

Возник следующий вопрос - используем MS SQL 2008R2. Есть таблица-куча в которую выполняются интенсивно инсерты (без TABLELOCK), из этой таблицы также необходимо читать данные (SELECT). Никаких апдейтов или удалений из этой таблицы нету в момент выполнения чтений. Вопрос: будет ли использование хинта read uncommitted в случае выполнения ТОЛЬКО insert безопасным? Возможно ли появление каких либо аномалий при чтении и каковы их причины? Как вариант рассматриваем read committed snapshot isolation (RCSI) но как известно там использование temp DB + включается на уровне всей базы, а не таблицы.. Как кто думает есть ли возможность обойтись "малой кровью" и просто использовать грязное чтение в этом конкреном случае?
15 мар 13, 16:36    [14053883]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
Тынц
15 мар 13, 16:41    [14053916]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Кот Матроскин
Member

Откуда: Москва
Сообщений: 8933
Fire83,

что Вы понимаете под "безопасным"?
У Вас, естественно, будет ненулевая вероятность прочитать из таблицы запись, которой никогда там не было. Насколько это для Вас критично - нам отсюда сложно судить.
15 мар 13, 17:03    [14054084]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Fire83
Member

Откуда: Гомель-Минск
Сообщений: 474
Кот Матроскин,

Разумеется что запись которой никогда небыло прочитать будет можно (в случае отката транзакции),
я это осознаю и даже если это случится то ничего критичного с точки зрения бизнес не произойдет.
В вот возможно ли, например, прочитать строку дважды? Вооще не прочитать её хотя был коммит?
15 мар 13, 17:11    [14054160]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Crimean
Member

Откуда:
Сообщений: 13147
вопроса не понял, но RCSI включайте - не зная интимных подробностей вашей системы однозначно рекомендовать грязное чтение "не тамифлю". хотя при некоторых условий NOLOCK / UNCOMMITTED даже "показаны"
15 мар 13, 17:12    [14054164]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3422
Fire83
В вот возможно ли, например, прочитать строку дважды? Вооще не прочитать её хотя был коммит?
И то, и другое можно легко словить, если подсунуть в соседней транзакции грамотно спроектированный апдейт. Одним только инсертом такое не делается, вроде.

А зачем вам NOLOCK?
15 мар 13, 17:16    [14054194]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Crimean
Member

Откуда:
Сообщений: 13147
> возможно ли, например, прочитать строку дважды?

на практике я такое ловил и воспроизводил, правда, на update. но в read committed

> Вооще не прочитать её хотя был коммит?

а почему нет? и чем так RCSI пугает-то? большим оверхедом на tempdb? так зато вопросов сколько снимается
15 мар 13, 17:18    [14054212]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Fire83
Member

Откуда: Гомель-Минск
Сообщений: 474
Ennor Tiegael,

Если бы был возможен апдейт я был и не спрашивал...
автор
будет ли использование хинта read uncommitted в случае выполнения ТОЛЬКО insert безопасным
15 мар 13, 17:18    [14054214]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Fire83
Member

Откуда: Гомель-Минск
Сообщений: 474
Crimean,

Дело в том что речь о конкретной таблице в которую идут инсерты и параллельно нужно с неё читать данные.
RCSI включается на уровне всей базы, база огоромная там много еще чего, включение этой опции потребует пересмотра всего кода, с большим количеством усилий на тестирование всего этого добра.
15 мар 13, 17:23    [14054252]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Crimean
Member

Откуда:
Сообщений: 13147
Fire83
RCSI включается на уровне всей базы, база огоромная там много еще чего, включение этой опции потребует пересмотра всего кода, с большим количеством усилий на тестирование всего этого добра.


да где вы все это вычитываете, покажите! ни разу еще ни одного факапа с этой опцией не было кроме небольшого оверхеда по темпу. а вот проблем очень много уходило почти всегда
15 мар 13, 17:52    [14054476]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3422
Crimean
Fire83
RCSI включается на уровне всей базы, база огоромная там много еще чего, включение этой опции потребует пересмотра всего кода, с большим количеством усилий на тестирование всего этого добра.


да где вы все это вычитываете, покажите! ни разу еще ни одного факапа с этой опцией не было кроме небольшого оверхеда по темпу. а вот проблем очень много уходило почти всегда
Да, мне вот тоже интересно, откуда таких присылают :)

Единственный случай, который я поймал за 4 с лишним года - нужно было организовать строго последовательный доступ к финансовому аккаунту клиента. Чтобы нельзя было одновременно из двух коннектов сделать два заказа на общую сумму, превышающую баланс. Блокировочник просто вставал на ожидание, а вот RCSI такое пропускает, в результате чего после второго коммита имеем отрицательный баланс. Решилось хинтами.
15 мар 13, 17:58    [14054533]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Crimean
Member

Откуда:
Сообщений: 13147
Ennor Tiegael
Единственный случай, который я поймал за 4 с лишним года - нужно было организовать строго последовательный доступ к финансовому аккаунту клиента. Чтобы нельзя было одновременно из двух коннектов сделать два заказа на общую сумму, превышающую баланс. Блокировочник просто вставал на ожидание, а вот RCSI такое пропускает, в результате чего после второго коммита имеем отрицательный баланс. Решилось хинтами.


эй, эй, не надо грязи!! типовые шаблоны:

№1

update accounts set balance = balance + @delta where id = @id


№2

begin tran
select @balance = balance from accounts with (xlock) where id = @id
set @balance = @balance + @delta
update accounts set balance = @balance where id = @id
commit tran


у вас был №2 причем в select не было xlock, а должен быть! и RCSI тут вообще никаким боком, если в №2 хинт не ставить - будет влет при любом положении RCSI
15 мар 13, 18:25    [14054699]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
Ennor Tiegael
Fire83
В вот возможно ли, например, прочитать строку дважды? Вооще не прочитать её хотя был коммит?
И то, и другое можно легко словить, если подсунуть в соседней транзакции грамотно спроектированный апдейт. Одним только инсертом такое не делается, вроде.
Да легко!
1ый процесс читает страницу данных, 2ой вставляет в эту страницу еще одну запись, места на странице нет, происходит сплит, часть данных уходит в конец таблицы, и тут до нее добирается процесс №1...
15 мар 13, 21:25    [14055527]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3422
Crimean,

-- Читаем в переменную - нужна для последующих проверок
select @AccountAmount = Deposit, @TS = TS
from dbo.ClientAccounts with (xlock, holdlock, rowlock)
where Id = @AccountId;

...

-- Пишем
update ca set Deposit = ca.Deposit + case @ActionMask when 1 then ao.amount else 0 end,
	-- For credit-related operations, reducing of deposit part also reduce (repay) of credit part, and vice versa
	Credit = ca.Credit + case @ActionMask when 3 then ao.amount else 0 end
from dbo.ClientAccounts ca
	inner join dbo.AccountOperations ao on ca.Id = ao.AccountId
where ca.Id = @AccountId
	and ao.OperationId = @OperationId
	and ca.TS = @TS;

-- Check for consistency
if @@rowcount = 0
	-- Error on account access
	raiserror(80235, 16, 1);
Изначально я слегка нагнал - в принципе, проверка таймстемпа записи гарантирует нас от отрицательного баланса. Другой вопрос, что клиентам не интересно ловить 80235, ибо на данный момент все возможные проверки уже пройдены, причем успешно. Вместо этого лучше немного подождать на блокировке, благо это все-таки не форекс.

Разумеется, если второй коннект читает таблицу счетов, пока первый находится между этими двумя запросами, то тут никакого RCSI не надо, чтобы в минус улететь. Но расстояние между ними минимальное, обычно меньше 1 мс выходит. А вот дальше, после апдейта, идет достаточно действий, чтобы второй коннект успел прочесть предыдущую версию записи, которую ему подсовывает RCSI.
16 мар 13, 06:25    [14056474]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3422
Mind,

Может, согласен, совсем забыл про сплиты, ибо последние 5 лет писал код исключительно под RCSI :)
16 мар 13, 06:44    [14056480]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
invm
Member

Откуда: Москва
Сообщений: 9827
Crimean
да где вы все это вычитываете, покажите! ни разу еще ни одного факапа с этой опцией не было
Все же RCSI опосредованно влияет и на писателей в части ожиданий на блокировках. Так что возможность получение факапа нельзя исключать.
17 мар 13, 13:07    [14058961]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Ennor Tiegael
Crimean,

-- Читаем в переменную - нужна для последующих проверок
select @AccountAmount = Deposit, @TS = TS
from dbo.ClientAccounts with (xlock, holdlock, rowlock)
where Id = @AccountId;

...

-- Пишем
update ca set Deposit = ca.Deposit + case @ActionMask when 1 then ao.amount else 0 end,
	-- For credit-related operations, reducing of deposit part also reduce (repay) of credit part, and vice versa
	Credit = ca.Credit + case @ActionMask when 3 then ao.amount else 0 end
from dbo.ClientAccounts ca
	inner join dbo.AccountOperations ao on ca.Id = ao.AccountId
where ca.Id = @AccountId
	and ao.OperationId = @OperationId
	and ca.TS = @TS;

-- Check for consistency
if @@rowcount = 0
	-- Error on account access
	raiserror(80235, 16, 1);
Изначально я слегка нагнал - в принципе, проверка таймстемпа записи гарантирует нас от отрицательного баланса. Другой вопрос, что клиентам не интересно ловить 80235, ибо на данный момент все возможные проверки уже пройдены, причем успешно. Вместо этого лучше немного подождать на блокировке, благо это все-таки не форекс.

Разумеется, если второй коннект читает таблицу счетов, пока первый находится между этими двумя запросами, то тут никакого RCSI не надо, чтобы в минус улететь. Но расстояние между ними минимальное, обычно меньше 1 мс выходит. А вот дальше, после апдейта, идет достаточно действий, чтобы второй коннект успел прочесть предыдущую версию записи, которую ему подсовывает RCSI.

Каким же образом второй коннект прочтёт предыдущую версию записи? Он читает без этих хинтов: with (xlock, holdlock, rowlock)? Тогда приведите код, который работает во второй коннекции.
Если код во второй коннекции такой же, то with (xlock, holdlock, rowlock) навесит на ключ Id = @AccountId либо X-блокировку, либо блокировку RangeX-X. Соответственно другая коннекция будет висеть на ожидании этого ключа при попытке сделать select, а когда значение будет считано, оно уже будет с учётом результата первой транзакции. Приведённый вами код одинаково работает как на блокировочнике, так и на версионнике.
18 мар 13, 09:57    [14061118]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Гость333
Member

Откуда:
Сообщений: 3683
invm
Все же RCSI опосредованно влияет и на писателей в части ожиданий на блокировках.

Поясните вашу мысль, пожалуйста. Не очень понятно, какое именно влияние оказывается на писателей — ведь они (вроде бы) не накладывают S-блокировок на ресурсы?
18 мар 13, 10:05    [14061147]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3422
Гость333,

Спасибо, кэп.

Да, это один и тот же код, в несколько потоков. Вы, видимо, не поняли самого главного: хинты - это то, что мне пришлось добавить, чтобы поведение данного кода стало одинаковым и на блокировочнике, и на RCSI.

Я привел это как пример того, что иногда RCSI может изменять поведение кода в неожиданную сторону. В ответ на ту эскападу Crimean'a, где он утверждал, что без хинтов будет залет в любом режиме.
18 мар 13, 10:26    [14061222]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Ennor Tiegael
Вы, видимо, не поняли самого главного: хинты - это то, что мне пришлось добавить, чтобы поведение данного кода стало одинаковым и на блокировочнике, и на RCSI.

Конечно, не понял, бо об этом не было сказано :-)
18 мар 13, 10:49    [14061315]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Ennor Tiegael
Разумеется, если второй коннект читает таблицу счетов, пока первый находится между этими двумя запросами, то тут никакого RCSI не надо, чтобы в минус улететь.

Опять же не понял — вы говорите, что TS — это таймпстемп и он не даёт уйти в минус. Вроде так оно и есть. Так уходим в минус или нет? :-)
18 мар 13, 10:56    [14061350]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
invm
Member

Откуда: Москва
Сообщений: 9827
Гость333
Поясните вашу мысль, пожалуйста. Не очень понятно, какое именно влияние оказывается на писателей — ведь они (вроде бы) не накладывают S-блокировок на ресурсы?
Например, в транзакции1 выполнено:
update Table1 set Status = ... where id = 1;
Затем транзакция2 выполняет:
update t2
 set
   SomeField = ...
from
 Table2 t2 join
 Table1 t1 on t1.id = t2.id
where
 t2.id = 1 and t1.Status = ...;
На RC вторая будет ждать завершения первой, на RCSI не будет.
Существенно ли это для системы или нет и нужно выяснять перед переходом на RCSI.
18 мар 13, 11:18    [14061445]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3422
Гость333
Ennor Tiegael
Разумеется, если второй коннект читает таблицу счетов, пока первый находится между этими двумя запросами, то тут никакого RCSI не надо, чтобы в минус улететь.

Опять же не понял — вы говорите, что TS — это таймпстемп и он не даёт уйти в минус. Вроде так оно и есть. Так уходим в минус или нет? :-)
Нет, не уходим.
Изначально, когда я говорил про уход в минус, я забыл что сделал проверку на таймстемпах. Это было несколько лет назад, всех деталей в голове не удержишь :)
18 мар 13, 12:07    [14061659]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Crimean
Member

Откуда:
Сообщений: 13147
Ennor Tiegael,

а вы это чего, без транзакции делали?
18 мар 13, 15:51    [14063109]     Ответить | Цитировать Сообщить модератору
 Re: использование read uncommitted  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3422
Crimean,

Смеетесь, что ли? С клиентскими деньгами так не шутят :)
18 мар 13, 17:17    [14063666]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить