Имя: Пароль:
1C
1С v8
Объяснение по уровню изоляции READ COMMITED с ИТС
0 gae
 
19.10.18
13:24
Читаю на ИТС статью по блокировкам.

https://its.1c.eu/db/metod8dev#content:5839:hdoc

Там написано:

READ COMMITED -  обеспечивает запрет «грязного» чтения. Если моя транзакция начала изменять данные, то конкурирующая транзакция не может не только измененить, но даже прочитать их до завершения моих изменений. После того, как мои изменения закончены, конкурирующие транзакции могут читать данные, не дожидаясь окончания моей транзакции в целом. Таким образом решается проблема неповторяемого чтения.

Вот это "могут читать данные, не дожидаясь окончания моей транзакции в целом" я не понял, как это могут читать данные, а если записывающая транзакция откатится? Грязное чтение это же если читаются измененные данные, но записывающая транзакция потом откатывается. Я что-то не так понял?
1 Вафель
 
19.10.18
13:25
так "не могут же"
2 gae
 
19.10.18
13:33
(1) где?
3 gae
 
19.10.18
13:36
И не понял слова "Таким образом решается проблема неповторяемого чтения. " причем тут неповторяемое чтение, если оно при данном уровне изоляции (READ COMMITED) как раз может быть?
4 Йохохо
 
19.10.18
14:00
(3) для этой транзакции не может
5 yavasya
 
19.10.18
14:10
(0) ты читать можешь только свои транзакции
6 stopa85
 
19.10.18
14:12
Вот не готов сказать, что это правильно. Но ведь вроде так:

для блокировочника (MS SQL Server) не могут читать данные, которые были изменены еще пока не зафиксированной транзакцией. Для версионника - могут, но увидят последнюю подтвержденную версию

Главное в READ COMMITED не допусть грязного чтения. Все остальное там может быть.
7 mistеr
 
19.10.18
14:17
(0) READ COMMITED нужно понимать как "можно прочитать только закоммиченные данные". Соответственно незакоммиченные нельзя.

P.S. Фраза "не дожидаясь окончания моей транзакции в целом" конечно вводит в заблуждение. Нужно исправить.
8 gae
 
19.10.18
14:21
(6)(7) Спасибо, а то я не мог понять, то ли я дурак, то ли фигня написана.
9 gae
 
19.10.18
14:21
(5) Я не понимаю что значит "читать свои транзакции". Читают вроде как данные.
10 yavasya
 
19.10.18
14:25
(9) что ты не можешь понять? у тебя при проведении документа происходит постепенное наполнение регистров , и ты постепенно их читаешь хотя транзакция не завершена. Может быть это потому что 1С не поддерживает вложенные транзакции ?
11 yavasya
 
19.10.18
14:26
(9) ты слышал о методике проверки отрицательных остатков ? записал регистр и в этой же транзакции его читаешь и проверяешь на отрицательные остатки, хотя транзакция еще не завершилась
12 mistеr
 
19.10.18
14:27
(10) В (0) идет речь о чтении конкурирующими транзакциями. Отсюда и путаница.
13 yavasya
 
19.10.18
14:28
(12) что такое конкурирующая транзакция? не знал, расскажи пж
14 Cool_Profi
 
19.10.18
14:29
СТоп, а если транзакция (вторая) у меня с NOLOCK - я же могу прочитать данные из первой?
15 gae
 
19.10.18
14:29
(10) Теперь ясно, что ты имел ввиду: в транзакции читаем данные, измененные этой транзакцией.
Просто в (0) действительно, говорится о чтении конкурирующими транзакциями.

(13) Другая транзакция, которая выполняется одновременно с первой.
16 mistеr
 
19.10.18
14:31
(14) Да, но это уже не READ COMMITED.
17 Cool_Profi
 
19.10.18
14:32
(16) Но первая-то в ридкоммитед?*
18 gae
 
19.10.18
14:32
(14) Вроде как да, вот другое объяснение READ COMMITED для блокирвоочников (Википедия):

"Заключается в том, что пишущая транзакция блокирует изменяемые данные для читающих транзакций, работающих на уровне read committed или более высоком, до своего завершения, препятствуя, таким образом, «грязному» чтению, а данные, блокируемые читающей транзакцией, освобождаются сразу после завершения операции SELECT (таким образом, ситуация «неповторяющегося чтения» может возникать на данном уровне изоляции)."

То есть вторые транзакции с более низкими уровнями изоляций игнорируют эти блокировки.
19 mistеr
 
19.10.18
14:36
(17) READ COMMITED относится к тому, кто читает.
20 gae
 
19.10.18
14:40
(19) Ну я так понял, что у каждой транзакции есть свой уровень изоляции. И этот уровень изоляции определяет, какие эффекты (деффекты - грязное чтение, непвторяющееся чтение и т.п.) могут возникнуть в этой конкретной транзакции. Правильно?
21 gae
 
19.10.18
14:43
Вот еще текст:
-----
Уровень изоляции READ COMMITTED

Как уже упоминалось, уровень READ COMMITTED имеет две формы. Первая форма применяется в пессимистической модели одновременного конкурентного доступа, а вторая - в оптимистической. В этом разделе рассматривается первая форма этого уровня изоляции.

Транзакция, которая читает строку и использует уровень изоляции READ COMMITTED, выполнят проверку только на наличие монопольной блокировки для данной строки. Если такая блокировка отсутствует, транзакция извлекает строку. (Это выполняется с использованием разделяемой блокировки.) Таким образом предотвращается чтение транзакцией данных, которые не были подтверждены и которые могут быть позже отменены. После того, как данные были прочитаны, их можно изменять другими транзакциями.

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

Тут говорится о том, что вторая читающая транзакция с уровнем READ COMMITTED при чтение ставит разделяемые блокировки и сразу же их снимает, до завершения транзакции. В тексте на ИТС это как то трансформировалось в
"После того, как мои изменения закончены, конкурирующие транзакции могут читать данные, не дожидаясь окончания моей транзакции в целом".
Ну или  я вообще не понимаю о чем они.
22 Йохохо
 
19.10.18
15:05
(20) просто пойми что грязное чтение имеется ввиду внутри одной одной транзакции, две независимых транзакции могут получить разные данные, от этого коммитед не защищает
23 Вафель
 
19.10.18
15:37
MSSQl в 8.3 уже далеко не блокировочник
24 Cool_Profi
 
19.10.18
15:59
(23) Далеко, если включать опции
25 Cyberhawk
 
19.10.18
16:30
(24) Какие опции? Режим совместимости конфигурации
26 Фрэнки
 
19.10.18
16:31
похоже, что некоторые читатели путают смысл между получением данным для отчета и получением данных в "читающей транзакции". В отчете (в большинстве случаев) просто нет смысла создавать транзакцию для получения данных
27 Вафель
 
19.10.18
16:33
(24) 8.3 сам включает
28 Вафель
 
19.10.18
16:33
(26) отчеты тоже не читают незавершенные транзакции
29 Cyberhawk
 
19.10.18
16:39
(3) Почему ты считаешь, что может быть неповторяемое чтение? Напиши сценарий, при котором тебе это кажется возможным.
Сценарий с пронумерованными пунктами.
30 Фрэнки
 
19.10.18
16:44
(28) тогда о чем тут дискутировать?
31 Cyberhawk
 
19.10.18
16:50
(7) Зачем какую-то фразу убирать, если она в точности отражает то, что происходит?
32 gae
 
19.10.18
17:23
(29) Я считаю, потому что, там же, ниже:
"REPEATABLE READ - обеспечивает повторяемость чтения данных. Если моя транзакция начинает читать данные, то другая транзакция не может их изменить до окончания моей транзакции."
А READ COMMITED не обеспечивает.
33 Йохохо
 
19.10.18
17:30
(32) потому и не обеспечивает что комиттет защищает только от роллбэк
34 gae
 
19.10.18
17:33
(33) Я тоже так думаю, но в (29) намекают что не может быть неповторяемого чтения при READ COMMITED, и фраза с ИТС "Таким образом решается проблема неповторяемого чтения" верна.
35 Йохохо
 
19.10.18
17:55
36 Вафель
 
19.10.18
17:59
REPEATABLE READ - это блокировка чтения от изменения
37 mistеr
 
19.10.18
19:51
(31) Нет, она вводит в заблуждение.
38 Cyberhawk
 
19.10.18
20:51
(37) Что-то ты повторяешься.
Я вроде бы довольно ясно указал, что фраза в точности соответствует действительности.
В чем заблуждение?
39 Cyberhawk
 
19.10.18
20:54
(32) Вроде Я довольно ясно указал, что от тебя нужен сценарий, при котором на твой взгляд проблема неповторяемого чтения будет наблюдается при указанном в статье уровне изоляции транзакций.
Ты в ответ приводишь что-то совершенно не то, видимо надеясь, что это прокатит, но это не так.
40 Йохохо
 
19.10.18
20:59
(39) 66 лет, старый пердун
41 gae
 
19.10.18
21:04
(39) Я попытаюсь:

1. Транзакция 2

SELECT f2 FROM tbl1 WHERE f1=1;

2. Транзакция 1                           
UPDATE tbl1 SET f2=f2+1 WHERE f1=1;     
COMMIT;

3. Транзакция 2     
SELECT f2 FROM tbl1 WHERE f1=1;

В транзакции 2 выбирается значение поля f2, затем в транзакции 1 изменяется значение поля f2. При повторной попытке выбора значения из поля f2 в транзакции 2 будет получен другой результат.
42 Cyberhawk
 
19.10.18
21:54
(41) Ясно. Просто ты не учитываешь, что в том примере-кусочке статьи речь только об уровнях изоляции СУБД, а в 1С поверх этого работает еще и свой менеджер блокировок.

В общем, вердикт следующий:
1. На ИТС ошибка в утверждении "решается проблема".
Смех в том, что на ТВКВ та же статья о блокировках имеет правильный текст и там написано "Таким образом существует проблема неповторяемого чтения".
2. Товарищу gae плюсик за внимательное чтение ИТС.
3. От товарища mistеr по-прежнему ожидаю разъяснения, в чем там по его мнению заблуждение в части выделенной ранее фразы "не дожидаясь окончания моей транзакции в целом".

Могу заранее оппонировать, т.е. разъяснить (чтоб дважды не вставать), что:
- на ИТС в приведенном фрагменте речь о блокировках СУБД, а не блокировках 1С
- при READ COMMITED блокировка СУБД на запрет изменения другими транзакциями накладывается только до конца выполнения читающего _запроса_, а не до конца всей нашей транзакции
- из указанных двух пунктов следует, что в том примере после выполнения читающего запроса в транзакции мы в этой своей транзакции что угодно там еще можем потом кодом делать (писать движения, например) и это уже никак не будет мешать другим транзакциям читать и даже изменять то же самое, что полностью и соответствует написанному "конкурирующие транзакции могут читать данные, не дожидаясь окончания моей транзакции в целом"
- очевидно, что эта "особенность" СУБД для режима READ COMMITED не спасает нас от проблемы повторяемого чтения и поэтому в игру-то и вступает менеджер блокировок 1С (мы перед читающим запросом накладываем исключительную блокировку) - профит
43 gae
 
19.10.18
22:03
(42) Я и разбирался с уровнями изоляции в СУБД.

Кстати, есть и книга "От 8.0. к 8.1", там похожий текст, и последнее  приложение абзаца про READ COMMITED такое: "Таким образом, существует проблема неповторяемого чтения".

Как они на ИТС так накосячили...
44 gae
 
19.10.18
22:12
Но по предложению "После того, как мои изменения закончены, конкурирующие транзакции могут читать данные, не дожидаясь окончания моей транзакции в целом." я пока ничего не понял.
45 palsergeich
 
19.10.18
22:16
46 ssh2006
 
19.10.18
23:05
(42) +1
в автоматическом режиме был REPEATABLE READ и повторяемое чтение
47 Cyberhawk
 
20.10.18
08:13
(44) Вроде Я довольно понятно разъяснил это в своем предыдущем посте
48 Йохохо
 
20.10.18
09:08
(44) уровень изоляции транзакции это балансировка при решении одновременно двух проблем, 1 консистентность данных в транзакции, 2 снижение конкуренции ака максимальная многопоточность
49 gae
 
20.10.18
09:17
>> - из указанных двух пунктов следует, что в том примере после выполнения читающего запроса в транзакции мы в этой своей транзакции что угодно там еще можем потом кодом делать (писать движения, например) и это уже никак не будет мешать другим транзакциям читать и даже изменять то же самое, что полностью и соответствует написанному "конкурирующие транзакции могут читать данные, не дожидаясь окончания моей транзакции в целом"

Мое понимание такое: Если запрос с уровнем READ COMMITED читает данные, то он ставит разделяемую блокировку и после чтения сразу её снимает (до окончания транзакции). То есть другие запросы могут изменить эти данные, и про повторном чтении они могут оказаться другими. То есть получаем эффект неповторяемого чтения.
Это эквивалент того что ты написал. Речь про чтение.

Если запрос с уровнем READ COMMITED записывает данные, то он ставит эксклюзивную блокировку на измененные данные до конца транзакции, и другая транзакция с уровнем не ниже READ COMMITED видит эти блокировки и не может прочитать измененные данные до конца записывающей транзакции. Таким образом, вторая транзакция не может сделать dirty read.

В тексте на ИТС же написано как-то противоречиво:

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

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

Поправьте меня, если я не прав.
50 gae
 
20.10.18
09:20
(49) к (42)
51 Cyberhawk
 
20.10.18
10:01
"Мое понимание такое ... Речь про чтение" // Тут все правильно
А вот про запись ты походу просто считаешь, что "изменения закончены" = "окончание транзакции", а это (в мире СУБД) может быть не так. В общем случае начало и окончание "физического" изменения данных (на каких-нибудь там страницах памяти в СУБД) могут не совпадать с началом и окончанием транзакции. Речь на ИТС только об этом.
Т.е. пока СУБД что-то там шуршит в UPDATE-запросе (первая транзакция), конкурирующие транзакции встают в очередь на чтение, но _не до конца первой транзакции_. Как только UPDATE-запрос в СУБД завершен, остальные транзакции могут спокойно данные считывать и изменять.
52 rsv
 
20.10.18
10:29
(0) качните експресс скуль
    По умолчанию походу там 2 й уровень.
    Begin tran   и ваш пример на update
     во втором окне пример на select..он будет ждать
53 gae
 
20.10.18
10:46
(51)
>> просто считаешь, что "изменения закончены" = "окончание транзакции"
Нет, так не считаю.

>>Как только UPDATE-запрос в СУБД завершен, остальные транзакции могут спокойно данные считывать и изменять.

То есть, если транзакция с UPDATE-запросом потом откатится, то те транзакции, что прочитали апдейтнутые данные, получат "грязное чтение". От чего же тогда READ COMMITED защищает?

Или имелось ввиду то, что остальные транзакции могут какие-то совсем иные данные читать и изменять? Но это и так понятно.
54 gae
 
20.10.18
10:47
(52) будет ждать ... до окончания первой транзакции же?
55 Йохохо
 
20.10.18
10:51
(49) "Если запрос с уровнем READ COMMITED читает данные, то он ставит разделяемую блокировку" "Если запрос с уровнем READ COMMITED записывает данные, то он ставит эксклюзивную блокировку" яснопонятно
56 ssh2006
 
20.10.18
13:52
(54) READ COMMITTED
Указывает, что инструкции не могут считывать данные, которые были изменены другими транзакциями, но еще не были зафиксированы. Это предотвращает чтение«грязных» данных.
https://docs.microsoft.com/ru-ru/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-2017

При чтении будет либо ожидание на блокировке , либо будет получена версия данных до начала незафиксированной параллельной транзакции (PostgreSQL , MS SQL + 8.3 (READ_COMMITTED_SNAPSHOT ON))

Как тогда получить например корректные остатки для проверки при проведении?

Пример - сначала контроль остатков, потом их изменение:

Допустим параллельно проводится документ, данные записаны, но транзакция еще не зафиксирована. При записи платформа автоматически накладывает исключительную управляемую блокировку до конца транзакции. В своем менеджере блокировок на сервере 1С.

Поэтому перед читающим контрольным запросом нужно самому наложить исключительную упр. блокировку. Тогда чтения будет ожидать фиксации параллельной транзакции. И плюс не возникнет дедлока.
57 ssh2006
 
20.10.18
13:56
Поэтому перед читающим контрольным запросом нужно самому наложить исключительную упр. блокировку. - т.е. Заблокировать() будет ждать пока не завершиться параллельное проведение и после этого уже будет установлена блокировка и прочитаны остатки. И эта упр. блокировка с другой стороны гарантирует их неизменность до конца транзакции
58 Cyberhawk
 
20.10.18
16:07
(53) Нет, другие транзации, читающие с READ COMMITED, конечно же не смогут прочитать результат апдейта до конца транзакции (коммита)
59 Cyberhawk
 
20.10.18
16:10
+(58) Так что, на твой вопрос "От чего же тогда READ COMMITED защищает?" ответ - таки защищает от грязного чтения
60 Cyberhawk
 
20.10.18
16:13
Автору почему-то сложно понять, что чисто на уровне СУБД READ COMMITTED для 1С не может работать, т.к. если бы это было так, что был бы полный ахтунг. Поэтому-то READ COMMITTED _только в паре_ с менеджером блокировок 1С работает (разрабочтик сам ставит упр. блокировку где надо, которая и исключает неповторяемое чтение другими _1С-ными_ транзакциями)
61 gae
 
20.10.18
16:37
(60) Я вообще пока не рассматривал 1С, а чисто SQL.
Я в курсе, что корректность данных при использовании управляемых блокировок в 1С должен обеспечить менеджер блокировок 1С и разработчик.

Вопрос был изначально про то, является ли текст на ИТС про уровни изоляции транзакций MSSQL, в частности предложение "После того, как мои изменения закончены, конкурирующие транзакции могут читать данные, не дожидаясь окончания моей транзакции в целом.", корректным.

Конкурирующие транзакции с READ COMMITTED не могут читать заблокированные данные, измененные другой транзакцией, до её завершения. Поэтому я считаю это предложение некорректным.
62 Cyberhawk
 
20.10.18
17:59
Теперь вроде наконец-то понял, о чем ты!
Да, согласен, что под "конкурирующие транзакции" по идее должны иметься в виду транзакции с той же изоляцией, о которой речь идет в этом абзаце (в статье ИТС), и тогда предложение однозначно неверное.

Касательно Х до конца транзакции при любом уровне пессимистической изоляции - да, в англоязычной доке это подтверждается. Выходит, что в (51) Я был не прав про снятие блокировки после выполнения апдейта, но до коммита, а значит ветка оказалась полезной :)

Единственная лазейка для писателя этого текста на ИТС может состоять в том, что он мог иметь в виду под "конкурирующими транзакциями" те, что с хинтом NOLOCK / READUNCOMMITTED.
63 gae
 
21.10.18
09:16
Всем спасибо за обсуждение!
Оптимист верит, что мы живем в лучшем из миров. Пессимист боится, что так оно и есть.