Возможности оптимизации блокировок в 1С

Для определения возможности оптимизации блокировок в 1С необходимо вспомнить о блокировках в СУБД MS SQL и системе 1С.

Так, используемый по умолчанию уровень изоляции Read Committed использует следующие блокировки:

Возможности оптимизации блокировок в 1С

Блокировки «полезные», иначе получим проблему «грязного чтения». Что можно сделать для оптимизации в первую очередь — это уменьшить время и количество блокировок.

Что бы уменьшить время и количество «S» блокировок при чтении данных, необходимо оптимизировать запросы так, что бы они выполнялись быстро и без лишних блокировок (этот вопрос будет обсуждаться в отдельном разделе «Оптимизация запросов»). При записи — изменять данные как можно ближе к концу транзакции. Для этого в платформе предусмотрены следующие настройки:
Режим удаления движений документа (вкладка «Движения»):
• удалять автоматически при отмене проведения – по умолчанию;
• удалять автоматически – движения удалятся (запишутся пустые наборы непосредственно перед обработкой проведения и установится X блокировка до конца транзакции);
• не удалять автоматически.

Если движения автоматически не удаляются, то это может повлиять на алгоритм проведения (например на контроль остатков). Тогда необходимо записать пустой набор непосредственно перед запросом остатков:
// Запишем пустые наборы записей, чтобы читать резервы без учета данных в документе.
Движения.РезервыНоменклатуры.Записать();
Результат = Запрос2.Выполнить();

Также надо учитывать существующие записи при использовании записи с добавлением записей из набора «Записать(Ложь)»

Варианты записи движений:
1. Запись вручную каждого набора используя «Движения.ИмяНабора.Записать()»;
2. Запись определенного списка наборов в соответствии со свойством документа «Запись движений при проведении»:
Свойство документа «Запись движений при проведении» определяет список наборов для записи:
«Записывать выбранные» — устанавливается по умолчанию. При этом список наборов для записи определяется свойством «Записывать» каждого набора (Движения.ИмяНабора.Записывать = Истина)
«Записывать модифицированные» — при этом список наборов для записи будет состоять из наборов с установленным свойством «Модифицированность».

В соответствии со свойством «Запись движения при проведении» все «Выбранные» или «Модифицированные» наборы записей записываются автоматически непосредственно после обработки проведения:
КонецПроцедуры //Обработка проведения
Наборы записываются последовательно в соответствии с их порядком в дереве конфигурации:

  • Регистры сведений;
  • Регистры накопления;
  • Регистры бухгалтерии;
  • Регистры расчета.

Записать наборы, в соответствии со свойством документа «Запись движения при проведении», можно и вручную, используя «Движения.Записать()».

Не путать метод «Записать()» коллекции движений «Движения» с методом «Записать()» набора записей (элемента коллекции движений).
После записи набора, независимо каким способом он записан, его свойства «Записывать» и «Модифицированность» сбрасываются в «Ложь».

Автоматическая запись движений непосредственно после обработки проведения как и ручная с использованием «Движения.Записать()» записывают наборы с замещением записей, аналогично ручной записи конкретного набора «Движения.ИмяНабора.Записать(Истина)»

Свойства документа «Привилегированный режим при проведении» и «Привилегированный режим при отмене проведения» могут существенно ускорить запись наборов, так как при этом не проверяются права доступа.

Использование обработчиков событий в транзакции

Запись документа (объекта) происходит между обработчиками «ПередЗаписью()» и «ПриЗаписи()». В обработчике «ПриЗаписи()» уже можно использовать ссылку на объект.

Так же между обработчиками «ПередЗаписью()» и «ПриЗаписи()» происходит заполнение регистрации в последовательности, если для документа установлено автоматическое заполнение последовательности. В обработчике «ПриЗаписи()» можно изменить или очистить набор регистрации в последовательности.

Если для документа установлен параметр «Автоматическое удаление движений при проведении», то движения документа удаляются непосредственно перед обработчиком «ОбработкаПроведения()». Автоматическая запись движений документа (наборов с установленным признаком модифицированности или «Записывать») производится непосредственно после обработчика «ОбработкаПроведения()». Процедура «ОбработкаПроведения()» и связанные с нею операции автоматического удаления/записи движений выполняются только если документ записывается в режиме записи «Проведение».

Все обработчики, которые выполняются в транзакции имеют параметр «Отказ». Но не наоборот! Есть обработчики, которые имеют параметр «Отказ», но выполняются вне транзакции. Это обработчики, которые выполняются до транзакции, например обработчик формы «ПередЗаписью()».

Возможности оптимизации блокировок в 1С

В случае управляемого интерфейса имеются ввиду именно серверные процедуры «ПередЗаписьНаСервере()», «ПриЗаписиНаСервере()» и «ПослеЗаписиНаСервере()».

Разделитель итогов и параллельность записи наборов в транзакции

В таблицы итогов регистров хранятся итоговые данные (Начальные остаток, Приход, Расход, Конечный остаток) в разрезе всех измерений с периодичностью «Месяц». Также в таблицах итогов регистров накопления остатков и бухгалтерии хранятся текущие итоги, с периодом 3999 год (если используется смещение дат, то 5999).
При параллельной записи в таблицы итогов (из разных сеансов, разными регистраторами) по одинаковым наборам измерений и периода (полей) возникает ожидание блокировки:

Возможности оптимизации блокировок в 1С

Для исключения таких блокировок применяется разделитель итогов — в таблицы итогов добавляется служебное поле «Splitter». Каждому одновременно работающему сеансу назначается свое значение разделителя. Каждый сеанс записывает данные в таблицы итогов со своим значением разделителя. В таблице итогов будет столько разных значений разделителя сколько одновременных сеансов будут вести запись в регистр. Также поле «Splitter» включается в кластерный индекс таблицы итогов. Так как при использовании разделителя одновременные сеансы записывают данные в таблицы итогов по разному составу полей (из-за значения разделителя), блокировки при записи исключаются:

Возможности оптимизаций блокировок в 1С

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

Возможности оптимизации блокировок в 1С
Конкретное использование разделителя для регистра указывается в форме управления итогами:

Возможности оптимизаций блокировок в 1С

Разделитель можно применять только для регистров, имеющих итоги (регистры накопления и регистры бухгалтерии).
Применение разделителя исключает блокировки при записи в регистры, но несколько «раздувает» базу и уменьшает скорость чтения (при выполнении запросов по итогам агрегируются данные не только по измерениям и периоду, но еще и по полю «Splitter»).
При пересчете итогов итоги агрегируются (суммируются) без учета разделителя. Поле разделителя при этом очищается.

Уровень изоляции READ_COMMITTED_ SNAPSHOT в версии 8.3

Платформа версии 8.3 применяется модифицированный уровень изоляции READ_COMMITTED_SNAPSHOT, появившийся в В MS SQL Server 2005 и реализующий режим версионирования, не использовавшийся в СУБД MS SQL ранее. Поведение на уровне READ COMMITTED зависит от настройки аргумента базы данных READ_COMMITTED_SNAPSHOT.
Если параметр READ_COMMITTED_SNAPSHOT находится в состоянии OFF, компонент Database Engine при выполнении операций считывания текущей транзакцией для предотвращения изменения строк другими транзакциями использует разделяемые блокировки. Разделяемые блокировки также блокируют инструкции от считывания строк, измененных другими транзакциями, пока не завершится другая транзакция. По завершении инструкции разделяемые блокировки снимаются.
Если параметр READ_COMMITTED_SNAPSHOT находится в состоянии ON, компонент Database Engine использует управление версиями строк для представления каждой инструкции согласованного на уровне транзакций моментального снимка данных в том виде, который они имели на момент начала выполнения инструкции. Для защиты данных от обновления другими транзакциями блокировки не используются.

Возможности оптимизации блокировок в 1С

 

Как работает версионирование

Например есть несколько, параллельно выполняющихся, транзакций, читающие одни и те же данные. В обычном режиме READ_COMMITTED, MS SQL Server перед чтением делает попытку наложить разделяемую блокировку на нужный ресурс (S блокировка при чтении). При включенном версионировании вместо попытки установки разделяемой блокировки, транзакция прочитает нужные данные из базы tempdb, куда транзакция, которая успела изменить данный, скопировала версию данных до изменения. При изменении данных в транзакции с уровнем изоляции READ_COMMITTED_SNAPSHOT версия данных до изменения предварительно помещается из основной базы в tempdb. После выполнения транзакции, помещенная ею в tempdb версия данных будет удалена.

Возможности оптимизации блокировок в 1С

 

SQL команды установки параметров уровня изоляции после реструктуризации:

Запуск 1С при установке совместимости 8.2:

ALTER DATABASE test83 SET READ_COMMITTED_SNAPSHOT OFF WITH ROLLBACK IMMEDIATE
SET LOCK_TIMEOUT 20000
SET TRANSACTION ISOLATION LEVEL READ COMMITTED

Запуск 1С при установке совместимости 8.3:
ALTER DATABASE test83 SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE
SET LOCK_TIMEOUT 20000
SET TRANSACTION ISOLATION LEVEL READ COMMITTED

Определить состояние базы можно запросом:
select name,snapshot_isolation_state_desc,is_read_committed_snapshot_on from sys.databases

Posted in Блог Оптимизации 1С.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *