При работе с 1С:Предприятие 7.7 в связке с MS SQL Server 2005 пользователи могут столкнуться с крайне неприятным и трудно диагностируемым поведением: программа начинает спонтанно зависать, особенно у терминальных пользователей, при выполнении определенных операций. Давайте подробно рассмотрим этот феномен, выясним его причины и предложим конкретные шаги для устранения.
Проблема проявляется в случайных зависаниях 1С 7.7 на, казалось бы, ровном месте. Чаще всего это происходит у терминальных пользователей. Интересно, что пользователи, работающие с локальных машин, подобных трудностей не испытывают. Более того, если развернуть копию базы на другом сервере и подключиться к ней с того же терминала, где наблюдались сбои, все работает стабильно.
Рассмотрим конкретные примеры зависаний:
На этапе диагностики мы можем столкнуться с рядом неочевидных фактов:
Соединение (например, Соединение.ВыполнитьSQL()) также приводит к зависанию.Дальнейшее изучение проблемы выявило, что при выполнении некоторых запросов через ODBC-драйвер, через 20 секунд возвращается ошибка 24000: «недопустимое состояние курсора». Это указывает на проблемы на уровне взаимодействия между 1С, ODBC-драйвером и SQL Server.
Приведем примеры запросов, которые демонстрируют проблему:
// Этот запрос, как правило, вызывает зависание или ошибку
select * from SC17170 (NOLOCK) where row_id=(Select min(row_id) from SC17170 sc_2(NOLOCK) where sc_2.DESCR=(select
min(DESCR) from SC17170 sc_3(NOLOCK) where sc_3.DESCR>='БИ' and sc_3.DESCR<='БИяяя' ))
// Этот запрос работает корректно
select * from SC17170 (NOLOCK) where row_id=(Select min(row_id) from SC17170 sc_2(NOLOCK) where sc_2.DESCR=(select
min(DESCR) from SC17170 sc_3(NOLOCK) where sc_3.DESCR>='БУ' and sc_3.DESCR<='БУяяя' ))
Из этих примеров становится ясно, что проблема не в самой структуре запроса или данных, а в их обработке при определенных условиях, связанных с фильтрацией по данным, начинающимся на «БИ».
Дальнейшее исследование проблемы позволило выделить несколько критически важных деталей:
SELECT *: Если в проблемном запросе вместо SELECT * (выбора всех полей) явно перечислить необходимые поля, запрос начинает работать! Это крайне важный момент, указывающий на то, что проблема может быть связана с метаданными или тем, как ODBC-драйвер/1С обрабатывает информацию обо всех столбцах.SET NOCOUNT ON: Еще одно удивительное наблюдение: если перед проблемным запросом добавить оператор SET NOCOUNT ON, запрос также начинает выполняться без зависаний.Эти зацепки привели нас к гипотезе: проблема явно кроется в прослойке ODBC -> MSSQL. Возможно, что-то в работе ODBC-драйвера или его взаимодействии с SQL Server некорректно обрабатывается 1С 7.7, особенно при получении метаданных или информации о количестве затронутых строк.
После тщательного анализа и экспериментов, была выявлена комбинация факторов, приводящая к описанным зависаниям:
Причина: Конфликт между обновлением Windows KB948963 и включенной опцией «Force Encryption» (принудительное шифрование) в настройках MS SQL Server для ODBC-соединений.
Рассмотрим эти два компонента подробнее:
Итоговое решение проблемы состоит в одном из двух действий:
После выполнения одного из этих действий (или обоих для надежности) работа 1С 7.7 с MS SQL Server 2005 должна вернуться в нормальное русло.
Чтобы глубже понять, почему именно это решение работает, давайте разберем, как влияют обнаруженные детали:
Ошибка 24000, или SQLSTATE 24000, означает «invalid cursor state». Она обычно возвращается ODBC-драйвером версии 3.x и выше, когда приложение пытается выполнить операцию с курсором, который не находится в допустимом для этой операции состоянии (например, курсор не был открыт, или операция выполняется после закрытия курсора). В контексте проблем с KB948963 и force encryption, эта ошибка может указывать на:
SET NOCOUNT ON?Оператор SET NOCOUNT ON указывает SQL Server не отправлять клиенту сообщения о количестве затронутых строк после выполнения каждого оператора Transact-SQL или хранимой процедуры. По умолчанию, SQL Server отправляет такие сообщения. Например, после выполнения INSERT, UPDATE, DELETE или SELECT, клиент получает информацию о количестве измененных/выбранных строк.
В данном случае:
NOCOUNT позволяет избежать этой потенциальной точки сбоя.Использование SET NOCOUNT ON перед выполнением прямых SQL-запросов из 1С 7.7 является хорошей практикой в целом, так как это снижает нагрузку на сеть и клиентское приложение, улучшая производительность.
SELECT *) решает проблему?Когда мы используем SELECT *, SQL Server и ODBC-драйверу необходимо получить полную информацию обо всех столбцах таблицы, включая их имена, типы данных, размеры и другие метаданные. Эта информация передается клиенту перед началом передачи самих данных.
Если возникают проблемы на уровне шифрованного соединения или с ODBC-драйвером, процесс получения и обработки этих обширных метаданных для всех столбцов может оказаться уязвимым. Например:
SELECT *, что проявляется только при запросе всех полей.Явное перечисление полей уменьшает объем и сложность метаданных, которые необходимо обработать, и, таким образом, обходит узкое место, вызванное конфликтом шифрования и обновления Windows.
Давайте разберем по шагам, как можно применить предложенное решение:
На всех серверах, где работает 1С 7.7 (включая терминальные серверы), выполните следующие действия:
Это действие выполняется на сервере MS SQL Server 2005. Для этого используйте «SQL Server Configuration Manager»:
Также можно проверить и изменить эту настройку через реестр (но это менее предпочтительный способ и требует большей осторожности):
// Путь в реестре (может отличаться в зависимости от версии и экземпляра)
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL.1\MSSQLServer\SuperSocketNetLib
// Параметр: ForceEncryption (REG_DWORD)
// 0 = No (отключено), 1 = Yes (включено)
Перед любыми изменениями в реестре создайте резервную копию соответствующей ветки.
Хотя официальная поддержка 1С 7.7 для MS SQL Server 2005 и более поздних версий отсутствует, на практике многие компании успешно используют такую связку, применяя ряд «ухищрений»:
Cyrillic_General_CI_AS.80).BkEnd.dll: Иногда для обхода проверки версии SQL Server может потребоваться «патчинг» файла BkEnd.dll платформы 1С 7.7.Multiple («Properties - Options - State - Restrict access»).Важно отметить, что переход на новые версии 1С:Предприятие (например, 8.3) для крупных самописных систем является сложным и дорогостоящим проектом. Он требует значительных временных и финансовых затрат на переписывание конфигурации, миграцию данных и покупку лицензий. При этом не всегда гарантирует мгновенный прирост производительности, особенно для систем, изначально оптимизированных под специфику 1С 7.7.
Мы надеемся, что данный подробный анализ и предложенное решение помогут вам успешно справиться с «непонятным поведением» 1С 7.7 в вашей инфраструктуре.