Добрый день, уважаемое сообщество.
Проявилась такая проблема в этом году. Возможно связано с большим количеством записей в базе данных. Но не факт.
Описание:
Terrasoft XRM 3.3.2.304.
Существует несколько расходных накладных.
Скрипт вызывает стандартную функцию ConductSelectedOfferingMovements:
В Data.OfferingMovementIDs передается массив ID складских документов.
Data.IsConduct = true;
Data.OfferingMovementStatus = omsCompleted;
Data.IsRecalcOfferingPrices = false;
Data.IsUpdateShipmentState = false;
Data.IsUpdatePurchaseState = false;
Data.IsReserveOfferingsFromOrders=false;
Data.IsAddSupplierInOffering = false;
var Result = ConductSelectedOfferingMovements(Data);
Все выполняется правильно, но пока идет выполнение этой функции на одном из рабочих мест, у других пользователей, работающих с разделами Склад (деталь Продукты)
или Продукты(деталь Складские документы), появляется ошибка "Ошибка открытия источника данных ds_MovementInOffering. Превышено время ожидания запроса на блокировку".
Изменений в функцию и хранимые процедуры не вносили.
Ошибка повторяется на 100 процентов.
Во время выполнения хранимой процедуры ошибка открытия может быть и для ds_Account и других
источников данных.
Сталкивался ли кто-нибудь с такой проблемой и в чем ее причина?
Нравится
Здравствуйте, Виктор.
Нужно тюнить базу, может помочь индексация используемых в ХП колонок.
Скорее всего, транзакция запущенная по ХП блокирует используемые таблицы, которые параллельно пытаются использовать пользователи с других рабочих мест.
Максим, добрый день.
Мы тут примерно в эту сторону и копаем. Похоже ХП блокирует tbl_MovementInOM. Мы убрали подзапросы в разделах и деталях, которые ее использовали. Но в том же ds_Offering поле Remain это подзапрос к этой таблице. Отсюда и ошибки.
По индексации: я правильно понимаю, что нужно добиваться того, чтобы ХП быстрее обрабатывала блокируемую таблицу?
Да, это один из вариантов. Насколько мне известно есть еще и возможности предотвращения дедлоков путем их приоритезации. Но каких либо конкретных рекомендаций дать не смогу, простите.
Возможно, эти статьи будут полезными:
http://technet.microsoft.com/ru-ru/library/ms189081.aspx
http://samag.ru/archive/article/797
Во время выполнения ХП закрытия документа SQL сервер грузит процессор на 100%. Это нормально?
Виктор, видимо обработка больших данных несет большую нагрузку. Может быть мощности не хватает.
Как долго выполняется хранимка?
Проверял на тестовой базе.
Всего в этой базе 87 складских документов, т.е. нет больших данных на мой взгляд. Выполняется закрытие практически мгновенно. Но делаем закрытие в цикле нескольких расходных, и на это время загрузка процессора 100%.
И еще один момент. К моей радости он пока проявляется только на тестовом сервере. Любая конфигурация от самых старых до текущей копии рабочей базы. Закрытие документа с недостаточным количеством продукта в остатках(т.е. остаток 100, а списываю 101) приводит не к сообщению о недостаточном количестве, а полностью вешает клиента. Процессор на сервере загружен на 100%, пока аварийно не завершу клиента. Часами я конечно не ждал результата. Думаю, что-то с SQL сервером (2008). Будем разбираться.
С другой стороны анализируем ХП, чтобы понять в каком месте мы зависаем.
Новые данные. Виснет если по продукту указан метод списания Средневзвешенный и есть несколько приходов по ним.
зацикливается в tsp_OfferingDistribute
не может закончится цикл:
while (@ARemainQuantity >= @AUnitDivision) begin OPEN Consignment_Cursor FETCH NEXT FROM Consignment_Cursor INTO @ConsignmentID, @ConsignmentQuantity WHILE @@FETCH_STATUS = 0 BEGIN if (@ARemainQuantity < @AUnitDivision) break update #ListQuantity set Quantity=Quantity + @AUnitDivision where ConsignmentID=@ConsignmentID and Quantity < @ConsignmentQuantity if (@@ROWCOUNT > 0) set @ARemainQuantity = @ARemainQuantity - @AUnitDivision FETCH NEXT FROM Consignment_Cursor INTO @ConsignmentID, @ConsignmentQuantity END CLOSE Consignment_Cursor end
Похоже выяснили причину зависания.
Пример:
Два прихода по продукту с количествами 1000 и 100.
Проводим.
Расходная с количеством 3500.
Зависание.
Дело в том что 3500 делится на части пропорционально остаткам по партиям.
Т.е получаем 3181,818 и 318,1818. И если правильно округлить, то 3182 и 318, что в сумме даст 3500.
Причина в ХП tsp_RoughOfferingDistribute
DECLARE Consignment_Cursor CURSOR FOR .... WHILE @@FETCH_STATUS = 0 BEGIN .... set @PartQuantity = floor(@PartQuantity / @AUnitDivision) * @AUnitDivision; insert into #ListQuantity (ConsignmentID, Quantity, BasicPrice, ConsignmentQuantity) values (@ConsignmentID, @PartQuantity, @BasicPrice, @ConsignmentQuantity) set @RemainQuantity = @RemainQuantity - @PartQuantity; FETCH NEXT FROM Consignment_Cursor INTO @ConsignmentQuantity, @ConsignmentID, @BasicPrice END CLOSE Consignment_Cursor DEALLOCATE Consignment_Cursor
Таким образом floor отбрасывает дробную часть и мы получаем в ListQuantity 3181, 318 и 1. А вот эта единичка и зацикливает tsp_OfferingDistribute, т.к. значений три, а партий только две.
меняем floor на round и все работает
set @PartQuantity = round((@PartQuantity / @AUnitDivision),0) * @AUnitDivision;
В любом случае по методу Средневзвешенный списание происходит неверно и возникают неверные остатки. Поэтому видимо сменим метод.
Здравствуйте, Виктор!
Большое спасибо за активное участие. Учтем Ваши замечания