Имя: Пароль:
1C
1C 7.7
v7: SQL, блокировки, два ствола
, ,
0 Phil_McLaren
 
04.12.13
15:41
Доброго!
Прошу совета в следующей ситуации.

Есть некая обработка на 77, чертовски большая и сложносочиненная, в которой в некоторый момент в ряде случаев вызывается процедура создания документов из сторонних входящих данных. Существующие документы ей никогда не перепроводятся, а создаваемых обычно от 1 до 20 в пределах одной сессии работы. Единственный типовой среди них - реализация.

/*код целиком не привожу сознательно, одна только обсуждаемая процедура содержит больше 1000 строк, будет тяжело там отделить зерна от плевел*/

Вот прошел сбор и корректировка входных данных, начали в цикле обрабатывать коллекцию, которая эти данные теперь содержит в готовом для формирования документов виде. После создания и заполнения каждый документ записывается и проводится в отдельной транзакции. Проблема: периодически N документов не удается провести из-за блокировки SQL ('...deadlocked on lock resources with another process and has been chosen...' и дальше по тексту), причем в совершенно беспорядочном на первый взгляд виде - может быть из 6 вылетит блокировка на 1ый и 4ый, может быть из 10 на 2ой, может из 15 ни на один.

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

Функция ПровестиВТранзакции(Док)
    Попытка
        
        НачатьТранзакцию();
        
        Док.Записать();
        ЗаписьВЛог("Документ "+Строка(Док)+" записан",1);
        
        Результат=Док.Провести();    

        ЗафиксироватьТранзакцию();
        
    Исключение
        
        ЗаписьВЛог("Документ "+Строка(Док)+": "+ОписаниеОшибки(),1,1);
        ОтменитьТранзакцию();
        
    КонецПопытки;
    
    Возврат Результат;
КонецФункции

, и, если документ не проведен, ждет одну секунду и пытается провести еще раз, вплоть до 10 попыток. Это не помогло - все 10 попыток в каждом таком случае попадают в такую же взаимоблокировку.
Следующий же документ вполне может провестись. А может быть то же самое.

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

В высшей степени признателен за любое внимание проблеме и идеи по ее решению.
1 Тьма
 
04.12.13
15:46
Собирай эти документы в кучку и пытайся их провести раз в несколько минут по паре штучек с помощью обработки ожидания, пока не закроешь весь список. Если используешь данные этих документов в последующих расчетах обработки - перепиши обработку.
2 Phil_McLaren
 
04.12.13
15:54
>>Собирай эти документы в кучку и пытайся их провести раз в несколько минут по паре штучек
А в чем преимущество по сравнению с последовательным проведением каждого в отдельной транзакции?
>>Если используешь данные этих документов в последующих расчетах обработки
Нет, мне сразу после обработки входных данных нужно сделать некоторые записи о результате работы и я забываю об этих документах.
3 Phil_McLaren
 
04.12.13
15:54
+спасибо за ответ
4 DeiMos
 
04.12.13
15:57
Пиши не в лог, а куда-нибудь в другое место (файлег).
5 ADirks
 
04.12.13
16:46
Для начала неплохо бы выяснить, кто кого там блокирует, например такой штукой  http://www.softportal.com/software-1058-sql-monitor.html

Как вариант решения проблемы: сначала все документы записывать, и только потом проводить, пока не проведутся. Ссылки на записанные документы запихивать, например, в спец.справочник, по мере проведения ссылки удалять.
6 Тьма
 
04.12.13
16:51
(2)В том что в данный момент база заблокирована, а через пару минут может освободиться.
7 Builder
 
04.12.13
17:11
А смысл проведения документа в транзакции?
Она же и так сама в транзакции делается....
И как сделано ожидание 1 секунды?
8 ikea
 
04.12.13
17:11
Обработка проводит документы в тот момент, когда заблокированы данные. У тебя же написано, что дедлок, значит ВЗАИМНАЯ блокировка. Скорее всего, у тебя документ при проведении считывает где-то данные, которые заняты другим пользователем. Посмотри, если есть в отчетах и модуле проведения SELECT, то  поставь обязательно with(nolock).
9 ikea
 
04.12.13
17:13
Либо параллельно обработка и другой пользователь  проводит документ, тут ты ничего уже не сделаешь. Запускай обработку в другое время.
10 Господин ПЖ
 
04.12.13
17:14
>В том что в данный момент база заблокирована, а через пару минут может освободиться.

блокирует ее кто? святой дух?

что qa+профайлер говорят?
11 Злой Бобр
 
04.12.13
18:42
(0) Попытка, транзакция - вы ребята как в детском саду. Может вы еще и запрос в цикле считаете нормальным?.. Боюсь увидев весь ваш шедевральный код мой мозг этого б невыдержал.
Посмотрите профайлер что именно блокирует. Вполне возможно что вы сами себе на яй** наступаете. А может кто и другой. Поймите одно - по фотографии такое нелечится. И само тоже непройдет. Так что или разгребайте сами, или пригласите программиста. И ненужно фыркать что вы типа тоже программисты. Все мы чего-то незнаем.
Вы задавайте конкретные вопросы и мы пнем вас в правильном направлении. Просто когда вы говорите что что-то делаете и неработает - нам это ничего неговорит.
12 Phil_McLaren
 
05.12.13
11:32
(11) Думаю, я задал вполне ясный вопрос, достаточно емко описав картину происходящего. У Вас, уважаемый, кажется, много демонов в голове: всегда думал, что если когда-нибудь свихнусь от 1С, то основным симптомом будут фразы типа "когда вы говорите что что-то делаете и неработает - нам это ничего неговорит"

(4) лог у меня ведется как файловый, так и в SQL базе, с ним все в порядке, только по нему и восстанавливаю картину.

(5) Вот сначала записывать это вариант, пожалуй.

(6) Разумно конечно, но приведенная функция проведения в транзакции вызывается, как я упоминал, циклически с интервалом в 1 секунду, и я могу делать это даже 30 секунд к ряду и каждый раз получать блокировку, а уже на следующем документе получить нормальное проведение.

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

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

(10) с профайлером не удалось поработать - попробовал подержать трассировку по шаблону Locks (я не очень в профайлере уверенно себя чувствую и потому решил воспользоваться шаблоном), но ошибка с блокировкой совершенно непредсказуема и вызвать ее искусственно я не могу, так что пришло держать профайлер включенным где-то с час. За это время ни одной блокировки не вылетело, зато вылетели несколько терминальных пользователей
13 Simod
 
05.12.13
11:42
(12) Транзакция на отдельный документ не имеет смысла - система по умолчанию выполняет проведение в транзакции. Если хочешь, чтобы не выпадали документы (12-й из 20-и), то проводи их все в одной транзакции. Или партиями (10, 100, ..).
14 Phil_McLaren
 
05.12.13
11:54
(13) хм, хорошо. Ты уверен, что группой будет надежнее, и я не потеряю все из-за блокировки при проведении одного? Я не прошу никаких гарантий, просто мне такое изначально казалось самой опасной реализацией, так что немного сомнения терзают
15 пипец
 
05.12.13
11:57
(14) проводили пачками с паузой (можно с отметкой о проведении ... в какой то момент ставить флаг , например в четный день 2-ку в нечетный 1, или вообще порядковый день года/что разумнее/) , дедлоки никуда не уйдут , просто многие смежные вещи придется пересмотреть через попытку исключение
ЗЫ рекомендовал бы еще 1с++
16 пипец
 
05.12.13
11:58
+ пауза была в виде пустого цикла между зафиксировать и начать транзакцию
17 Simod
 
05.12.13
12:03
(14) Если проведется первый документ, то проведутся и все остальные, т.к. из-за твоей транзакции никто не сможет "вклинится". Естественно, документ может не провестись по какой-либо другой причине. Например - нехватка товара. Тогда необходимо принимать решение - отмена всей транзакции или пропуск непроведенного документа и продолжение проведения остальных документов.

Разумеется это не все подводные камни.
18 Phil_McLaren
 
05.12.13
12:15
(15), (17)
понял. Попробую так реализовать, отпишу о результате. Спасибо за помощь.
19 Холст
 
05.12.13
14:10
(0) одна только обсуждаемая процедура содержит больше 1000 строк

- будь мужиком, начни с рефакторинга
20 Phil_McLaren
 
05.12.13
15:16
(19) -)) справедливо) Там в принципе довольно чистенький код, имело бы смысл в какой-то момент взяться за полный пересмотр структуры и пообрезать углы, но сейчас нужно бесперебойную работу обеспечить.
В общем мы все через это проходили)
Есть два вида языков, одни постоянно ругают, а вторыми никто не пользуется.