Проблема "грязного чтения" в запросах (1С-SQL)   

Те, кто часто строит отчеты в 1С-SQL, могли заметить, что иногда отчеты выдают сведения, не соответствующие действительности. Однако если при этом запустить отчет повторно с теми же параметрами, то при втором построении он дает правильные данные. Лично я не раз сталкивался с этим эффектом, который приводит пользователей базы в полное замешательство.

Но данный эффект имеет простое и логичное объяснение. Если исследовать в SQL-профайлере тексты посылаемых на сервер запросов 1С, то многое становится ясным. Для того чтобы уменьшить проблемы с блокировками данных, разработчики платформы во всех запросах на чтение данных пользуются подсказками блокировки (NOLOCK). Что это за подсказка? Эта подсказка означает следующее – выражение, использующее данную подсказку при выполнении, не только не устанавливает никаких блокировок, но и не принимает во внимание блокировки, включая эксклюзивные. Таким образом, в результате использования данной подсказки выполняемый запрос может прочитать нужные данные независимо от их статуса блокировки. Этим достигается высокая скорость работы запросов в 1С-SQL, но отсюда вытекают и проблемы, в частности рассматриваемая.

Итак, отчего в отчете получаются неверные данные. Это происходит при многопользовательской работе в моменты, когда один пользователь запускает отчет, а другой проводит документы, причем не создает новые, а когда перепроводит документы, бывшие проведенными. То есть – при операции перепроведения документа.

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

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

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


 


 

Перепечатка, воспроизведение в любой форме, распространение, в том числе в переводе, любых материалов с сайта www.softpoint.ru возможны только с письменного разрешения компании "СофтПоинт". Это правило действует для всех без исключения случаев, кроме тех, когда в материале прямо указано разрешение на копирование (основание: Закон Российской Федерации "Об авторском праве и смежных правах").