При эксплуатации крупных информационных баз 1С:Предприятие 7.7 на современных версиях СУБД системные администраторы и разработчики часто сталкиваются с жесткими техническими ограничениями. В MS SQL Server 2012 уровень обратной совместимости со старыми базами (уровень 80, соответствующий SQL Server 2000) был полностью упразднен. Возникает закономерный вопрос: насколько стабильно работает связка 1С 7.7 с MS SQL Server 2008 и MS SQL Server 2012 в режиме совместимости по умолчанию (уровни 100 и 110), какие «подводные камни» возникают при промышленной эксплуатации и как устранить критические просадки производительности?
Разберем практический опыт и детальные технические шаги, позволяющие эксплуатировать базы данных размером от 50 до 500 ГБ с числом активных пользователей более 100 человек без отката уровня совместимости.
Проанализируем ключевые причины, из-за которых штатный исполняемый файл платформы 7.7 дает сбой или приводит к колоссальным зависаниям на новых СУБД:
sp_dboption: начиная с SQL Server 2012, процедура sp_dboption отсутствует в СУБД. Платформа 1С 7.7 вызывает её при попытке входа в монопольном режиме и при сохранении метаданных в конфигураторе. При её отсутствии монопольный вход и реструктуризация блокируются.ПодчиненныеДокументы(): штатный механизм 1С при выборке подчиненных документов без явного указания дат генерирует запрос с фиктивной максимальной датой (31.12.9999). В оптимизаторе запросов SQL Server 2008/2012 это приводит к выбору плана Index Scan (полное сканирование индекса) по таблицам _1SCRDOC и _1SJOURN вместо точечного поиска Index Seek, вызывая блокировки и тайм-ауты.sysprocesses: штатный движок платформы опрашивает master..sysprocesses для проверки числа активных сеансов. В новых версиях SQL Server пользователь без полных прав администратора видит только свои процессы, что приводит к ложным ошибкам о невозможности блокировки базы.sqlsrv32.dll), выдавая ошибку при подключении через современные ОС.Выясним причину критических тормозов: когда в коде 1С 7.7 вызывается стандартный метод выборки подчиненных документов без передачи временного диапазона, запрос зависает из-за смены логики кардинальности оптимизатора SQL.
Рассмотрим два способа исправления этой проблемы:
Способ А. Быстрое исправление в штатном коде (указание интервала дат)
Если требуется устранить проблему максимально быстро без масштабного переписывания логики, достаточно передать в метод границы дат. Оптимизатор SQL Server при наличии хотя бы одной границы использует совершенно другой план выполнения, который выполняется мгновенно:
// Было: медленный запрос со сканированием таблицы
Док = СоздатьОбъект("Документ");
Док.ВыбратьПодчиненныеДокументы(,, ТекущийДокумент);
// Стало: ограничение интервалом дат
ДатаНач = ТекущийДокумент.ДатаДок - 100; // отступаем 100 дней назад
ДатаКон = ТекущийДокумент.ДатаДок + 100; // либо РабочаяДата()
Док.ВыбратьПодчиненныеДокументы(ДатаНач, ДатаКон, ТекущийДокумент);
Если для бизнес-логики необходима вся история за длительный период, можно указать интервал даже в десятки лет назад — передача конкретной даты исключает подстановку фиктивного значения 31.12.9999 и заставляет оптимизатор применять точечный Index Seek.
Способ Б. Переход на прямые запросы через 1С++
Для высоконагруженных систем с базой объемом свыше 50–100 ГБ наиболее эффективным решением является использование внешней компоненты 1С++ и прямых SQL-запросов. Это полностью снимает нагрузку с движка платформы и позволяет выбирать только нужные поля, фильтровать подчиненные документы по видам и статусу проведения прямо на уровне СУБД:
ЗапросSQL = СоздатьОбъект("ODBCRecordset");
ТекстЗапроса = "
|SELECT
| Doc.IDDOC as [Док $Документ]
|FROM
| _1SCRDOC as Links WITH (NOLOCK)
|INNER JOIN
| _1SJOURN as Doc WITH (NOLOCK) ON Links.CHILD_DATE_TIME_IDDOC = Doc.DATE_TIME_IDDOC
|WHERE
| Links.PARENTVAL = :ВыбРодитель
|";
ЗапросSQL.УстановитьТекстовыйПараметр("ВыбРодитель", ТекущийДокумент);
ТЗ = ЗапросSQL.ВыполнитьИнструкцию(ТекстЗапроса);
Разберем по шагам, как решить проблему отсутствия процедуры sp_dboption на стороне MS SQL Server 2012 и выше. Для этого создадим замещающую процедуру в базе данных master, которая будет транслировать устаревшие команды платформы в актуальные инструкции T-SQL:
USE [master]
GO
CREATE PROCEDURE [dbo].[sp_dboption]
@dbname sysname = NULL,
@optname varchar(35) = NULL,
@optvalue varchar(10) = NULL
AS
BEGIN
SET NOCOUNT ON;
IF @optname = 'single user'
BEGIN
IF @optvalue = 'TRUE'
EXEC('ALTER DATABASE [' + @dbname + '] SET SINGLE_USER WITH ROLLBACK IMMEDIATE');
ELSE
EXEC('ALTER DATABASE [' + @dbname + '] SET MULTI_USER');
END
END
GO
Данная процедура перехватывает команды 1С 7.7 при открытии базы в монопольном режиме и корректно переключает базу данных.
Посмотрим на проблему контроля сессий пользователей. 1С 7.7 использует обращение к sysprocesses для определения числа работающих пользователей и блокировок.
Для того чтобы учетная запись базы данных могла опрашивать сессии всех пользователей, необходимо выполнить команду назначения прав:
USE [master]
GO
GRANT VIEW SERVER STATE TO [ИмяПользователя1С];
GO
Если в инфраструктуре используется модифицированное системное представление, убедимся, что права на чтение master..sysprocesses открыты для роли, под которой авторизуются пользователи 1С.
Платформа 1С 7.7 исторически проектировалась под однопоточные запросы. При использовании современных многоядерных процессоров оптимизатор SQL Server может строить параллельные планы с распараллеливанием одного запроса на несколько ядер. Это приводит к ожиданиям типа CXPACKET и взаимным блокировкам пользовательских транзакций.
tempdb на несколько файлов данных одинакового размера (по числу физических ядер процессора, обычно от 4 до 8 файлов). Для SQL Server 2008/2012 рекомендуется включить флаг трассировки 1118 для предотвращения конфликтов распределения экстентов.BIN платформы пустой файл OrdNoChk.prm.Практика промышленной эксплуатации показывает, что при выполнении указанных настроек базы данных объемом 150–500 ГБ на 70–180 одновременных пользователей стабильно и быстро функционируют на MS SQL Server 2008 и 2012 без включения режима пониженной совместимости.