Вход | Регистрация

  1  2   
Информационные технологии :: Математика и алгоритмы

Проблемы одновременного доступа конкурирующими транзакциями - классификация.

Проблемы одновременного доступа конкурирующими транзакциями - классификация.
Я
   gae
 
21.10.18 - 09:44
К какой проблеме (dirty read, non-repeatable read, phantom reads или др.) относится такая ситуация:

Есть два элемента данных, пусть будут в разных таблицах.
А = 1; В = 11;

Одна транзакция №1 изменяет их значения на А = 2, В = 12.

Конкурирующая транзакция №2 читает эти данные. По идее она всегда должна гарантированно прочитать только 1 и 11, или 2 и 12, то есть либо не измененные значения, либо когда они изменены вместе.

2 и 11, 1 и 12 - это некорректная комбинация.

Может получиться, что читающая транзакция №2 считывает сначала В, пока оно еще не изменено транзакцией №1 (и не заблокировано), а потом читает А, когда транзакция №1 уже завершилась. К какой проблеме по классификации этот случай относится?
 
 
   asady
 
1 - 21.10.18 - 10:10
(0) что мешает анализировать версии прочитанных объектов
и не париться с этими уровнями изоляции
   Йохохо
 
2 - 21.10.18 - 10:35
к анпредиктед бихейвиор
   DmitrO
 
3 - 21.10.18 - 12:03
Это не повторяемое чтение.
Во второй транзакции можем получить:
B=11
A=2
Пытаемся повторить чтение и получаем B=12

Если транзакция хочет получать согласованные данные, она должна стать блокировки чтения до конца транзакции. Если порядок блокирования будет совпадать с приведенным порядком чтения, то будет возможен дедлок.
   DmitrO
 
4 - 21.10.18 - 12:04
*должна ставить
С телефона пишу
   Cyberhawk
 
5 - 21.10.18 - 13:24
(3)
"Во второй транзакции можем получить:
B=11
A=2"
Если мы получили измененное А и неизмененное В, прочитав это во второй транзакции, то значит мы прочитали часть изменений от первой транзакции, а значит это и грязное чтение тоже
   gae
 
6 - 23.10.18 - 05:38
(5) Я тоже сначала думал, что грязное чтение, так как ловим промежуточное состояние по незакрытой транзакции. Но формально, если посмотреть, какой уровень изоляции защищает от этого, то получается вот что:
1) read commited - не защищает, так как читаем данные, которые транзакция №1 еще не трогала и не блокировала. Значит это не грязное чтение.
2) repeatable read - транзакция №2 заблокирует прочитанное B для изменения, и транзакция №1 не сможет его поменять, откатится, освободит исходное значение А. То есть, данный уровень защитит от неповторяемого чтения. В примерах про неповторяемое чтение обычно фигурирует повторное чтение, здесь его нет, потому может сбить с толку. Тут больше подойдет другое название эффекта "несовместимый анализ".
   Cyberhawk
 
7 - 23.10.18 - 08:22
"Значит это не грязное чтение" // Т.е. ты считаешь, что пофигу на то, что если два апдейт/инсерт-запроса находятся внутри одной транзакции, то этого недостаточно? Т.е. грязным чтение может считаться только если мы читаем данные уже _после_ начала выполнения апдейт/инсерт-запроса, правильно тебя понял?
   Cyberhawk
 
8 - 23.10.18 - 08:25
"транзакция №2 заблокирует прочитанное B для изменения, и транзакция №1 не сможет его поменять, откатится" // Почему транзакция 1 откатится, а не дождется?
   bolobol
 
9 - 23.10.18 - 09:18
Если транзакция, то А и В изменятся разом, значит, проблема в чтении.

Запрос, получающий А и В может прочитать данные вокруг транзакции?, если, например, А читается в первой виртуальной таблице, а В - в пятой.
   Cyberhawk
 
10 - 23.10.18 - 09:20
(9) "Если транзакция, то А и В изменятся разом" // Ты конечно же ошибаешься
 
 Рекламное место пустует
   gae
 
11 - 23.10.18 - 09:30
(7) Я рассуждал по такой логике: все эти эффекты сформулированы в привязке к уровням изоляции, которые их устраняют. Если уровень изоляции read commited не устраняет эффект, значит этот эффект более сложный, чем грязное чтение.

"грязным чтение может считаться только если мы читаем данные уже _после_ начала выполнения апдейт/инсерт-запроса" - да, получается так, это уже скорее следствие, исходя из того, как уровни изоляции реализация при помощи блокировок. Если записи еще не было, значит X-блокировки на этом элементе нет, его можно почитать транзакцией с уровнем read commited.
   gae
 
12 - 23.10.18 - 09:32
(8) >> Почему транзакция 1 откатится, а не дождется.
Она будет ждать завершения транзакции №2, а та в свою очередь будет ждать снятия X-блокировки с элемента А, установленного транзакцией №1. Deadlock.
   gae
 
13 - 23.10.18 - 09:34
(11) реализация -> реализуются
   Йохохо
 
14 - 23.10.18 - 09:37
(11) комиттед защищает от ролбэк, т.е. Б не увидит А вообще если у нее рид комиттед, а у Б ниже
   Cyberhawk
 
15 - 23.10.18 - 09:39
(11) Ну тогда выходит, что read committed все-таки защищает от грязного чтения
   bolobol
 
16 - 23.10.18 - 09:48
(10) Пук в лужу какой-то, или вы научились читать данные незавершённой транзакции. Поделитесь хак-ом, штолле.

Ответ же на свой вопрос нашёл такой, что ВЫБРАТЬ без ДЛЯ ИЗМЕНЕНИЯ - покажет всем запросам пакета снимок базы на старте запроса. А с ДЛЯ ИЗМЕНЕНИЯ, получается, что каждый следующий подзапрос будет видеть данные всех завершённых транзакций, может прочитать А старое и в последующих запроса уже А новое...
   gae
 
17 - 23.10.18 - 09:48
(11) Ну да, это как бы по определению. Но read committed не защищает это эффекта в (0). Значит эффект в (0) - сложнее чем грязное чтение.
repeatable read защищает, значит этот эффект в (0) - неповторяемое чтение.
   bolobol
 
18 - 23.10.18 - 09:49
* может прочитать А старое и в последующих _подзапросах_ запроса уже А новое...
   gae
 
19 - 23.10.18 - 09:49
(16) транзакции с уровнем read uncommited читают данные незавершенных транзакций
   MrStomak
 
20 - 23.10.18 - 09:51
(17)
Это неповторяющееся чтение, просто для всего набора данных, а не отдельно для А и Б, в (3) всё верно написно.
   MrStomak
 
21 - 23.10.18 - 09:51
(16) Хак выглядит так: WITH NOLOCK
Пользуйтесь.
   MrStomak
 
22 - 23.10.18 - 09:55
(16) В целом - бред какой-то написан.. ДЛЯ ИЗМЕНЕНИЯ к снимкам отношения не имеет, функционально работает ровно наоборот тому, как написано в посте. И вообще - кто еще использует автоматический режим блокировок?
   gae
 
23 - 23.10.18 - 09:57
(16) "ВЫБРАТЬ без ДЛЯ ИЗМЕНЕНИЯ" работает в режиме автоматических блокировок 1С, внутри транзакции, и пускает запросы с уровнем изоляции serializable, то есть не начинает читать данные, если на них чья-то блокировка (даже на их диапазоне), и не дает никому читать пока идет транзакция.
   MrStomak
 
24 - 23.10.18 - 10:05
(23) Нет, там не в Serializable "фича".
Serializable на любых запросах по регистрам встает в автоматических блокировках.
ДЛЯ ИЗМЕНЕНИЯ просто ставит U блокировку, т.е. другой запрос, в котором та же таблица с "ДЛЯ ИЗМЕНЕНИЯ" её прочитать не сможет. При этом обычная S блокировка с ней совместима, т.е. прочитать данные не с намерением из изменить система даст.
   Йохохо
 
25 - 23.10.18 - 10:05
(17) что за бред?
   gae
 
26 - 23.10.18 - 10:07
(25) что не так?
   gae
 
27 - 23.10.18 - 10:22
(24) Да, ты прав, там все хитрее, поизучаю еще детали.
Тут кое что есть http://catalog.mista.ru/public/621599/
   Cyberhawk
 
28 - 23.10.18 - 10:23
(16) Мальчик, ты не путай 1С и СУБД. Мы тут чисто за СУБД говорим.
   Вафель
 
29 - 23.10.18 - 10:24
есть еще ситуации добавления/удаления строк
   gae
 
30 - 23.10.18 - 10:26
(29) если добавление, то это уже phantom reads
   Йохохо
 
31 - 23.10.18 - 10:29
(26) защищает
   gae
 
32 - 23.10.18 - 10:35
(31) Если транзакция №1 уже изменила значение А, но еще не добралась до Б, и не поставила никаких блокировок на неё, то что мешает другой транзакции прочитать Б?
   Йохохо
 
33 - 23.10.18 - 10:36
(32) нет блокировок, нет коммита, для тран2 и А и Б не менялись
 
 
   gae
 
34 - 23.10.18 - 10:51
(33) Транзакция №2 прочитала исходное Б, сняла с него S-блокировку, и ждет пока освободится А, измененное транзакцией №1. Транзакция №1 меняет Б и коммитится. Транзакция №2 читает измененное А.
   Вафель
 
35 - 23.10.18 - 10:52
(32) а другая транзакция нолоск читает чтоли?
   gae
 
36 - 23.10.18 - 10:54
(35) Вторая, допустим, читает в режиме read committed. Хотя какая разница, если Б незаблокировано, хоть кто прочитает.
   bolobol
 
37 - 23.10.18 - 10:55
(28) Теперь-то точно пук в лужу? Или опять что-то скрываете? Учитесь давать ответы, например у (21), а то читаются как бессмысленные транзакции с WITH NOLOCK ))
   Cyberhawk
 
38 - 23.10.18 - 10:57
(37) Ответ в стиле "разжевать и в рот положить" - это точно не ко мне. Я даю удочку.
   bolobol
 
39 - 23.10.18 - 10:57
(21) А в чём смысл применения этого хак-а? Прочитать кто чего пытается в базу пихнуть? Это какой-то админский режим, совсем не пользовательский. Т.е. ожидать использование такого в СУБД - да ну не...
   Йохохо
 
40 - 23.10.18 - 10:57
(36) так комиттед же, комиттед, срать тран2 хотела на тран1, так понятнее?
   gae
 
41 - 23.10.18 - 11:00
(40) Если Транзакция №1 уже закоммичена, то тран 2 не срать, а читать будет А.
   Вафель
 
42 - 23.10.18 - 11:00
(36) если 2 читает рид комимитед, то она не прочитает данные незавершенной 1 ну никак. вне зависимости от блокировок
   Йохохо
 
43 - 23.10.18 - 11:01
(41) тогда 2 и 12 146%
   MrStomak
 
44 - 23.10.18 - 11:03
(39) Этот хак применяется повсеместно, в динамических списках например
   gae
 
45 - 23.10.18 - 11:03
(42) И как это реализовано? Транзакция №1 еще даже не добралась до запуска запроса с UPDATE B, как другая транзакция узнает то что B читать нельзя? По моему она свободно считает исходное B.
   Cyberhawk
 
46 - 23.10.18 - 11:05
(45) Он имел в виду "она не прочитает _измененные_ данные незавершенной 1"
   gae
 
47 - 23.10.18 - 11:05
(43) Но допустим тран2 успела прочитать исходное B, до того, как тран 1 сделала update B.
   Йохохо
 
48 - 23.10.18 - 11:06
(47) а, если про (34) то чтение будет атомарным, Т2 будет наложена блокировка на обе таблицы на время чтения и (34) невозможно
   MrStomak
 
49 - 23.10.18 - 11:06
Народ, вы не поняли сценарии возникновения проблемы.
А=1, Б = 11

Транзакция №1 поменяла данные А.
А = 2
Транзакция №2 ПРОЧИТАЛА данные Б.

Транзакция №1 поменяла данные Б
Б = 12
Транзакция №1 закомитилась

Транзакция №2 ПРОЧИТАЛА данные А.

В итоге у транзакции №2 на read comitted А = 2, Б = 11.
 
 Рекламное место пустует
   Вафель
 
50 - 23.10.18 - 11:07
(45) транзакция пишет не напрямую в таблицы, а в спепц область, а потом перносит данные в таблицы по коммиту
   Вафель
 
51 - 23.10.18 - 11:08
иначе ACID нарушается. а такого быть не может
   gae
 
52 - 23.10.18 - 11:11
(50) Это, наверное, другой подход, это версионные копии данных, а не блокировки.
Есть read commited на блокировках, а есть read commited snapshot на версиях, разная реализация изоляции.
   Вафель
 
53 - 23.10.18 - 11:12
(52) сам попробуй и увидишь
   Йохохо
 
54 - 23.10.18 - 11:14
при комиттед такое вроде сделать можно, если сделать в Тран2 типа селект А из Таб1; селект Б из Таб2. Комиттед поставит блокировку только на время селекта и между первым и вторым селектом можно закоммитить Тран1. Но если селект только один то при рид комиттед ситуация (0) невозможна
   MrStomak
 
55 - 23.10.18 - 11:18
(52) На возникновение такой ситуации не влияет принцип организации параллельности - блокировки или версии.
   Cyberhawk
 
56 - 23.10.18 - 11:19
(54) А с чего ты взял, что "селект только один"? В транзакции описанная ситуация может происходить с каким угодно временным разрывом.
   bolobol
 
57 - 23.10.18 - 11:19
(44) Динамический список не показал мне записанный документ при незавершённой транзакции, не показал и изменения в существующем документе в незавершённой транзакции. Вы вне 1С нашли или создали динамический список или вьюшку, которая показывает незафиксированные данные?? Даже не знаю, чем бы вы могли ткнуть меня, убедиться, что такое используется хоть где-то.
   gae
 
58 - 23.10.18 - 11:23
(54) Да, получается, если тран 2 построить так, чтобы одновременно на А и Б пыталась ставится блокировка, то невозможно. Правда не знаю как конкретно будет действовать СУБД, если на Б разрешено блокировку поставить, а А заблокировано...
   bolobol
 
59 - 23.10.18 - 11:23
(56) Не может. Т.к. при наличии разрыва во времени - будут поставлены блокировки. Проблем "чудака в кабине" странно рассматривать с точки зрения СУБД.
   Cool_Profi
 
60 - 23.10.18 - 11:23
(58) Дедлок будет и виктим-транзакция...
   Йохохо
 
61 - 23.10.18 - 11:25
(56) где я и что взял?
вообще (0) не подпадает под классификацию всех этих грязных и неповторяющихся т.к. они рассматривают блокировки на одной таблице. а ситуация в (0) это ошибка неконсистентных данных
(58) ждать будет, ничего в этом такого, почитай "эскалация блокировок"
   Cyberhawk
 
62 - 23.10.18 - 11:25
(59) Хз о чем ты
   Cyberhawk
 
63 - 23.10.18 - 11:26
(61) "где я и что взял?" // Я вроде даже процитировал тебя
   gae
 
64 - 23.10.18 - 11:26
(57) В 8.3 вроде динамические списки уже не показывают незафиксированные данные, а в режиме совместимости с 8.2 - легко. Вот тут демонстрируют https://курсы-по-1с.рф/news/2016-11-30-repeatable-read-vs-read-commited/
   Йохохо
 
65 - 23.10.18 - 11:27
(63) про тебя с утра непонятно ты уже или еще)
   Cyberhawk
 
66 - 23.10.18 - 11:28
(65) Непонятно из такого сообщения, все ли ответы на твои вопросы тебе ясны или что-то осталось непонятным
   gae
 
67 - 23.10.18 - 11:31
(61) >>не подпадает под классификацию всех этих грязных и неповторяющихся т.к. они рассматривают блокировки на одной таблице.

Я вот в этом не уверен.
   Йохохо
 
68 - 23.10.18 - 11:34
(67) правильность данных проверяет кто то, но не СУБД, значит не подпадают
   gae
 
69 - 23.10.18 - 11:41
(68) Ну не совсем, правильность должна обеспечиться транзакциями, главное их изолировать друг от друга, чтобы одна не прочитала промежуточный результат другой.
   Йохохо
 
70 - 23.10.18 - 11:45
(69) где то есть граница между субд и логикой приложения, и реализация ситуации в (0) по мне так уровня приложения, данные то независимые
   gae
 
71 - 23.10.18 - 11:49
(70) Приложение должно запустить нужные транзакции с нужным уровнем изоляции, это да. Но раз речь про уровни изоляции, то и про эффекты можно говорить смело.
   MrStomak
 
72 - 23.10.18 - 11:51
(57) Все нетранзакционные запросы к СУБД на MS SQL в режимах совместимости до 8.3 идут с хинтом NOLOCK. Потому что без него списки бы "висели" на блокировках.
Когда в MS SQL добавили версионный read committed(snapshot), от этого получилось уйти.

При работе отчетов и списков на любом "блокировочнике" разработчик вынужден использовать грязное чтение.
   bolobol
 
73 - 23.10.18 - 11:51
(64) Точно! Это ж как раз тот самый случай, когда изначально промахнулись с блокировками данных и расширили возможности платформы (ускорили или вообще к работоспособному состоянию привели) именно хак-ом: прочитаем, конечно, но это не точно, да и смысл - всё равно на записи отвалимся. Чего ещё можно было от 1С ожидать? ))
   MrStomak
 
74 - 23.10.18 - 11:52
(73)
Никто не "лоханулся". Это ограничения блокировочных СУБД - им неоткуда тебе взять "незакомиченную" версию для показа.
   bolobol
 
75 - 23.10.18 - 11:54
(72) Да не может быть, чтоб Постгри разработало механизм быстрее эмэсскуля! Тогда - беру свои слова про "1С" обратно. Всё, оказывается, совсем не просто было.
   Йохохо
 
76 - 23.10.18 - 11:56
(71) в этом случае оно должно озаботиться блокировками, чтобы показать субд что для приложения данные связаны, иначе ошибки нет и так это и должно быть, а что там в приложении дела семейные
   gae
 
77 - 23.10.18 - 12:01
(76) Получается есть два варианта решение проблемы согласованности данных приложением: либо сделать нужные уровни изоляции транзакций в СУБД, либо обеспечить свои собственные блокировки (как в 1С свой менеджер управляемых блокировок).
   MrStomak
 
78 - 23.10.18 - 12:03
(77) Решение проблемы только в слое блокировок 1С. Менять уровень изоляции транзакций в базе 1С - нарушение лицензионного соглашения. И глупо.
   gae
 
79 - 23.10.18 - 12:04
(78) С 1С понятно, мы пытаемся в целом теоретически осмыслить.
   gae
 
80 - 23.10.18 - 12:05
Есть еще в СУБД триггеры, но я в этом не разбираюсь.
   MrStomak
 
81 - 23.10.18 - 12:09
(75) Постгре сразу по идеологии был версионником, как и Оракл. MS SQL и IBM по идеологии - блокировочники.
У них изначально разный подход - каким способом технически изолировать транзакции. В блокировочнике ты всегда получаешь актуальные данные, но вынужден ожидать. В версионнике ты не ждешь, но данные получаешь не актуальные. Очевидно, что для разных задач подходят разные решения.
   gae
 
82 - 23.10.18 - 12:09
(76) А приложение может напрямую управлять блокировками СУБД?
   Вафель
 
83 - 23.10.18 - 12:10
(82) хинты запрсов
   MrStomak
 
84 - 23.10.18 - 12:10
(80) А что там разбираться? То же самое, что подписка на событие.
   gae
 
85 - 23.10.18 - 12:11
(83) Это некое косвенное управление, по моему, через задания уровня изоляции.
   MrStomak
 
86 - 23.10.18 - 12:12
(85) Хинты даются конкретно на таблицу, очень даже напрямую
   Tonik992
 
87 - 23.10.18 - 12:23
(34)  Полагаю, что прежде, чем получить доступ к каким-то данным, СУБД обращается к диспетчеру блокировок. Диспетчер блокировок уже либо предоставляет блокировку, либо ставит в очередь.
В 1С установленная блокировка держится до конца транзакции.

Полная цитата из docs.microsoft

Приложения обычно не запрашивают блокировку напрямую. За управление блокировками отвечает внутренний компонент Компонент SQL Server Database Engine, называемый диспетчером блокировок. Когда экземпляр компонента Компонент SQL Server Database Engine обрабатывает инструкцию Transact-SQL, обработчик запросов компонента Компонент SQL Server Database Engine определяет, к каким ресурсам требуется доступ. Обработчик запросов определяет, какие типы блокировок требуются для защиты каждого ресурса, в зависимости от типа доступа и уровня изоляции транзакции. Затем обработчик запросов запрашивает соответствующую блокировку у диспетчера блокировок. Диспетчер блокировок предоставляет блокировку, если она не противоречит блокировкам, удерживаемым другими транзакциями.

Теперь сопоставьте всё это.

(49) - Неправильно, у транзакции 2 значение А не получиться считать новое, т.к. транзакция 1 еще не закончилась и не закоммичена, таким образом будет считано значение 1
   Йохохо
 
88 - 23.10.18 - 12:24
(86) но диапазон установить нельзя, он будет вычислен потом из where. А по площадям лупить нехорошо
Получило приложение неожиданные несвязанные данные ну и ССЗБ
   Tonik992
 
89 - 23.10.18 - 12:24
(49) Пардон, у вас всё верно -)
И кстате в этом случае никаких проблем то собственно и нет.
Если такой вариант кажется недопустимым, значит надо накладывать X блокировки на всё данные
   gae
 
90 - 23.10.18 - 12:48
(89) Достаточно вроде S блокировки на Б до конца транзакции №2.
   Tonik992
 
91 - 23.10.18 - 12:54
(90) Несовсем. Если S, то:
В случае с (49) у транзакции 2 не возникнет ожидания на блокировке при чтении значения Б, и тогда в этой транзакции будет получено новое значение А.

Если будет установлена для транзакции 1 X блокировки на А и на Б, тогда транзакция 2 будет ждать.
   gae
 
92 - 23.10.18 - 12:59
(91) Я имею ввиду транзакция №2 после чтения Б должна поставить S блокировку на Б до своего конца, тогда Транзакция №1 не сможет поменять Б и они обе отвалятся, но неверного результата не получится.
   Tonik992
 
93 - 23.10.18 - 12:59
(90) Ну все зависит от того, какое правило нужно в данном конкретном случае.

Если вы допускаете того, что у транзакции 2 будет новое значение, тогда S блокировка для транзакции 1.

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

А можете реальный пример из жизни?
   Tonik992
 
94 - 23.10.18 - 13:01
(92) Почему отвалятся? Возникнет ожидание на блокировках.
Как только S блокировка у транзакции 2 будет снята, транзакция 1 продолжит свою работу
   gae
 
95 - 23.10.18 - 13:06
(94) Если транзакция №2 ставит такую S блокировку, то она в режиме  repeatable read, а значит будет ждать освобождения А, которое заблокировано транзакцией 1. Дедлок.
   gae
 
96 - 23.10.18 - 13:10
(93) Пример у меня пока теоретический, но начиналось все с того, что я в 1С 8.2 при чтении остатков в транзакции при в режиме упр. блокировок словил чтение из таблицы итогов и таблицы записей, когда итоги уже изменены, а записи еще нет (или наоборот).
   Tonik992
 
97 - 23.10.18 - 13:12
(95) Вы не сможете установить S блокировку на те данные, где установлена X блокировка. Это несовместимые блокировки.
   gae
 
98 - 23.10.18 - 13:17
(97) Но на Б к этому моменту не будет еще никакой блокировки, Транзакция №1 до неё не добралась еще.
   Tonik992
 
99 - 23.10.18 - 13:22
(98) Распишите еще раз на оси времени, какая в вашем случае последовательность изменения/чтения и установки блокировки для транзакций 1 и 2.
А то мне кажется, что я об одном, а вы о другом.
   gae
 
100 - 23.10.18 - 13:28
(99) На основе того, что в (49), только если ставим уровень repeatable read:

А=1, Б = 11

Транзакция №1 поменяла данные А.
А = 2 (ставит Х на А до конца Тр1)

Транзакция №2 ПРОЧИТАЛА данные Б. (ставит S на Б до конца Тр2)

Транзакция №1 пробует менять данные Б
[Б на 12] (ожидание на блокировке)

Транзакция №2 пробует читать данные А.(ожидание на блокировке)
  1  2   

Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Рекламное место пустует