Ускоряем регистрацию объектов в МОД (для SQL)

Менеджер обмена данными - популярный и очень своеобразный продукт. В статье рассматривается решение одной из его проблем - получения нового уникального IDD.

Опубликовано в блоге Вадимко/

Менеджер обмена данными - популярный и очень своеобразный продукт. В статье рассматривается решение одной из его проблем - получения нового уникального IDD.

После оптимизации проведения ключевых документов у нас начались блокировки констант. Переделывать будем эту функцию:

Функция ПолучитьНовыйИДД()

//Предусматриваем одновременное обращение к константе нескольких пользователей

Блокировка=1;

Пока Блокировка=1 Цикл

Попытка

НачатьТранзакцию();

Константа.УникальныйIDD=Константа.УникальныйIDD;//блокируем

Блокировка=0;//константа заблокирована не была - можем работать

Исключение//константа заблокирована !!

ОтменитьТранзакцию();

//Ожидание для возможности работы других пользователей (по совету Олега Яковлева из ЧПТФ "ЮСИ")

Стр=ТекущееВремя();

Пока Стр=ТекущееВремя() Цикл

КонецЦикла;

КонецПопытки;

КонецЦикла;

//Увеличиваем счетчик в константе на единицу

Константа.УникальныйIDD=Число(Константа.УникальныйIDD)+1;

Рез=Прав("0000000"+СокрЛП(Константа.IDD),7)+прав("0000000000"+СокрЛП(Константа.УникальныйIDD),10);

ЗафиксироватьТранзакцию();

Возврат Рез;

КонецФункции

 



Итак, приступим. Будем использовать 1С++.
В глобальном модуле в процедуру ПриначалеРаботыСистемы() добавим следующие строки для создания таблицы и заполнения ее значениями:

//таблица IDD для МОДа

ТекстЗапроса = "

|if not exists (select name from dbo.sysobjects where name = 'UIDD' and xtype = 'U ')

|create table UIDD (idd char(7), uidd numeric(10,0))

|";

RecordSet.ВыполнитьИнструкцию(ТекстЗапроса);

//начальное заполнение значений таблицы

ТекстЗапроса = "

|if (select count(*) from UIDD (nolock)) = 0

|insert into UIDD values (:ИДД,:УникальныйИДД)

|";

RecordSet.УстановитьТекстовыйПараметр("ИДД", Константа.IDD);

RecordSet.УстановитьТекстовыйПараметр("УникальныйИДД", Число(Константа.УникальныйIDD));

RecordSet.ВыполнитьИнструкцию(ТекстЗапроса);



Теперь переделанный текст функции (спасибо за обсуждение на 1cpp.ru коллегам):

Функция ПолучитьНовыйИДД() Экспорт

ТекстЗапроса = "

|begin tran

|select right('0000000' + LTrim(idd), 7) + right('0000000000' + LTrim(str(uidd + 1, 10)),10)

|from UIDD (updlock)

|update UIDD

|set uidd = uidd + 1

|commit tran

|";

ТЗ = RecordSet.ВыполнитьИнструкцию(ТекстЗапроса);

Возврат ТЗ.ПолучитьЗначение(1,1);

КонецФункции

 



Слово Экспорт добавили не зря. В обработках конфигурации мы найдем изобилие конструкций с блокировкой константы, которые также нужно переделать
Пример переделанного кода:

Для ы=1 по Метаданные.Справочник() Цикл

НачатьТранзакцию();

//Блокировка=1;

//Пока Блокировка=1 Цикл

// Попытка

// НачатьТранзакцию();

// Константа.УникальныйIDD=Константа.УникальныйIDD;//блокируем

// Блокировка=0;//константа заблокирована не была - можем работать

// Исключение//константа заблокирована !!

// ОтменитьТранзакцию();

// //Ожидание для возможности работы других пользователей (по совету Олега Яковлева из ЧПТФ "ЮСИ")

// Стр=ТекущееВремя();

// Пока Стр=ТекущееВремя() Цикл

// КонецЦикла;

// КонецПопытки;

//КонецЦикла;

КолПрогрессора=КолПрогрессора+10;

Прогрессор(КолПрогрессора);//**************** прогрессор

Ст=Метаданные.Справочник(ы).Идентификатор;

Если (ст<>"ПравилаЗагрузки") и (ст<>"ПравилаВыгрузки") и (ст<>"ПериферийныеБазы") Тогда

Спр=СоздатьОбъект("Справочник."+Ст);

М_Состояние("Обработка "+Ст);

Спр.ВыбратьЭлементы(0);

Пока Спр.ПолучитьЭлемент()>0 Цикл

Если (Сокрлп(Спр.IDD)="")ИЛИ(ФлНовый=1) Тогда

//Константа_УникальныйIDD=Константа_УникальныйIDD+1;

//Спр.IDD=Сокрлп(Константа_IDD+прав("0000000000"+Константа_УникальныйIDD,10));

Спр.IDD = ПолучитьНовыйИДД();

Попытка

Спр.Записать();

Исключение

Сообщить("Ошибка на : "+Спр.Вид()+", владелец "+Спр.Владелец+", элемент="+Спр.ТекущийЭлемент()+", код="+Спр.Код+" . Внимание: найдите данный элемент справочника вручную и измените код !!");

КонецПопытки;

КонецЕсли;

Если РежимИниц=1 Тогда

ПриИзмененииОбъектаМОД(Спр,Спр,'01.01.1976',0);//для периодических реквизитов надо задавать период выгрузки

ПриИзмененииОбъектаМОД(Спр,Спр,РабочДата,0);//у нас период равен: 01.01.1976 - рабочая дата

КонецЕсли;

КонецЦикла;

КонецЕсли;

//Константа.УникальныйIDD=Строка(Число(Константа_УникальныйIDD)+1);

ЗафиксироватьТранзакцию();

КонецЦикла;

 


Не забывайте о том, что МОД при нахождении неуникальных IDD присваивает уникальные значения УЖЕ СУЩЕСТВУЮЩИМ объектам.

Начать дискуссию