|
|
|
v7: Недопустимое состояние курсора | ☑ | ||
|---|---|---|---|---|
|
0
1snik_d
18.11.25
✎
15:13
|
Всем привет. Есть база 7.7 сильно переписанная ТиС, используются прямые запросы, FormEx и т.д., имеется УРБД. Суть проблемы следующая: есть прямой запрос, который вставляет в таблицу регистрации изменений УРБД записи для отправки справочников в нужные периферийки по условию. Периодически при попытке выполнения такого запроса вылетает критическая ошибка "Недопустимое состояние курсора" и 1С тупо закрывается. Перед этим обычно происходит deadlock. Помогите решить проблему, хотя бы с какой стороны подойти к решению.
|
|||
|
1
arsik
гуру
18.11.25
✎
15:15
|
(0) Перед вставкой наверно нужно блокировку наложить. Не?
|
|||
|
2
1snik_d
18.11.25
✎
15:24
|
ТекстЗапроса = " |DECLARE @SelectedId char(9) |DECLARE @SelectedDef int |DECLARE @SelectedSign char(3) |DECLARE @count int |SET @SelectedId=? |SET @SelectedDef=? |SET @SelectedSign=? |UPDATE _1sjourn SET verstamp=(SELECT verstamp FROM _1sjourn WHERE iddocdef=@SelectedDef AND iddoc=@SelectedId)+1 |WHERE iddocdef=@SelectedDef AND iddoc=@SelectedId |SET @count=(SELECT count(*) FROM _1supdts WHERE typeid=@SelectedDef AND objid=@SelectedId AND dbsign=@SelectedSign) |IF @Count=0 |BEGIN INSERT INTO _1supdts VALUES (@SelectedSign,@SelectedDef,@SelectedId,' ',' ') |END |ELSE |BEGIN |UPDATE _1supdts SET dwnldid='' WHERE Typeid=@SelectedDef AND Objid=@SelectedId AND DBSign=@SelectedSign |END"; Если Элемент.Выбран() = 1 Тогда ИдЭлемента = глMDW.ЗначениеВСтрокуБД(Элемент); ДефЭлемента = глMDW.ИДСправочника(Элемент.Вид()); глRecordSet1CPP.ДобПараметр(1,14,9,0); глRecordSet1CPP.ДобПараметр(1,4,4,0); глRecordSet1CPP.ДобПараметр(1,14,3,0); глRecordSet1CPP.УстПараметр(1, ИдЭлемента); глRecordSet1CPP.УстПараметр(2, ДефЭлемента); глRecordSet1CPP.УстПараметр(3, ИдБазы); глRecordSet1CPP.ВыполнитьСкалярный(ТекстЗапроса); глRecordSet1CPP.УдалитьПараметры(); // Удалить параметры КонецЕсли; Вот такой запрос выполняется для вставки. |
|||
|
3
1snik_d
18.11.25
✎
16:09
|
(1) А разве она сама не накладывается автоматически?
|
|||
|
4
trad
18.11.25
✎
16:38
|
set nocount on
в начале запроса |
|||
|
5
1snik_d
18.11.25
✎
17:07
|
|UPDATE _1sjourn SET verstamp=(SELECT verstamp FROM _1sjourn WHERE iddocdef=@SelectedDef AND iddoc=@SelectedId)+1 |WHERE iddocdef=@SelectedDef AND iddoc=@SelectedId Вот это я так понимаю тоже можно выкинуть, если регистрируются только справочники, без документов? |
|||
|
6
Ёпрст
гуру
18.11.25
✎
17:31
|
(5) да
|
|||
|
7
1snik_d
18.11.25
✎
20:41
|
Спасибо за ответы, внес правки, буду наблюдать за поведением 1С.
|
|||
|
8
АгентБезопасной Нацио
19.11.25
✎
13:56
|
(5) а зачем вообще verstamp трогать? ты ж не изменяешь док.
|
|||
|
9
Лодырь
19.11.25
✎
14:22
|
(8) принудительная регистрация к обмену
|
|||
|
10
АгентБезопасной Нацио
19.11.25
✎
15:43
|
(9) Принудительная регистрация - это как раз запись в updts.
изменять верстамп для этого совршенно не нужно. Верстамп нужен для разрешения коллизий. |
|||
|
11
1snik_d
19.11.25
✎
16:08
|
В общем добавление set nocount on в начало запроса не помогло. Все равно вылеты с этой ошибкой. Перед вылетом всегда deadlock. Если отключить эту регистрацию прямым запросом, то падения не происходит. Просто вылетает сообщение о deadlock и все.
|
|||
|
12
1snik_d
19.11.25
✎
16:16
|
Есть подозрение, что в момент выполнения этого прямого запроса к таблице _1supdts, она параллельно изменяется УРБД и при попытке обновления найденной записи в таблице падает, т.к. записи уже нет, например
|
|||
|
13
Franchiser
19.11.25
✎
16:16
|
SELECT verstamp FROM _1sjourn (nolock)
|
|||
|
14
1snik_d
19.11.25
✎
16:17
|
(13) Я уже выкинул из запроса журнал документов, он мне не требуется
|
|||
|
15
Franchiser
19.11.25
✎
16:33
|
Тогда так
FROM _1supdts (nolock). Возможно ещё нужно объявлять курсор, и делать deallocate. Добавь глRecordSet1CPP.Закрыть(); |
|||
|
16
1snik_d
20.11.25
✎
09:32
|
(15) Что-то я не уверен, что nolock правильный вариант, точность данных может нарушиться. Получается чтение того, что где-то в параллельном сеансе можем апдейтнуться
|
|||
|
17
Franchiser
19.11.25
✎
16:39
|
(16) тогда только закрывай курсор
|
|||
|
18
АгентБезопасной Нацио
20.11.25
✎
09:53
|
(16) в паралельном сеансе может быть либо регистрация для обмена (штатно ли, либо твоим механизмом), либо разрегистрация (подтверждение обмена механизмом УРБД).
В первом случае ты "повторно отправишь" (т.е. ничего не изменишь), во втором - зарегистрируешь еще раз (т.е. элемент сбегает в ПБ еще разок. Если у тебя не "снежинка", то - имхо - ничего страшного ). Ну и как вариант - ищи запись только неотправленную (с пустым даунлоадидом), если нет - создавай. Будет небольшая избыточность при обмене... Ну или натравливай на базу-таблицу sql-профайлер, лови ошибку... |
|||
|
19
trad
20.11.25
✎
10:37
|
(11) "В общем добавление set nocount on в начало запроса не помогло."
но, тем не менее, не убирай, он там нужен |
|||
|
20
1snik_d
20.11.25
✎
11:47
|
(18) т.е. предлагаешь не апдейтить таблицу, а только инсертить в нее по необходимости?
|
|||
|
21
АгентБезопасной Нацио
20.11.25
✎
11:59
|
(20) ну да. искать с пустым идом обмена, и если нету - то добавить. тут может быть коллизия только если запись уже выгружена, но еще не отмечена как выгруженная (но она по идее в этот момент в курсоре, и будет обработана). Я индексы не помню, уж лет 8 в клюшечную урбд не лазил, но вроде должно разрешить...
|
| Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |