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

Откуда: Кишинёв
Сообщений: 6724
UP
Mnior
Вопрос: Для чего нужно локировать строку путём чтения, но при этом не давать (XLock) делать банальное чтение (без намерения изменения) другим ?
10 июл 12, 17:05    [12846287]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Леша777
Guest
Вопрос: Для чего нужно локировать строку путём чтения, но при этом не давать (XLock) делать банальное чтение (без намерения изменения) другим ?



Есть несколько игоровых серверов соединенные с одной базой данных. А клиенты соединяются с игровыми серверами.
В системе есть так назывемые накления - пулы (таблица PP). В момент когда наступает событие X (джэкпот), создается новый экземпляр пула. В системе може быть только один активный пул одного типа.
Игровые серверы постоянно получают текущие значения (S lock), так и наращивают его.
Если все-таки дэкпот произошел, то все ( и читатели и писатели) должны ждать пока новый экзэпляр создасться.
Может быть и такое что на 2 игровых серверах произошли джэкпоты одновременно (чисто теоретический случай, очень низкая вероятность), то они должны быть обработаны последовательно.
Первый произошел - пересчиталась началальная сумма и новый создался, а уже на его основании второй.
10 июл 12, 18:04    [12846685]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Леша777, спасибо что ответили и не побоялись привести свою систему.

Коль опять не описана причина ожидания подсчётов читателями, попытаюсь доописать.

Значит имеем модель игры:
Игроки, игровые столы (рулэтка), сыгранные и не ещё сыгранные партии, фишки и ставки.
Фишки это суммы на счетах (карманах) игроков (или казино), а также суммы ставок.

"активный пул" - естественно что игровой стол может вести одну партию за раз.
Консистивность определяется одним элементом (для каждого стола), не важно как, это либо таблица (при Top(1) ORDER BY) или строка (уникальный индекс по одному состоянию), неважно, всегда будет только один объек в базе - и консестивносить будет основываться на системе блокировок и контролю уникальности.
Это так сказать "бутылочное горлышко", из-за чего система изменений будет выстраиваться в очередь/последовательность.

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

Но даже в одной области момент вещь долгая (прцессы в мире кварков), но атомарная (законы сохранения), даже в базе момент длится от BEGIN TRAN до COMMIT, но при это он остаётся мгновением.
Эта относительность весёлая штука - можно получить старые данные после BEGIN TRAN (хотя только на микросекундах), даже в локировочной системе(данные при этом останутся консестивными). Локировка это не сферический конь в вакууме.

Поэтому нужно понимать, что если запустить сначало запрос А, а потом параллельно такой же Б, то при малых разницах времени может случится, что A получит новые данные, а Б старые. Это нормально (и ничему не противоречит).
--------------------------------------------------------------------------------
Вернёмся к задаче. Рассмотрим воможные процессы:
Расчёт "активности" игры, активация новой, завершение (джекпот)
Расчёт выиграша
Расчёт сумм на счетах (карманов)
Просмотр результатов игры, выигрышей и остатков.

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

Между двумя командами BEGIN TRAN и COMMIT, мы вволе выбрать что запрос относится к моменту ДО или ПОСЛЕ события, которое эта транзакция вносит. И не важно, у нас SNAPSHOT или READ COMMITED, элемент "случайности" всё равно остаётся (микро задержки, расположение элементов в памяти, или особенности конкрктных алгоритмов). [Просто для снапов это ближе к BEGIN, а для локов ближе к COMMIT].

Процесс "джекпот" будет состоять с определённой последовательности изменений базы.
- Смена состояния у игры, запись выпавшего значения
- чтение данных установленных на кон сумм
- подсчёт выиграша
- запись выигрыша на счета

Процесс "ставка":
- снятие сумм со счетов
- считывание "активной" игры
- и запись ставки
(последние два пункта атомарны)

Процессы "окончание ставок", "обналичивание счетов" и т.п. аналогично.
--------------------------------------------------------------------------------
Теперь указывайте, где есть ошибки:
1. наличие чтения блокирующего другие чтения
2. неправильная последовательность, проводящая к нарушению целостности

PS: Надеюсь, что все написано в стиле KO и не возникает чувство "какая-то муть"? Если чё пишите.
PPS: А где описано в BOL что запросы атомарны?
11 июл 12, 13:45    [12850463]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
UP
12 июл 12, 01:34    [12853834]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Леша777
Guest
Mnior , похоже но не совсем так, как вы описали.

Люди играют, делают ставки, и мизерный процент от каждой ставки накапливается (например 0.05 %) в фонд (пул).
Когда происходит джэкпот накапления перераспределются : часть фонда идет победителям, часть проигравшим, часть остается в фонде как стартовая сумма нового экзэмпляра.

Так вот, произошел джэкпот: Cколько на данным момент в фонде ? Для меня UNKNOWN. Пока проценты раздачи не пересчитаны и новый экзэмпляр фонда не создан.
Я не понимаю, почему я имею право показывать старые данные если событие уже произошло ?
Опять же произошел джэкпот, но игры ведь продолжаются - делаются новые ставки и как результат фонд должен увеличиваться. А как фонд ? старый уже невалиден, а нового еще нету.


PS. Ну а макрософт могли бы конечно в BOL описать поведение XLOCK
12 июл 12, 10:55    [12854803]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Леша777
Люди играют, делают ставки, и мизерный процент от каждой ставки накапливается (например 0.05 %) в фонд (пул).
Это не важно, я вроде как абстрактно написал. Просто "фонд" всегда выигрывает

Леша777
Так вот, произошел джэкпот: Cколько на данным момент в фонде ? Для меня UNKNOWN. Пока проценты раздачи не пересчитаны и новый экзэмпляр фонда не создан.
Я не понимаю, почему я имею право показывать старые данные если событие уже произошло ?
Как у вас с физикиой в школе обстояло?

С чего вы решили что событие "произошло"?
Если "событие произошло", то как вы интерпретируете RollBack?

Событие происходит, но не произошло. Вы всё событие (всё что оно делает) сопоставляете с моментом, а не с диапазоном времени потому, что так вы сможете однозчно сопоставить порядок действий. И только. И этот порядок определяет простоту расчётов, и простоту контроля целостности (законов сохранения).

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

Ваша задача указать лишь ограничения: какие одни типы "моментов"/событий могут идти за другими. И только.
Локировки это мезанизм упорядочивания событий. Транзакции определяют события. Порядок действий в транзакции определяет нужные вам ограничения.

Леша777
Опять же произошел джэкпот, но игры ведь продолжаются - делаются новые ставки
старый уже невалиден
С какого бодуна?

Но это не так важно.
Вы посмотрите (12850463) на то как я выписал порядок действий событий. Вы видите, что нет такого, что чтение заблокировало другое чтение ?! Там есть только что изменение заблокировало чтение.

Леша777
PS. Ну а макрософт могли бы конечно в BOL описать поведение XLOCK
А что не описано?! Только может размазано по нескольким статьям.
12 июл 12, 12:06    [12855530]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
UP
Mnior
Вопрос: Для чего нужно локировать строку путём чтения, но при этом не давать (XLock) делать банальное чтение (без намерения изменения) другим ?
13 июл 12, 12:07    [12862131]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Кстати, ReadPast и ReadCommittedLock также "видит" заблокированные (неизменённые) строки.
RepeaTableRead, Serializable. конечно же блокируется, т.к. он рельно накладывает локировку чтения.

KO
13 июл 12, 13:19    [12862700]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Леша777
Guest
Mnior,

А почему можно читать?

Что плохого в том, чтобы не давать читать ? Почему у меня нет такой возможности кроме изменения строки ?


Когда я смотрю таблицу таблицу совсместимости блокировок в BOL, то я вижу что X и S несовместимы.
И нету никакой сносочки под таблицей **, говорящей о том что строка должна быть изменена.

Читаем дальше :

Specifies that exclusive locks are to be taken and held until the transaction completes. If specified with ROWLOCK, PAGLOCK, or TABLOCK, the exclusive locks apply to the appropriate level of granularity.

А почему тоже самое не работает для TABLOCKX ? Почему данные не читаются. Попробуйте. Ну на дргом уровне X, но данные то не менялись.

Я считаю, что в BOL должно быть описание в месте где хинт XLOCK
должен быть описан побочный эфект (особенность), что это не чистая X блкировка, а + данные должны изменены. Потому как поведение не соотв. Сompatibility matrix.

Теперь рассмотрим поведение update, когда ничего не меняем и такой же update c хинтом.

В первом случае накладывается U, предикат - true, меняем на X, иначе снимаем. U c S совместимы. Потенциально получаем deadlock. Если тот кто S наложил был Repatable Read например.

Для update c xlock это исключено.



С чего вы решили что событие "произошло"?
Если "событие произошло", то как вы интерпретируете RollBack?


На игровом сервере произошло, клиент (конечный игрок ) об этом узнал. Теперь он ждет приза. В случае rollback он ничего не получит.

Причины rollback ?
какая-нибудь ошибка ( случился deadlock, log переполнен, нарушено какое-нибудь check constraint). Мы естесственно логируем ошибки, тестрием, делаем все чтобы их минимизировать.
Да, в этом случае распределения не будет. Все останется как было.
13 июл 12, 13:33    [12862819]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Леша777
Что плохого в том, чтобы не давать читать? Почему у меня нет такой возможности кроме изменения строки?
1. Не имеет смысла (для любых задач)
2. Эта (никому не нужная) функциональность дорого обходится (для всех)

Леша777
Когда я смотрю таблицу таблицу совсместимости блокировок в BOL, то я вижу что X и S несовместимы.
И нету никакой сносочки под таблицей **, говорящей о том что строка должна быть изменена.
Не боги горшки обжигают.
Вы можете это поправить (внизу "добавить").

Леша777
А почему тоже самое не работает для TABLOCKX? Почему данные не читаются.
Потому что локировка на таблицу ставится палюбэ, это объект схемы, а не данные.

Леша777
update c хинтом
Масло масляное.
Хинты тут не нужны. Хинтами вы управляете только чтение, а не изменение (оно палюбэ X до конца транзакции).

Леша777
В первом случае накладывается U ...
Не верю (с). Для UPDATE ставится X сразу.

Давайте расмотрим SELECT FOR UPDATE для вашего случая.
Леша777
В первом случае накладывается U, потом меняеся на X. U c S совместимы. Потенциально получаем deadlock. Если тот кто S наложил был Repatable Read например.
Ничё не будет, если не будет других запросов на изменение. Т.е. явная ошибка в коде.

U даёт читать всем без намерения изменеиня. А коль не менять - то никаких дедлоков.
U не даёт читать тем у кого есть намерение изменения (U). Опять никаких дедлоков.

Т.е. если кто-то пишет:
BEGIN TRAN

SELECT	*
FROM	X WITH (RepeatableRead)
WHERE	ID = @ID

UPDATE	X
SET	..
WHERE	ID = @ID
Просто неотёсанный буратино. Первая команда говорит - "я менять не собираюсь", а последующая "поменяйте, пжалуста".
Идиотизм! На месте MS я бы даже не дал запустить такой код (но это нереально проанализировать).

Repatable Read сначало ставит локировку, а потом читает и не снимает локировку.
А Read Committed сразу читает, без наложения и снятия локировок, просто во время чтения проверяет страницу на наличие изменений (контрольный бит).
Repatable Read не контролирует этот бит.

Леша777
С чего вы решили что событие "произошло"?
Если "событие произошло", то как вы интерпретируете RollBack?
На игровом сервере произошло, клиент (конечный игрок) об этом узнал.
Ничего подобного!, пока событие не закончится (COMMIT), об этом никто не узнает. Потому что он не сможет прочитать изменение. То что не поменялось (событие не произошло) он прочитает (как ничего не произошло).

Леша777
Причины rollback ?
какая-нибудь ошибка ( случился deadlock, log переполнен, нарушено какое-нибудь check constraint). Мы естесственно логируем ошибки, тестрием, делаем все чтобы их минимизировать.
В том-то и дело, что это не важно. Ибо никто не узнает об этом. Кроме того кто попытался провести само событие (джекпот). Ему лишь остаётся повторно провести.
13 июл 12, 15:47    [12863892]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Леша777
Guest
Потому что локировка на таблицу ставится палюбэ, это объект схемы, а не данные.


Что за бред ? Давайте не путь блокировки изменнения объектов схемы с уровнями (строка, страница, таблица).

Почему чтение в этом случае невозможно ?

BEGIN TRAN 

SELECT *
FROM dbo.ActionTypes at WITH(XLOCK, PAGLOCK)


Строка такой же абслоютно уровень как и страница.

Данные изменились ?
Нет. Чего ждем ?

Не верю (с). Для UPDATE ставится X сразу.


Откройте профайлер и посммотрите, неверующий. Для Updat-ов U блокировки и были придуманы.
13 июл 12, 16:17    [12864083]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Леша777
Потому что локировка на таблицу ставится палюбэ, это объект схемы, а не данные.
Что за бред
Согласен. Тупанул. Схема тут не причём.

На таблицу и на страницу также накладывается блокировки палубе. Только там ставятся IS (если я не путаю) - совмещаемые (при RowLock стратегии). Нужно же всю иерархию залочить. А многие совмещамые - совместимы (ссори за тавтологию). Кстати, тогда и проверяется на контрольный бит.
Но когда вы ставите Page или Table lock, тогда ставятся уже не совмещаемые на эти уровни, а эксклюзивные.

Леша777
Строка такой же абслоютно уровень как и страница.
Чё за фигня. Строка/Страница/Партиция/Таблица это разные объекты. Да это всё данные, но уровни разные.

Леша777
Данные изменились?
Нет. Чего ждем?
А ХЗ. By design.
Или вы считаете что частное решение програмного кода, есть доказательство физических законов ?! Нет!

автор
Не верю (с). Для UPDATE ставится X сразу.
Откройте профайлер и посммотрите, неверующий.
USE tempdb
GO
CREATE TABLE dbo.Tbl (ID Int PRIMARY KEY, Data Int)
GO
INSERT dbo.Tbl VALUES (1,1)
GO
BEGIN TRAN XXX

UPDATE dbo.Tbl
SET Data = 1
WHERE ID = 1

EXEC sp_lock

ROLLBACK
GO
DROP TABLE dbo.Tbl
spiddbidObjIdIndIdTypeResourceModeStatus
782772953851PAG1:1100402 IXGRANT
782772953851KEY(010086470766) XGRANT
782772953850TAB IXGRANT
А как в профайлере?
Для доказательства моих утверждений большего не надо.

Но лучше показать, что снача ставится U, а затем сразу X.
Если так, то это также не логично со стороны M$, ибо просто бессмысленно по количесву телодвижений.

Леша777
Для Updat-ов U блокировки и были придуманы.
Режимы блокировки:
BOL
Режим блокировкиОписание
локировка обновления (U)Применяется к тем ресурсам, которые могут быть обновлены. Предотвращает возникновение распространенной формы взаимоблокировки, возникающей тогда, когда несколько сеансов считывают, блокируют и затем, возможно, обновляют ресурс.
Монопольная блокировка (Х)Используется для операций модификации данных, таких как инструкции INSERT, UPDATE или DELETE. Гарантирует, что несколько обновлений не будет выполнено одновременно для одного ресурса.
Не думаю что изначально для этого. Но точно не только для этого. Как раз только для SELECT FOR UPDATE имеет смысл.

Не забывайте про основную тему.
13 июл 12, 17:21    [12864558]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Леша777
Guest
А как в профайлере?


Я делаю так:
открываю новый запрос. запинаю spid.
Открываю профайлер выбираю 2 события : Lock:Acquired и Lock:Released.
И смотрю полную историю-деталировку как оно было.

Если есть таблица совместимости блокировок, то она должна работать на всех уровнях. А если есть особенности они должны быть описаны.

Для меня все уровни одинаковые, главное тут, что при блокировке любого, нужно наложить блокировки намерения на все вышестояшие. А какой он, 2 или 3ий неважно.
Главное тут понятие - ресурс. А он может быть оюъектом любого уровня.

И мое мнение, что поеведение хинта XLOCK непоследовательное. Я бы понял и согласился если бы оно хотя бы на уровне строк тоже работало так.

Если уже I из ACID не нарушается.
Если упор делается именно на изменения .
13 июл 12, 17:42    [12864645]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Леша777
профайлер
Помню было даже на форуме, что можно и без профайлера.
Нужно просто разнести операцию чтения и непосредственно изменения. Т.е. сделать соединение с другой таблой, которую предварительно залочить.
Посмотрю профайлер и покажу пример на запросе уже в понедельник, когда доступ к скулю будет.

Но жаль что M$ очередной раз расстраивает (если так оно и есть - дублирование действия в одной операции).

Леша777
Если есть таблица совместимости блокировок, то она должна работать на всех уровнях. А если есть особенности они должны быть описаны.
А вы заметили что я написал (12863892) "S локировка не ставиться для RowLock ReadCommitted". Можете проверить, тогда всё нормально даже с "таблицей совместимости локировок".

Леша777
Для меня все уровни одинаковые, главное тут, что при блокировке любого, нужно наложить блокировки намерения на все вышестояшие. А какой он, 2 или 3ий неважно. Главное тут понятие - ресурс. А он может быть оюъектом любого уровня.
Тут нужно поправить: не "намерения", а "совмещения". От "совмещать части чего-то общего", насколько "совмещать" - смотреть полную таблицу совместимости локировок.

Леша777
И мое мнение, что поведение хинта XLOCK непоследовательное.
Я как раз поставил целью не просто понять самому что это не так, но ещё показать это здесь на форуме. И я рад что вы дискутируете.

Леша777
Если уже I из ACID не нарушается.
Если упор делается именно на изменения.
Да, по определению всё правильно. Но я хочу показать не юридическую сторону (в ней нет никакого смысла), а физику, что и подразумевают когда говорят "нарушен ACID". А то некоторые путают причины и следствия "определения".

Я думаю тут заложена историческая причина - развитие железа и алгоритмов. И приходиться пере-осознавать теорию РБД из-за новых инструментов!
И я рад, что в M$ нашёлся чувак, который этим занялся и нашёл "решение" (с битом изменения). Хотя там море изменений, можно управлять страницами на уровне железа (к примеру доступность страницы памяти для данного процесса) не тратя драгоценных тактов (если это получается).

PS: Леша777, спасибо, что беседуете. Чем больше беседуем чем точнее формулируем и лучше понимаем механизмы. Кайф.
Я тут ещё параллельно беседую со своими, мы там даже рассматриваем возможные алгоритмы поведения. К примеру, когда читается бит изменения страницы и что делается если он меняется.

Тут есть один важный подводный камень, когда страница меняется хотя чтения уже происходят. Интересно?
13 июл 12, 21:32    [12865433]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Леша777
профайлер
BEGIN TRAN XXX

UPDATE dbo.Tbl
SET Data = 1
WHERE ID = 1

--
ROLLBACK
SPIDEventClassEventSequenceModeTypeObjectID2TextDataStartTyme
78Lock:Acquired9286878 - IX5 - OBJECT2212958982012-07-16 09:27:43.783
78Lock:Acquired9286888 - IX6 - PAGE40352253837209763841:11004022012-07-16 09:27:43.783
78Lock:Acquired9286895 - X7 - KEY4035225383720976384(010086470766)2012-07-16 09:27:43.783
78Lock:Released9286900 - NULL7 - KEY4035225383720976384(010086470766)2012-07-16 09:27:43.783
78Lock:Released9286910 - NULL6 - PAGE40352253837209763841:11004022012-07-16 09:27:43.783
78Lock:Released9286935 - X7 - KEY4035225383720976384(010086470766)2012-07-16 09:27:45.850
78Lock:Released9286948 - IX6 - PAGE40352253837209763841:11004022012-07-16 09:27:45.850
78Lock:Released9286958 - IX5 - OBJECT2212958982012-07-16 09:27:45.850
Значит у M$ тут нормально.
+ Теперь сложный случай (согласно плану)
BEGIN TRAN XXX

UPDATE	T
SET	Data = 2
FROM	dbo.Tbl T JOIN dbo.Tb2 T2 ON T2.ID = T.Data
WHERE	T.ID = 1

--
ROLLBACK
Параллельно я временно блокировал вторую таблу.
SPIDEventClassEventSequenceModeTypeObjectID2TextDataStartTyme
78Lock:Acquired9294746 - IS5 - OBJECT2852961262012-07-16 09:49:38.713
78Lock:Acquired9294758 - IX5 - OBJECT2212958982012-07-16 09:49:38.713
78Lock:Acquired9294767 - IU6 - PAGE40352253837209763841:11004022012-07-16 09:49:38.713
78Lock:Acquired9294774 - U7 - KEY4035225383720976384(010086470766)2012-07-16 09:49:38.713
78Lock:Acquired9294786 - IS6 - PAGE41072829777998643201:11004892012-07-16 09:49:38.713
78Lock:Acquired9294813 - S7 - KEY4107282977799864320(010086470766)2012-07-16 09:49:38.703
78Lock:Acquired9294828 - IX6 - PAGE40352253837209763841:11004022012-07-16 09:49:44.910
78Lock:Acquired9294835 - X7 - KEY4035225383720976384(010086470766)2012-07-16 09:49:44.910
78Lock:Released9294843 - S7 - KEY4107282977799864320(010086470766)2012-07-16 09:49:44.910
78Lock:Released9294856 - IS6 - PAGE41072829777998643201:11004892012-07-16 09:49:44.910
78Lock:Released9294860 - NULL7 - KEY4035225383720976384(010086470766)2012-07-16 09:49:44.910
78Lock:Released9294870 - NULL6 - PAGE40352253837209763841:11004022012-07-16 09:49:44.910
78Lock:Released9294886 - IS5 - OBJECT2852961262012-07-16 09:49:44.910
78Lock:Released9294915 - X7 - KEY4035225383720976384(010086470766)2012-07-16 09:49:51.120
78Lock:Released9294928 - IX6 - PAGE40352253837209763841:11004022012-07-16 09:49:51.120
78Lock:Released9294938 - IX5 - OBJECT2212958982012-07-16 09:49:51.120
И для 2х строк:
SPIDEventClassEventSequenceModeTypeObjectID2TextDataStartTyme
78Lock:Acquired9298046 - IS5 - OBJECT2852961262012-07-16 10:03:01.453
78Lock:Acquired9298058 - IX5 - OBJECT2212958982012-07-16 10:03:01.453
78Lock:Acquired9298067 - IU6 - PAGE40352253837209763841:11004022012-07-16 10:03:01.453
78Lock:Acquired9298074 - U7 - KEY4035225383720976384(010086470766)2012-07-16 10:03:01.453
78Lock:Acquired9298086 - IS6 - PAGE41072829777998643201:11004892012-07-16 10:03:01.453
78Lock:Acquired9298173 - S7 - KEY4107282977799864320(010086470766)2012-07-16 10:03:01.450
78Lock:Acquired9298188 - IX6 - PAGE40352253837209763841:11004022012-07-16 10:03:24.117
78Lock:Acquired9298195 - X7 - KEY4035225383720976384(010086470766)2012-07-16 10:03:24.117
78Lock:Released9298203 - S7 - KEY4107282977799864320(010086470766)2012-07-16 10:03:24.117
78Lock:Released9298216 - IS6 - PAGE41072829777998643201:11004892012-07-16 10:03:24.117
78Lock:Released9298220 - NULL7 - KEY4035225383720976384(010086470766)2012-07-16 10:03:24.117
78Lock:Released9298230 - NULL6 - PAGE40352253837209763841:11004022012-07-16 10:03:24.117
78Lock:Acquired9298247 - IU6 - PAGE40352253837209763841:11004022012-07-16 10:03:24.117
78Lock:Acquired9298254 - U7 - KEY4035225383720976384(020068e8b274)2012-07-16 10:03:24.117
78Lock:Acquired9298266 - IS6 - PAGE41072829777998643201:11004892012-07-16 10:03:24.117
78Lock:Acquired9298293 - S7 - KEY4107282977799864320(020068e8b274)2012-07-16 10:03:24.127
78Lock:Acquired9298308 - IX6 - PAGE40352253837209763841:11004022012-07-16 10:03:31.273
78Lock:Acquired9298315 - X7 - KEY4035225383720976384(020068e8b274)2012-07-16 10:03:31.273
78Lock:Released9298323 - S7 - KEY4107282977799864320(020068e8b274)2012-07-16 10:03:31.273
78Lock:Released9298336 - IS6 - PAGE41072829777998643201:11004892012-07-16 10:03:31.273
78Lock:Released9298340 - NULL7 - KEY4035225383720976384(020068e8b274)2012-07-16 10:03:31.273
78Lock:Released9298350 - NULL6 - PAGE40352253837209763841:11004022012-07-16 10:03:31.273
78Lock:Released9298366 - IS5 - OBJECT2852961262012-07-16 10:03:31.273
78Lock:Released9298425 - X7 - KEY4035225383720976384(020068e8b274)2012-07-16 10:03:40.527
78Lock:Released9298435 - X7 - KEY4035225383720976384(010086470766)2012-07-16 10:03:40.527
78Lock:Released9298448 - IX6 - PAGE40352253837209763841:11004022012-07-16 10:03:40.527
78Lock:Released9298458 - IX5 - OBJECT2212958982012-07-16 10:03:40.527
Блокировал так:
BEGIN TRAN YYY

UPDATE dbo.Tb2
SET Data = 2
WHERE ID = 1

--
ROLLBACK
Остаётся вопрос, а зачем MS ставит U и лишь затем X, а не сразу X.
1. Длительные операции. Типа хешь соединения и т.п. и когда не построчно, а скопом
2. Неизвестность/неточность предстоящего (не всегда U в X, может и просто Release)
3. Возможное укрупнение блокировки (гарантированно хреново скажется на других процессах)

Выгодная ли текущая стратегия? А ХЗ. В плане того что итак читается при X, то очень слабая стратегия. Даже повышеный уровень дедлока (при корявых прогеров).
Но как обычно, снова и опять, в очередной раз, мешает поправить ситуацию всякая мелочёвка. Укрупнение блоировки до уровня таблицы в случает смены U на X рискованное дело, хотя это нужно ещё посмотреть на возможные случаи, что ставит все предыдущие исследования "коту под хвост". На самом деле, они уже "под хвостом", только неофицально, официально поставить это в самой компании разрабам "кишка тонка".

Что я понимаю - можно далее нехило ускорять блокировочную технологию. Уменьшив количество "телодвижений" до минимума.
===================================================================================================
Но мы отвлеклись от основной темы.

Mnior
Вопрос: Для чего нужно локировать строку путём чтения, но при этом не давать (XLock) делать банальное чтение (без намерения изменения) другим ?
Леша777, в вашем случае нет требуемого в вопросе случая.

UP
16 июл 12, 12:27    [12871980]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Леша777
Guest
Я знаю почему, но если вы добавите индекс на столбец Data из вашего примера. То U будет даже в простом случае.
Думал изначально, что в случае сканов, когда непонятно что обновлять, то шел перебор с U и потом снятие или Х.
У меня на таблице есть один некластерный индекс, и U было всегда. А стал ваш пример проверять, действительно сразу X.


Вопрос: Для чего нужно локировать строку путём чтения, но при этом не давать (XLock) делать банальное чтение (без намерения изменения) другим ?


Я же уже говорил, что если процесс расчета начался, то текущее значение неопределено.



Вы мне можете по-простому, на пальцах объяснить почему можно? Расчет то начат. Почему вы считаете на этот момент старое значение все еще валидно ?

У меня такая ситуация:
Клиент понимает, что произошел событие, для него оно произошло.
Идет расчет и клиентам показывается, кто чего получил.


Ну и встречные вопрос, не совсем по теме ?

Вы когда-нибудь использовать RCSI? Для каких задач это может быть применимо ?
Как это так показывать старые версии данных на начало стэйтмента, если они изменились (залочены) ? Пофиг что читать, лишь бы не ждать снятия блокировки. Я честно не понимаю этого уровня.


