|
Как правильно разруливать такие ситуации (грязное чтение) | ☑ | ||
---|---|---|---|---|
0
degot
04.11.14
✎
12:38
|
Предположим есть такая ситуация : есть какие-то документы, которые проводятся длительное время. И есть процесс , в котором делаются запросы к таблице данного вида документов. Результат запроса обрабатывается, создаются объекты базы данных со ссылкой на на те самые документы.
Но бывают ситуации когда документ в итоге не проведется, в итоге объекты получаются с битыми ссылками на документы . В общем как правильно обрабатывать такие ситуации? Как исключить из запроса доки, по которым транзакция не завершена? Спасибо платформа 8.2, управляемый режим блокировок, sql 2012 |
|||
1
Bober
04.11.14
✎
12:41
|
(0) перед выполнение запроса НачатьТранзакцию(), после выполнения ОтменитьТранзакцию().
|
|||
2
Armando
04.11.14
✎
12:49
|
||||
3
Armando
04.11.14
✎
12:58
|
Можно перед тем как выполнится это "создаются объекты базы данных со ссылкой на на те самые документы." накладывать исключительную блокировку на документ. Если не заблокировалось, значит с документом что-то происходит.
|
|||
4
herfis
04.11.14
✎
13:20
|
(0) Если именно "исключить из запроса доки, по которым транзакция не завершена", тогда (1) - чтение в транзакции READ COMMITTED, а не "грязное".
|
|||
5
Armando
04.11.14
✎
13:23
|
Кстати на 8.3 эту проблему вроде решили
|
|||
6
AlexITGround
04.11.14
✎
13:25
|
(4) мсье, не ругайтесь такими словами, ТС-а может спугнуть такой внезапный тон
|
|||
7
floody
04.11.14
✎
14:06
|
(1) прав, в 1С грязное чтение только вне транзакции. все, что в транзакции (явной или неявной) - это уже минимум read committed
|
|||
8
floody
04.11.14
✎
14:08
|
(0) если у вас какой-то документ проводится - это значит что он уже записан
причем тут битые ссылки? битые образуются, если документ удалить без контроля ссылочной целостности |
|||
9
Armando
04.11.14
✎
14:11
|
(8) Может там при проведении Отказ = Истина
|
|||
10
Web00001
04.11.14
✎
14:29
|
(9)дык это же все равно, документ то есть, а проведен он или нет, это дело уже 10е.
|
|||
11
Armando
04.11.14
✎
14:35
|
(10) Создай новый документ, в при записи или обработке проведения сделай отказ, и попробуй провести его. Он у тебя не проведется и не запишется. Ну то есть в момент проведения ссыль будет, отказ заставит откатить транзакцию, и ссылки не станет.
|
|||
12
vi0
04.11.14
✎
15:05
|
(0) расскажи что за задачу решаешь
зачем "исключить из запроса доки, по которым транзакция не завершена"? ты их потом будешь отдельно обрабатывать? эти документы по которым транзакция уже будет завершена |
|||
13
floody
04.11.14
✎
15:17
|
(11) это верно в том случае, если вы создали документ и записываете его программно с режимом "проведение"
в конфигурациях обычно у пользователя документ сначала записывается, потом уже проводится |
|||
14
Armando
04.11.14
✎
15:21
|
(13) "конфигурациях обычно у пользователя документ сначала записывается, потом уже проводится"
проверить не желаешь? |
|||
15
herfis
04.11.14
✎
16:05
|
(13) Чушь какая-то. Проведение на 8-ке всегда было частью транзакции записи. Или появились быдло-типовые, где проведение нового документа разбито на две транзакции?
|
|||
16
degot
04.11.14
✎
16:34
|
(12) да, они обработаются следующим заходом
|
|||
17
Обработка
04.11.14
✎
16:39
|
(0)
В запросе у вас должно быть проверка "ссылка.проведен". Если документ записан но не проведен тогда не попадет в ваш запрос. А если уж поапл тогда значит документ уже провелся. Если документ перепроводится эо уже другой случай. |
|||
18
Зеленый пень
04.11.14
✎
16:51
|
(0) "Результат запроса обрабатывается, создаются объекты базы данных со ссылкой на на те самые документы." - в этот момент накладывать блокировку на документы из запроса, если удалось - всё ок.
|
|||
19
vi0
04.11.14
✎
17:02
|
(18) не, если ТС говорит про битые ссылки на документы, значит достаточно запрос делать в транзации - запрос не увидит эти документы т.к. чтение не будет грязным
|
|||
20
tridog
04.11.14
✎
18:10
|
(17) Если документ проведен, но транзакция еще не зафиксирована - то при грязном чтении параллельный сеанс вполне себе прочитает незафиксированное состояние через условие вида "Ссылка.Проведен".
Ваш совет ничем не отличается от исходной ситуации в (0). Единственный (и правильный) вариант избежать подобного - получить при чтении уровень изоляции, при котором не будет чтения изменений незафиксированных транзакций. Как уже писали Выше - самый простой вариант - это выполнять чтение в транзакции, тем самым получив в СУБД уровень изоляции Read committed. Вообще говоря, для современных конфигураций (управляемые блокировки, режим совместимости 8.3 и т.д.) - уже сложно найти причины, которые бы делали чтение вне транзакции обоснованным. |
|||
21
vi0
04.11.14
✎
18:22
|
> выполнять чтение в транзакции, тем самым получив в СУБД уровень изоляции Read committed.
у него управляемые блокировки, поэтому до субд не дойдет > уже сложно найти причины, которые бы делали чтение вне транзакции обоснованным. отчеты, по прежнему, логично выполнять вне транзакции |
|||
22
tridog
04.11.14
✎
18:44
|
(21) > у него управляемые блокировки, поэтому до субд не дойдет
Мы говорим про уровень изоляции при чтении. Чтение до СУБД дойдет в любом случае (вместе с уровнем изоляции). Управляемые блокировки этому не помешают. > отчеты, по прежнему, логично выполнять вне транзакции Ну они действительно так и формируются на текущей платформе. А какие от этого плюсы? |
|||
23
vi0
04.11.14
✎
19:22
|
(22) почему не помешают?
Про плюсы. Транзакции всегда ипользуют ресурсы и задействовать их есть смысл, когда будет реальная необходимость |
|||
24
Armando
04.11.14
✎
19:40
|
Вот в тему про 8.3:
http://downloads.v8.1c.ru/content//Platform/8_3_5_1248/1cv8upd.htm#4cc794a4-7d56-11e1-b5d1-e61f135f174b Как было: Microsoft SQL Server 2005 и выше использовался в режиме блокировок. Использовался уровень изоляции транзакций READ_COMMITED. При чтении вне транзакций использовалось «грязное» чтение. Как стало: При работе с Microsoft SQL Server версии 2005 и выше, используется режим управления версиями строк, если конфигурация использует режим управляемых блокировок. Используется уровень изоляции транзакций READ_COMMITED_SNAPSHOT. При чтении данных вне транзакций используется согласованное чтение. Реализованные изменения приводят: К уменьшению блокировок и взаимоблокировок при выполнении запросов, работающих в транзакции; Исчезновению ошибок при выполнении запросов вне транзакции над часто модифицируемыми прикладными объектами; Получению согласованных результатов отчета вне транзакции на момент выполнения отчета. |
|||
25
tridog
04.11.14
✎
19:45
|
(23) Потому что собственный менеджер блокировок внутри платформы не может влиять на то, как СУБД читает данные.
|
|||
26
vi0
04.11.14
✎
19:50
|
(25) я говорил, что упр блокировки работать будут и при чтении, и блокировки субд тут вторичны
|
|||
27
tridog
04.11.14
✎
20:06
|
(26) Мне кажется, что Вы несколько не до конца разобрались с тем, что такое управляемые блокировки.
Могу прокомментировать Ваше высказывание так: 1. При выполнении запросов управляемые блокировки сами по себе не устанавливаются. Вообще :) Чтобы бы устанавливались управляемые блокировки при чтении - нужно либо устанавливать их из встроенного языка (объект БлокировкаДанных), либо выполнять чтение не через запросы, а через объектную технику (РегистрСведенийМенеджерЗаписи и т.д.). 2. При чтении вне транзакции управляемые блокировки вообще не могут устанавливаться - можно проверить через объект БлокировкаДанных и техжурнал по событию TLOCK. Кстати в офф. документации (а не на "сленге") они называются транзакционными блокировками, а не управляемыми. 3. Использование управляемых блокировок не отменяет блокировок в СУБД, и неправильно считать, что блокировки СУБД вторичны. Например, даже при использовании управляемых блокировок реальны ситуации избыточных блокировок в СУБД - по-максимуму такие ситуации исключены в 8.3 без режима совместимости, как тут уже выше писали. 4. То, "прочитаются" ли запросом данные параллельных незафиксированных транзакций вообще никак не зависит от блокировок! Ни от блокировок в СУБД, ни тем более, от управляемых блокировок. А зависит только от уровня изоляции транзакций, которым мы можем управлять только неявно. Что автору и было посоветовано - в виде выполнения запроса в транзакции. |
|||
28
vi0
04.11.14
✎
22:28
|
1. согласен
2. 3. зачем вы это написали? 4. странный абзац с учетом того, что уровень изоляции как раз задает, как именно будут блокироваться данные еще странно советовать автору рулить блокировками СУБД (уровнем изоляции) при том что конфигурация у него на управляемых |
|||
29
Ник второй
04.11.14
✎
22:38
|
(27)
1. Ложь. Блокировки ставятся всегда 2. Привыполнении запроса ставится блокировка на чтении, смотри профайлер 4. мда, (28) в части 4 пункта +1 |
|||
30
tridog
04.11.14
✎
23:06
|
(28) Уровень изоляции задает не только стратегию блокировки данных при чтении. Еще, например, стратегию чтения данных, заблокированных другой транзакцией (несогласованное чтение).
> При том что конфигурация у него на управляемых Управляемые блокировки в этом случае (выполнение запроса) вообще не устанавливаются. При чем тут они - непонятно. При выполнении запроса вне транзакции допускается несогласованное чтение (до 8.3 без совместимости). При выполнении запроса в транзакции в этом случае платформа использует READ_COMMITED - что ликвидирует грязное чтение. Это и было посоветовано автору, притом сразу в первом ответе) (29) Профайлер показывает блокировки СУБД. Речь шла про управляемые блокировки (это отдельно подчеркивалось). |
|||
31
Torquader
04.11.14
✎
23:41
|
Начнём с того, что если мы открываем транзакцию и обращаемся к объекту, изменённому в другой ещё неподтверждённой транзакции, то будет блокировка и транзакция будет ожидать завершения транзакции проведения.
Однако, возможна ситуация, когда при проведении данные для записи в таблицы (например, регистры) готовятся, но ещё не были записаны - в этом случае - транзакция чтения получит старые данные, и ничего удивительного в этом нет. |
|||
32
vi0
05.11.14
✎
07:57
|
(30) еще раз: зачем ему советовать инструменты субд, 8.3 и прочее, когда он написал, что у него 8.2 управляемые блокировки - для этого есть соответствующие инструменты
|
|||
33
vi0
05.11.14
✎
08:02
|
(29) всегда ставятся упр блокировки?
а можно пример кода? |
|||
34
tridog
05.11.14
✎
08:16
|
(32) Инструменты СУБД ему никто не советовал. Ему посоветовали выполнять запрос в транзакции - изменив непосредственно код на встроенном языке.
Описание того, почему это изменит ситуацию я привел в ответ на совет добавить в запрос условие вида Ссылка.Проведен. Соответствующие инструменты для того, чтобы избежать грязного чтения на 8.2 (хоть на управляемых блокировках, хоть на автоматических) - это выполнять чтение в транзакции. Само по себе использование управляемых блокировок не отменяет грязного чтения. Попутно много раз было отмечено (не только мной), что на 8.3+ проблемы вообше нет в принципе из-за изменений в платформе (всегда считал, что это полезная информация). |
|||
35
herfis
05.11.14
✎
10:30
|
(34) "на 8.3+ проблемы вообше нет в принципе из-за изменений в платформе"
Не совсем так. Проблема не в платформе, а логике работы используемой СУБД. В версионниках этой проблемы и не было никогда. В postgres, например. Просто 8.3+ научилась работать с MSSQL в режиме версионника, который там с некоторых пор появился (см. 24) Как дела обстоят в DB2 точно не знаю, но вроде как он остался чистым блокировочником а значит и грязное чтение вне транзакций в 1С там осталось скорее всего. |
|||
36
degot
05.11.14
✎
11:03
|
(35) а вы случаем не в курсе, будет ли 8.3 работать с версиями, если конфа в режиме совместимости?
|
|||
37
herfis
05.11.14
✎
12:13
|
(36) Не в курсе.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |