«Гибкие» блокировки в 1С

Как то помню на форуме прочитал сообщение типа «а вот знакомый админ удалил Tablockx и поставил rowlock в хранимых процедурах и все закрутилось, завертелось»… Эта мысль по-моему достаточно показательна для многих из 1С программистов и особенно для новичков.

Материал опубликован на сайте www.softpoint.ru/

Как то помню на форуме прочитал сообщение типа «а вот знакомый админ удалил Tablockx и поставил rowlock в хранимых процедурах и все закрутилось, завертелось»… Эта мысль по-моему достаточно показательна для многих из 1С программистов и особенно для новичков.

Автор статьи - Сердюк В.И.

Для того чтобы не наломать дров в вашей ИТ системе необходимо : во первых понимать для чего существуют блокировки в М S SQL server , во вторых понимать как устроен блокировочный механизм в 1С.

По первой части есть масса литературы и поэтому не хотелось бы ее пересказывать…Отмечу лишь принципиальные моменты…

В MS SQL есть понятие блокировок и подсказок блокировок. Основное предназначение избежать проблем некорректного(грязное чтение, чтение фантомов и т.п.) чтения информации.

Для 1С значимы следующие виды блокировок

Holdlock – Захватывает разделяемую блокировку до завершения транзакции.

Nolock - Приминима только к оператору select . Читает все…

Tablock - Используется блокировка на уровне таблиц.

Tablockx - Используется монопольная блокировка таблицы.

Отдельно выделю подсказки блокировки которые «горячие» головы рекомендуют применять

Rowlock - блокировка на уровне строк

Updlock - блокировка на изменение

Readpast - Приминима только для Select . Пропускаются строки блокированные( rowlock ) другими транзакциями.

Для того что бы понять как действуют эти блокировки необходимо почитать соответствующую литературу а еще лучше самим проверить на практике эти блокировки в различных ситуациях…

На специфике реализации блокировок в 1С остановлюсь подробнее.

Механизм блокировок в 1С максимально простой - блокируется все и по максимуму.

Интересней всего конечно реализация блокировок на документы т.к. как правило это и является самым узким местом системы а также документы и являются источником конфликтов.

Начнем с того что в 1С существует специальная таблица _1 sjourn где хранятся внутренние идентификаторы всех документов. При записи, проведении и т.п. операциях с документами 1С накладывает блокировку на таблицу _1 sjourn и соответственно в системе в один момент времени может проводиться не более одного документа. То есть _1 sjourn выступает в роли своеобразного семафора. До тех пор пока не завершиться транзакция и соответственно не будет снята блокировка с таблицы все остальные клиенты будут ждать разблокировки и самое интересное как это они будут делать. В момент ожидания 1С загружает ресурсы сервера, т.к. непрерывно сканирует таблицу на вопрос разблокировки и поэтому загружает процессор по максимуму.

Удалить механизм блокировок можно путем изменения хранимых процедур, через которые 1С проверяют таблицы на блокировки. А точнее, удалить хинты на блокировку таблиц.

Например, в хранимой процедуре _1 sp __1 SJOURN _ TLockX в конструкции
select @i=1 from _1SJOURN(TABLOCKX HOLDLOCK) where 0=1
необходимо удалить TABLOCKX HOLDLOCK.

Также необходимо удалить соответствующие хинты(подсказки блокировки) в остальных таблицах относящихся к документам. Если этого не сделать то будут возникать deadlock -и – взаимоблокировки транзакций на уровне SQL server .

Предположим что мы это сделали. Казалось бы все теперь хорошо , документы параллельно проводятся , процессор не загружается. Но не все так просто. Что бы доказать ошибочность этих выводов приведем следующий эксперимент.

Создадим конфигурацию : справочник - Товары, документ – ПриходнаяНакладная, документ – РасходнаяНакладная, регистр – ОстаткиТовара Приходная накладная нужна только для того что бы сделать одно единственное движение. Больше логической нагрузки она нести не будет.

В модуле расходной накладной реализуем следующую логику :

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Товар = Регистр.Остатки.Товар;
|Количество = Регистр.Остатки.Количество;
|Функция КоличествоКонОст = КонОст(Количество);
|Группировка Товар;
|"//}}ЗАПРОС
;

Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
Возврат;
КонецЕсли;

Сообщить(НомерДок);
Если Число(НомерДок)=1 Тогда
Для Сч6=1 По 10000 Цикл
Сообщить("Ждем второго. Вообще то здесь может идти
| какой-то анализ или обработка данных.
|Чем больше интервал между получением остатков и их
| анализом с последующей записью движений -
|тем больше вероятность возникновения отрицательных остатков");
КонецЦИкла;
КонецЕсли;



Запрос.Группировка(1);
Если (Запрос.КоличествоКонОст<0) Тогда
Сообщить("Ошибка!!!");
Возврат;
КонецЕсли;

Если Запрос.КоличествоКонОст>=Количество Тогда
Регистр.Остатки.Товар=Товар;
Регистр.Остатки.Количество=Количество;
Регистр.Остатки.ДвижениеРасходВыполнить();
Иначе

Сообщить("Не хватает!");
Возврат;
КонецЕсли;

Товар это у меня реквизит шапки и поэтому я использую одномерную (например использую Запрос.Группировка(1) зная что движение по одному товару) модель. Для многомерной модели ничего принципиально не меняется…

Логика вкратце сводится к тому что необходимо перед тем как списывать товар провести анализ , а хватает ли его на складе? Казалось бы при такой модели не должно возникать отрицательных остатков – ведь стоит проверка. Это возникающее на первый взгляд впечатление ошибочно. Для доказательства этого я вставил в середине модуля обработку которая эмулирует задержку между получением остатков и их последующим анализом и записью движений. Получается следующая ситуация когда два пользователя одновременно пытаются списать товара в сумме больше чем есть на складе(в хронологическом порядке)

  • Первый пользователь получает остатки
  • Второй пользователь получает остатки
  • У первого пользователя идет какая либо обработка.(в моем случае выводится сообщение)
  • Второй пользователь проводит проверку остатков и списывает товар. Конец проведения.
  • Первый пользователь проводит анализ остатков и тут возникает самое интересное – информация по остаткам уже устарела! Но первый пользователь об этом не подозревает , проходит проверка остатка и списание. КонецПроведения.

Возникают отрицательные остатки. С точки зрения бизнес логики я думаю не нужно комментировать к чему это может привести.

Как избежать этой неприятной ситуации? – Реализовать свой, гибкий механизм блокировок.

Вот пример:

Перем глТои Экспорт;

Процедура ПроверкаБлокировкиРесурса(Ресурс) Экспорт;
глТои.Закрыть();
глТои.Соединиться(0);
//глТои.ВыполнитьЗапрос("set lock_timeout 20000");
Состояние("Проверка блокировки...");
Если Ресурс = "Регистр.ОстаткиТовара" Тогда
Если (глТои.ВыполнитьЗапрос("exec MyRA17_TLockX") = 1) тогда

Иначе
Сообщить("Ждет Занят MyRA17_TLockX");
КонецЕсли;
Если(глТои.ВыполнитьЗапрос("exec MyRG17_TLockX") = 1) тогда

Иначе
Сообщить("Ждет Занят MyRG17_TLockX");
КонецЕсли;
КонецЕсли;
глТои.Закрыть();

КонецПроцедуры
Загрузчик = CreateObject("Toy.Loader");
Хэндл = Загрузчик.LoadLibrary("C:Program Files1Cv77BINtoysql21.dll");
глТои = СоздатьОбъект("ToyQuery");

В данном случае я блокирую по объекту метаданных Регистр.ОстаткиТовара.

А хранимые процедуры MyRG17_TLockX и MyRA17_TLockX я полностью дублирую текстом старых RG17_TLockX и RA17_TLockX.

Вставляя процедуру ПроверкаБлокировкиРесурса( «Регистр.ОстаткиТовара» ) в начало модуля проведения мы добиваемся того что второй пользователь ожидает пока первый не завершит транзакцию и только после этого он может прочитать остатки товара. При этом не возникает неоправданной нагрузки процессора и документы проводятся последовательно но только в контексте движения по Регистр.Остатки.

Возникает вопрос а что делать если у нас происходит движение по бухгалтерским итогам? В этом случае движение затрагивает одну таблицу и она становиться узким местом системы.

Возникает соблазн использовать конструкцию rowlock - ведь судя по названию она и сможет устанавливать блокировку не монопольную на таблицу а построчную на изменяемые записи.

Тут нужно во первых понять как хранит 1С данные и какими запросами получает данные.

Я возьму для примера только регистры. Для бухгалтерских итогов концепция будет аналогична.

Нужно отметить , что данные по регистрам хранятся в агрегированном виде т.е остатки по измерения хранятся в нескольких записях соответствующим периодичности итогов. Возникает вопрос . А не изменится ли целостность и непротиворечивость агрегированных данных при отключении стандартного механизма блокировок.

Для ответа на этот вопрос нужно во первых понимать что SQL server сам расставляет блокировки объектов при изменении данных. Убедиться в этом можно изменив в транзакции запись таблицы(как правило на индексированные) и запустив sp _ lock . По результатам sp _ lock мы увидим что данная запись заблокирована как будто если бы мы в явном виде поставили подсказку rowlock .

Вкратце концепция изменения агрегированных данных(например регистра остатков) 1С следующая –

При движении по регистру вызывается ряд хранимых процедур но показательные из них две это _1sp_GetNextPeriod - обеспечивает последовательное обновление агрегированных данных и _1sp_RG17_Change – собственно изменят конкретную запись. Для этого используется следующая конструкция:

Update RG17
set SP19=Case When ABS(SP19+@p3)>9999999999 Then 9999999999 Else SP19+@p3 End
where PERIOD=@per AND SP18=@p1 AND SP24=@p2
if @@ROWCOUNT=0
insert into RG17 values(@per,@p1,@p2,@p3)

Как мы видим в конструкции Update нет хинта rowlock . Но по большому счету он и не нужен т.к. сервер сам расставляет блокировки по измененным записям. В этом опять таки не сложно убедиться если провести ряд тестов, вкратце их смысл искусственно создать ситуацию при которой одна сессия будет изменять запись и другая ее будет изменять но на основании прочитанных ранее устаревших данных. Вставка новых записей в агрегационную таблицу по документу происходит как правило не более одной(если конечно точка актуальности не установлена абы как) и соответственно ситуация когда один документ делает вставку( insert into RG 17 values (@ per ,@ p 1,@ p 2,@ p 3) ) а другой ее не видит практически невозможна(кроме того стоит ограничение на уровне уникальности индекса, для возможной повторной вставки).

Теперь что касается грязного чтения. С эти дело обстоит хуже и к сожалению никакие установки rowlock в этом не помогут. Во первых информация по изменению должна пройти по всем агрегационным записям в пределах транзакции(хоть и маловероятно что в этот момент возникнет конфликт).Во вторых 1С в запросах использует хинт nolock , что вообще не оставляет шансов на создание универсального блокировочного механизма .Да и нужен ли он?

Обращаясь к примеру с созданием процедуры ПроверкаБлокировкиРесурса продолжая аналогию можно прийти к выводу о достаточности реализации блокировки объекта данных. Ну например если мы хотим , что бы блокировалась не целиком таблица проводок а например только информации связанная со счетом 41 и 004 то нам достаточно заблокировать объект СчетПоКоду(«41») и СчетПоКоду(«004»). То есть если мы знаем, что расходная накладная использует данные по 41 и 004 счетам нам достаточно вставить в начале модуля проведения процедуру ПроверкаБлокировкиОбъекта(« СчетПоКоду(«41») ») и ПроверкаБлокировкиОбъекта(« СчетПоКоду(«004») ») .

Если же мы знаем, что для нас принципиальна информация по остаткам товара на складе, то соответственно ПроверкаБлокировкиОбъекта(« Склад ») . Таким образом все документы по одному складу будут проводиться по очереди а по разным складам параллельно. То же самое если мы хотим сделать блокировки по Товару. Тогда будет соответственно ПроверкаБлокировкиСпискаОбъектов(спТовара) – но в этом случае нужно понимать что чем больше информации по блокировкам тем больше нагрузка на сервер. Необходимо найти золотую середину.

Собственно а как все вышеперечисленное реализовать. Вариантов несколько. Но раз мы уже остановились на классическом блокировочном механизме MS SQL то можно воспользоваться процедурой sp_getapplock. Смысл ее в следующем – блокировка произвольного ресурса. Запустив sp _ lock мы можем убедиться что это всего лишь еще одна запись. То есть например блокировку по складу(в контексте остатков по складу) можно сделать следующим образом sp_getapplock 'Остатки**Склад**Основной', 'Exclusive', 'transaction' . Соответственно аналогичная процедура выполненная из Сессии №2 сессии будет ждать завершения транзакции открытой Сессией №1 если в ней была запущенна sp_getapplock такими же параметрами. Процедура ПроверкаБлокировкиОбъекта всего лишь преобразует объект в уникальный идентификатор и передает его в качестве параметра в sp_getapplock в открытой сессии 1С.

В конце статьи хочется отметить что для того что бы реализовать механизм «гибких» блокировок необходимы какие либо навыки в MSSQL server а также понимание внутренней структуры 1С. Например снимая хинты с процедуры _1sp__1SSYSTEM_TLock вы тем самим можете попасть в ситуацию когда два проведенных документа перемещающие ТА проведутся одновременно и один из них окажется позже точки актуальности или наоборот сняв хинты с _1sp__1SJOURN_TLock и не сняв их с _1sp_DT???_TLockX вы можете создать deadlock -и.

P.S. На данный момент у автора статьи имеется готовое решение которое анализирует конфигурацию. На основании этого снимает все необходимые блокировки и взамен предоставляет свои готовые процедуры, используя которые вы можете реализовать блокировочный механизм на свое усмотрение. При этом, вставив сгенерированный текст процедуры в процедуру ПриНачалеРаботыСистемы вы гарантированно не будете зависеть от структурных изменений в конфигурации.

Подробнее о "гибких" блокировках читайте на сайте www.softpoint.ru.

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

Ипотека

+6%: вырастет ставка по Арктической ипотеке

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

Утренний бухгалтер № 5685. Изменят сроки сдачи ЕФС-1

Проект с поправками опубликован на федеральном портале.

Использование искусственного интеллекта станет отягчающим обстоятельством

Если группа мошенников применяет возможности искусственного интеллекта для обмана населения, наказание за преступление должно быть серьезнее.

Курсы повышения
квалификации

18
Официальное удостоверение с занесением в госреестр Рособрнадзора

ЦБ опубликовал методологию расчёта официальных курсов доллара и евро

Обратим внимание на основные моменты, которые полезно знать

Налог на ангелов, НДФЛ при разделе земли, антитуристический налог в финансовом обзоре

События в налоговой сфере

Бухгалтерам придется чаще сдавать отчет ЕФС-1. «Куда уж чаще?» — недовольны бухгалтеры. 🤦‍♀️«Ночной бухгалтер» № 1729

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

Иллюстрация: Вера Ревина Клерк.ру
Опытом делятся эксперты-практики, без воды

Исполнение лицензии EUROCLEAR

Сегодня мы получили заряд позитивного настроения, поздравили нашего клиента и теперь спешим поделиться этим настроением с Вами. Речь идет о получении персональной лицензии Казначейства Бельгии на разблокировку замороженных активов, учитываемых в EUROCLEAR, в адрес физического лица.

Исполнение лицензии EUROCLEAR
Интернет и IT

В Роскомнадзоре назвали риски развития искусственного интеллекта без достаточного регулирования законом

Советник гендиректора Главного радиочастотного центра (ГРЧЦ) по научно-техническому развитию Евгения Рыжова рассказала, что одна из сегодняшних тенденций в области ИИ – развитие технологий управления эмоциями.

Отпуска

СФР: работник может оформить отпуск на один период только по одному основанию

Родителю, находящемуся в отпуске по уходу за ребенком, ежегодный оплачиваемый отпуск в это время не предоставляется.

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

В доход семьи при комплексной оценке нуждаемости также входят трудовой заработок, пособия, алименты, проценты по вкладам, суммы от продажи имущества и т. п.

Ведение бизнеса

Минпромторг аккредитовал 19 объектов промышленной инфраструктуры и 7 промкластеров

Министерство промышленности и торговли во втором квартале 2024 года включило в федеральный реестр 26 промышленных кластеров, индустриальных парков и технопарков.

Курсы валют

Центробанк будет по-новому определять курс доллара и евро

Банк России отсечет крайние значения курса, которые выбиваются из среднего диапазона. Данные будут получены на основании сведений о внебиржевых торгах между банками.

Бесплатно с Расчеты с работниками

Как оплачивать работу в выходные и праздничные дни

Разбираем, по каким правилам платят зарплату за работу в выходные и праздничные дни.

Как оплачивать работу в выходные и праздничные дни

С 1 марта 2025 материнский капитал можно тратить на строительство жилых домов

Деньги на строительство жилого дома будут лежать на счете-эскроу. Подрядчик сможет их забрать после сдачи объекта.

Налог на имущество

Налог на имущество организаций: как рассчитывается и уплачивается

В Налоговом законодательстве действует термин «региональные налоги» (РН). Это обязательный сбор, который ФЛ и предприятия уплачивают в бюджет субъекта РФ: республики, края, области. Налог на имущество организаций – один из трех РН. По факту это налоговый сбор на недвижимое имущество, движимая собственность налогом не облагается.

Налог на имущество организаций: как рассчитывается и уплачивается
Товарный знак

Как оформить бренд за рубежом и выйти на иностранный рынок

Вывести свой продукт на новый рынок — ответственное решение. Неважно, хотите вы оказывать услуги за рубежом, продавать товары или продвигать собственное приложение / игру / сервис, нужно позаботиться о защите интеллектуальной собственности. 

Как оформить бренд за рубежом и выйти на иностранный рынок

Разработчик корпоративного софта VK Tech начал вести блог на «Клерке»

Теперь узнавать больше о том, как ведется налоговый мониторинг, вы сможете от разработчика! Уже сейчас можно написать отзыв о продуктах компании и о работе с ней и задать свой вопрос.

Разработчик корпоративного софта VK Tech начал вести блог на «Клерке»
НДС

Какие разделы декларации по НДС заполняют экспортеры

Экспортеры заполняют «экспортные» разделы декларации по НДС, исходя из правил, установленных для подтверждения нулевой ставки НДС.

Какие разделы декларации по НДС заполняют экспортеры
Платежные системы

У «ВкусВилла» появился свой платежный сервис EshPay

Покупатели смогут в пять раз быстрее оплачивать покупки через QR-код в мобильном приложении «ВкусВилл».

Интересные материалы

Чем руководитель отличается от лидера, и есть ли у них что-то общее?

В современном мире бизнеса все чаще звучат термины «руководитель» и «лидер». И многие предполагают, что у этих понятий одинаковый смысл. Однако на практике данные роли отличаются друг от друга и требуют особенных навыков и подходов.

Чем руководитель отличается от лидера, и есть ли у них что-то общее?