Другое совсем дело чистый Snapshot - где соглассованное состояние системы на момент старта транзакции.
16 июл 12, 14:22    [12872587]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Леша777
Я же уже говорил, что если процесс расчета начался, то текущее значение неопределено.
Это с какого бодуна?!
Не может быть такого "значение неопределено", оно определено: до COMMIT одно значение, после другое, никиких промежуточных неопределённых значений нет.

Ещё раз, если стоит лок, то это не значит значение не определено, это значит считывание "переносится во времени". А пока оно не считалось, говорить о значении нет смысла.

Леша777
Вы мне можете по-простому, на пальцах объяснить почему можно?
Понятия это не тупой расчёт, это строго определённо вычерченные определения, и мне нужно тыкать вас в те места, где ваши определения "несрастаются". И вам нужно почувствовать теорию.

Леша777
Расчет то начат. Почему вы считаете на этот момент старое значение все еще валидно ?
А с чего оно не валидино?
В системе нет никаких вычислений вообще, внутренние вычисления системе до лампочки, они нигде не фиксируются, их не существует.
В системе есть состояние ДО и состояние ПОСЛЕ. Ничего другого нет. Транзакция это линия, которое отделяет ДО от ПОСЛЕ, отделяет чётко.

Леша777
Клиент понимает, что произошел событие, для него оно произошло.
Ошибка.
БД консестивна, в ней нет независимых частей, в ней клиент "понимает", "очки подсчитаны", "суммы зачислены" идут вместе одновременно.
Клиент не сможет получить информацию, что событие произошло, а суммы не подсчитаны, он либо будет получать:
а) событий нет, сумма X
б) событие есть, сумма Y
Неважно были ли задержки от базы или нет. Не клиенты определяют, что событие произошло, а база. База всему венец.

Леша777
Идет расчет и клиентам показывается, кто чего получил.
Ничего не идёт, нет такого процесса. Нету и всё тут. Есть состояние ДО и состояние ПОСЛЕ.
Как только вы это возмёте за непоколебимое, вы сможете дальше решать, что должно выполнятся в данной реализации СУБД, а что нет, чтобы они продолжали быть нерушимыми.

+ RCSI
Леша777
Вы когда-нибудь использовать RCSI?
Честно - практики на самом MS очень мало.
SI - это оракалавская подход, и неудачные решения которые я наблюдал там, сделело меня немного неравнодушным к данному подходу. Хотя у MS реализации некотоых проблем нет, во всяком как я сейчас понимаю внутринности работы.

То, что я писал выше, что "неважно будут ли клиенты получать старые данные или блокироваться", именно это я и имел ввиду: т.е. "не важно SI или RC". Теория целостности данных не зависит от реализации.

Леша777
Для каких задач это может быть применимо ?
Это стратегия, когда видны старые данные, до самого COMMIT-а или от самого начала транзакции. У неё такие же недостакти, что и приемущества, просто перекладывается с лева направа и наоборот.

Соответственно применимо когда критична выдача данных клиенту в условиях длительных транзакций. К примеру.

Почему мне не нравиться? Потому что зарывает в песок суть проблемы. На блокировки, дедлоки можно молится - всё становится понятно сразу, а при SI забивают болт. Но повторюсь, опыта мало, может быть ошбки и при SI не сложно вкуривать.
И то что в системе может быть 100500 версий одной строки (хотя надо две) мне не нравиться, и то что это "пускается на самотёк".
Может быть стоило позволить "показывать" строго предыдущую (аля расширенный ReadPast), но я пока не думал про это.

Ещё есть проблема сбора данных, отчёты, аггрегирование и т.п. В сильно меняющейся системе иногда возникает проблема "фантомов", когда связанные данные считывают в разное время (даже в одном запросе) и следовательно при разных состояних/проведения транзакций, что будет вывалится в несхождении данных. И ставить локировки Serializable на эти длительные операции неразумно. С SI такого не будет.
Но я встречал это только на корявых проектах, так что SI я пока воспринимаю как костыль, выданный вместо лечения.

Леша777
Как это так показывать старые версии данных на начало стэйтмента, если они изменились (залочены) ? Пофиг что читать, лишь бы не ждать снятия блокировки. Я честно не понимаю этого уровня.
Это если SI - но это не важно, ждёте вы COMMIT или видите старые данные, в рамках целостности данных.
Вам разъяснить теорию версионности? Может не надо (т.е. в отдельной теме).
16 июл 12, 18:46    [12874236]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
UP
Mnior
Вопрос: Для чего нужно локировать строку путём чтения, но при этом не давать (XLock) делать банальное чтение (без намерения изменения) другим ?
17 июл 12, 15:48    [12878522]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Леша777
Guest
Вообще это бизнес требования определят что можно и когда.
XLOCK в моей задаче не помошник. вот и все.

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

P.S. Опять же повторю я решаю конкретную задачу, у меня это недоступимо.
17 июл 12, 16:24    [12878858]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Леша777
Вообще это бизнес требования определят что можно и когда.
Этого нет в бизнес требованиях. Там есть цель, но не реализация.
Леша777
мы можем старое значение отдавать ?
Зависит от задачи. Но очень слабо.
Леша777
Почему версионники вообще себе это представляют?
Ну так они устроены.
Леша777
Опять же повторю я решаю конкретную задачу, у меня это недоступимо.
Значит вы не поняли смысл. Ок, повторение (под разным ракурсом) не помогает.

Скажите, вот допустим в 15:40:42.613 запустилась процедура "джекпот", она работает ровно 10 секунд.
Что вернёт процедура "остаток на счёте", которая запустилась в 15:40:42.612 ?
А что вернёт "остаток на счёте", которая запустилась в 15:40:42.614 ?
Почему и с чего вы так решили?
Когда она вернёт значение?
А что она вернёт та, которая запустилась в 15:40:52.612 ?
А в 15:40:52.614 ?

