Константы. Распостраненная ошибка

19 января 2013

Предисловие

КонстантаПлатформа 1С:Предприятие 8.x поддерживает работу с таким объектом конфигурации как "Константа". Этот объект служит для хранения редко изменяющихся данных. Например, в типовых конфигурациях он используется для хранения названия компании, для которой ведется учет в программе. Подробнее о константах Вы можете узнать по ссылке, в статье же будет идти речь о распространенной ошибке использования данного объекта в прикладных решениях.

Суть проблемы

Методика разработки фирмы "1С" не просто так говорит, что константы предназначены для хранения редко изменяемой информации. Дело в том, что в базе данных каждая из констант хранится в отдельной таблице, где ее значение представлено единственной (!) записью. Название таблицы начинается с "_Const", а состав ее колонок зависит от типа данных константы, заданного в конфигураторе (подробнее о хранении типов данных платформы на стороне MS SQL Вы можете узнать здесь).

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

Таблицы констант составного типа и типа "строка"

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

Ошибка конфликта блокировок (файловый вариант работы)

Для клиент-серверного варианта работы ошибка будет выглядеть следующим образом:

Ошибка конфликта блокировок (клиент-серверный вариант работы)

Примечание: время ожидания на блокировке настраивается в свойствах информационной базы. Для этого в режиме конфигуратора нужно перейти "Администрирование ->  Параметры информационной базы" и установить время в секундах в поле "Время ожидания блокировки данных". 

Настройка параметров информационной базы

Именно этот интервал времени ожидает платформа, прежде чем показать ошибку о  конфликте блокировок.

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

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

Реальный пример

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

Используемые объекты тестовой конфигурации

Соответственно, при записи элемента справочника "Товары", ему в реквизит "IDСайта"  присваивается значение константы "ПоследнийIDСайта", и при успешной записи элемента значение константы увеличивается на единицу. Тип значения реквизита справочника и самой константы  - "число".

Что мы в итоге имеем? Если при работе с информационной базой несколько пользователей одновременно создают элемент справочника "Товары", то возникает ожидание на блокировке данных для тех пользователей, которые начали записывать элемент позже.

Кроме того, из-за блокировок уникальность значения ID может не соблюдаться (!).

На следующем видео данная ошибка продемонстрирована со стороны работы двух пользователей.

Мы видим, что производительность программы значительно снизилась из-за ожидания на блокировке константы, причем на видео показана работа всего четырех пользователей! Как вы думаете, что бы изменилось, если с номенклатурой работало одновременно 50 человек?

КАК СДЕЛАТЬ ПРАВИЛЬНО?

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

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

НЕМНОГО ВЫВОДОВ

Неправильное использование констант, как было показано выше, может привести к значительному снижению производительности системы. Замедление работы системы будет тем заметнее, чем больше пользователей работают с платформой 1С:Предприятие 8.x. 

Если вариант использования GUID'ов нельзя использовать, так как нет возможности внести доработки на сайте, то можно использовать регистр сведений для хранения значений ID для сайта в измерении, что позволит сохранить его уникальность. При записи, если значение ID не уникальное, нужно получить доступное возможное значение в таблице. В таком случае хоть и придется использовать дополнительный объект конфигурации, отрицательного воздействия на производительность можно избежать.

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

P.S. Обратите внимание на то, какая подсистема открывается при запуске в тестовой конфигурации. Как это сделать Вы можете узнать по ссылке.

 


comments powered by Disqus