Вот заполните табличку:
Время запуска "остаток на счёте"Что вернёт (старое/новое значение)Когда вернёт (время)
15:40:42.612
15:40:42.614
15:40:48.007
15:40:52.612
15:40:42.614
17 июл 12, 16:50    [12879121]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Леша777
Guest
Все, кто запустился после 15:40:42.613 должны получить данные после 10-секундного пересчета (в 15:40:42.613) и получить новый экзэмпляр пула.
Все кто успел до 15:40:42.613 попастать на данные (пробился в очереди, дождался возможности наложить S) - естественно старые.


Тут как вопрос бизнес-правил, можно или нет отдавать. А вы меня в строну уводите. В задача А можно, в задаче Б нельзя.
И привести когда можно вы тоже особо не хотите или не можете?
Я вам честно и открыто показал почему у меня так.

А природа такая, это типа by design. Это не ответ.
17 июл 12, 17:05    [12879255]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Отлично.

Леша777
Все, кто запустился после 15:40:42.613 должны получить данные после 10-секундного пересчета (в 15:40:42.613) и получить новый экзэмпляр пула.
А с чего вы так решили?

При этом, в интерфейсе (кнопочка) "третяя" процедура (42.614) бала запущена на клиенте раньше всех, только долго бегала по сети, а "первая" (42.612) позже, чем сама процедура "джекпот" (42.613), но на червер прибежала первой. И в итоге, по вашим словам у вас тот кто первый нажал увидел новые результаты, а последний старые. Для вас это что - нонсенс?

В вдруг SQL одноядерный, он запустил на 1 микросекунду процедуру "джекпот", потом её "заморозил" и переключтлся на "подсчёт остатка" на целую секунду, та выдала результат (веть ничего не успело заблокироваться), а потом снова на "джекпот". В итоге даже локировочный скуль выдаёт старые данные даже если было запущено позже. Или это типа "не сходится"? Но это факт.

Далее, ещё хуже, смотрим код процедуры "джекпот":
WAITFOR DELAY '00:00:06';
EXEC dbo.spJeckPot_Internal @Params -- Работает секунду
WAITFOR DELAY '00:00:03';
Опа. Оказывается, всё что было запущено до 48.613 практически сразу выдавало старые значения. А всё что было запущено после 49.613 вадавалось без задержек.

Вы понимаете, что даже если процедура закончилась позже всех, то она реально может выдать самые старые значения (это не говоря, что клиент тормозит). Это нормально. А вот привязывать результат прихода данных к текущему времени клиента, сервера и вообще к текущему времени неправильно.

Только в самих данных можно что-то контролировать. И то, что самая первая процедура прийдя последней, выдаст правильные данные - что на момент X состояние системы было Y, пусть даже если этот X давно прошёл. Усекаете?

Хотите разберём как это происходит на конкретных командах? И что порядок действий в процедуре очень важен (для RC очень).
Или уже дошло?

Для полного SI (но не RC) работает чуть по другому, там какбы вся база для данной транзакции заморожена на момент X (старта транзакции) и видны только свои собственные действия. И применяется какбы на момент окончания транзакции, при этом состояние системы не должно было измениться, иначе хамба.

Леша777
кто успел попастать на данные (пробился в очереди, дождался возможности наложить S)
Нет там никакой очереди, они там всё делают одновременно. Одновременно N-цать локировок S и одна U, но потом джекпот "в поте лица" старается дождаться пока не будет ни одной S, чтобы изменить U на X.
17 июл 12, 19:01    [12880011]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Леша777
Guest
Когда я говорю про время произошло это значит :

Пришел запрос (джэкпот), распределился на планировщик (scheduler SQL OS). Дождался своей очереди, Получил свой квант 4 мс. Начал выполняться.
4 мс прошло, все еще счиаем. Отпускаем процессор(SOS_SCHEDULER_YEILD). Расчет джэкпота в конец очереди. Пришел читатетель на процессор, ага запись залочена. в waiter list его. И со всеми читателями так будет, пока не досчитаю. Возвращаем на процессор расчет - опять ему 4 мс. Итд пока не посчитаем до конца.

Так я понимаю произошедшие события. Не время клиента, игрового сервера, а время первого попадания на процессор (running state).


Теперь по версионности : я применял чистую snapshot для отслеживания изменений сложного объекта там было 8 связанных таблиц и в каждой был timestamp. И я начинал snapshot транзакцию, чтобы получить данные на старт транзакции.
В RCSI там же данные на начало стэйтмета, а если этих стэйтметов много ( больше одного) ?
Для меня меня непонятно, что мы получаем, часть старых данных, часть новых. что это вообще ?
И не представляю задачи где это применимо, именно RCSI.
17 июл 12, 19:22    [12880078]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Леша777
Когда я говорю про время произошло это значит
На серверах много ядер, и все они работают параллельно. В транзакциях много команд. И если даже процедура "получить остаток" запустилась раньше, чем "джекпот" и успела прочитать старое состояние, она может быть залочена другими процессами на других таблах и в итоге прийти на клиент намного позже.

Леша777
Так я понимаю произошедшие события. Не время клиента, игрового сервера, а время первого попадания на процессор (running state).
Теплее, но всё ещё не точно, процессоров много, а вот локировка конкретной строки одна. И порядок локирования в транзакции определяет целостность данных. А то что результаты приходят в "не том" порядке на клиент - это уже неважно, главное что данные в каждом отдельном результате консистентны.

Если поменять порядок команд в транзакции, то мы можем попасть на ситуацию, что данные не такие какие должны быть, хотя с виду всё пучком.

Леша777
я применял чистую snapshot
Да, в данном случае вы можете не думать о порядке следования команд, но должны обработать ошибку изменения данных параллельными процессами.
==========================================================================================
Хочу кое-что прояснить.
Нельзя рассматриваю режимы RC или ещё что-то в чистом виде по отдельности, задачи нельзя решить на чистом RC (точнее не всякую задачу можно). Каждая часть задачи требует свой уровень изоляции. Это очень важно, а я не уделил этому должное внимание. Хотя мы слишком медленно разжёвываем простые вещи. Я толком ещё и не начал описывать.

К примеру, есть такое: Количество команд в транзакции должно быть минимально, желательно одна. Объясняется просто - внутри одного запроса, текущая полная логическая строка обработки данных работает в режиме консестивности. Одновременно держутся все локи по всем таблам. Это важно. Т.е. RC подразумевает однокомандную логику. А это положительный свойство - заставляет минимизировать время транзакции и оставить контроль данных скулю, а не прогеру.

Если команд много, то очень важен порядок и какие выстроены IL для каждой строки в каждой табле, удерживая не только изменения как одно целое, но и необходимые считанные строки. Это понятно?
Т.е. мы не должны вообще делить на "режимы" работы, мы должны обеспечить консестивность от начала транзакции до конца.
Некоторые это плохо понимают, думая что можно свободно рубить запросы на куски.

Очень важно понимать вот ещё что: мы можем расчитывать на то, как выстроены порядок команд у всех остальных кусков кода (остальная функциональность общей глобальной задачи). И можно не ставить жёсткие локи (SERIALIZABLE) расчитывая, что в другой транзакции итак не получится их изменение(!).
==========================================================================================
Леша777
В RCSI там же данные на начало стэйтмета, а если этих стэйтметов много (больше одного) ?
Для меня непонятно, что мы получаем, часть старых данных, часть новых. что это вообще ?
И не представляю задачи где это применимо, именно RCSI.
Про RCSI ничего дельного сказать рока не могу, надо переобмозговать. Но не забывайте главное: писатели блокируют писателей. Т.е. последовательность изменения можно контролировать. Но да, я не могу сейчас сказать, как работает RCSI на уровне одного запроса (для нескольких запросов проблемы теже что и у RC - это то понятно?), как обеспечивается консестивность. По мне, так при RCSI одна команда работает как полный SI, только после "окончания обрабоки" (строки или команды в целом), версии строк уже не нужны и при повторном чтении будут другие значения, только механизм не ясен. Об этом надо где-то найти.

Блин, ещё про принцип локировщика до конца не описано, а вы тут с версиями "лезете". :)

PS: Надеюсь вы понимаете, что я пишу не сколько вам лично, сколько просто формулирую, ввиде диалога, аля спектакль. :)
18 июл 12, 16:30    [12884379]     Ответить | Цитировать Сообщить модератору
 Re: непонятное поведение xlock  [new]
Леша777
Guest
На серверах много ядер, и все они работают параллельно. В транзакциях много команд. И если даже процедура "получить остаток" запустилась раньше, чем "джекпот" и успела прочитать старое состояние, она может быть залочена другими процессами на других таблах и в итоге прийти на клиент намного позже


Это понятно, попали на разные планировщики( на разные ядра). Но в waiter list, то читатели все равно попадут. Ресурс то тут один (не важно какой страница, раздел и строка) - ключ в хэш-таблице.
Все waiter-ы будут одновременно оповещены, что ресурс стал доступным.


Да, я понимаю, что может произойти такое, что запрос посланный с клиента ранее (по всеобщему времени), может получить свой квант позже ввиду загруженности очереди.
Но тут по другому и нельзя. Повезло или нет.

результаты приходят в "не том" порядке на клиент - это уже неважно

Мне совершенно неважно когда они придут клиенту.
Мне главное чтобы, запрос. которому первому посчастливилось получить или изменить данные.

Прежде чем, что-то менять или читать нужно наложить локировки (возможно подождать) а потом только читать, менять.

А тут получается я X наложил, а читатель в обход этого прочитал. Ну он же "одним глазком" по-быстрому прочитает и сразу же отстанет от строки.

Я честно до сегодняшнего дня верил в следущее :

Шаг 1 (создаем таблицу) :

CREATE TABLE dbo.PP(id INT NOT NULL PRIMARY KEY, dt datetime) 


Заполняем данными :

INSERT INTO dbo.PP(id, dt)
SELECT 1, GETDATE() 
UNION ALL 
SELECT 2, GETDATE() 


Шаг 3 : открываем REPEATABLEREAD транзакцию, но не закрываем.

BEGIN TRAN 

SELECT *
FROM dbo.PP AS p WITH(REPEATABLEREAD)
WHERE p.id = 1 


Шаг 4 : в новом окне выполняем

UPDATE p
SET p.dt = GETDATE() 
FROM dbo.PP AS p
WHERE p.id = 1 



Шаг 5 : в новом окне, пробуем читать.

SELECT *
FROM dbo.PP AS p 
WHERE p.id = 1 


И ведь на 5ом шаге данные читаются. Я свято верил, что это новое поколение ожидателей. Думал, что это шаг начнет работать когда обновление завершится.
А нет, так вот эти "зловредные" читатели монополизируют таблицу. И писатели будут долго ждать пока весь последний читатель отпустил строку.

Это по вашему как ?

По мне, то что S совметимые друг с другом не дает им право нарушать логический порядок.
Еще раз повторю, что I из ACID не нарушено (изменений нет), а логика да! Прежде чем что делать, нужно получить доступ к ресурсу. А доступ проверяется совместимость блокировок по матрице. А тут нашелся один из случаев, когда можно и так, без матрицы , оно же по-быстрому.
19 июл 12, 00:08    [12885976]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: Ctrl  назад   1 [2] 3   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить