Как решить проблему зависания 1С 7.7 с MS SQL Server 2005 у терминальных пользователей?

Системный администратор 1С v7.7
← На главную

При работе с 1С:Предприятие 7.7 в связке с MS SQL Server 2005 пользователи могут столкнуться с крайне неприятным и трудно диагностируемым поведением: программа начинает спонтанно зависать, особенно у терминальных пользователей, при выполнении определенных операций. Давайте подробно рассмотрим этот феномен, выясним его причины и предложим конкретные шаги для устранения.

Анализируем симптомы проблемы

Проблема проявляется в случайных зависаниях 1С 7.7 на, казалось бы, ровном месте. Чаще всего это происходит у терминальных пользователей. Интересно, что пользователи, работающие с локальных машин, подобных трудностей не испытывают. Более того, если развернуть копию базы на другом сервере и подключиться к ней с того же терминала, где наблюдались сбои, все работает стабильно.

Рассмотрим конкретные примеры зависаний:

  1. Подбор элементов в справочниках: В системе с самописной конфигурацией, например, подбор в справочнике для элементов, начинающихся на «БУ», работает корректно, а для элементов на «БИ» – приводит к полному зависанию 1С.
  2. Открытие документов: Документы, содержащие определенное количество строк (например, 14), могут вызывать зависание. При этом, если изменить количество строк (добавить или удалить), документ начинает открываться без проблем.

Диагностика и первичные выводы

На этапе диагностики мы можем столкнуться с рядом неочевидных фактов:

  1. Логи пусты: В логах 1С и Windows Event Log отсутствуют какие-либо записи, указывающие на причину сбоя.
  2. SQL Profiler: В профилировщике SQL Server видно, что запрос от 1С поступает на сервер, корректно выполняется и переходит в статус «выполнен». Однако после этого 1С не получает данные или не может их обработать, и просто останавливается.
  3. Ручное выполнение запросов: Если тот же самый запрос, на котором 1С зависает, попробовать выполнить напрямую в SQL Server Management Studio (SSMS), он отрабатывает без проблем.
  4. Прямые запросы из 1С: Попытка выполнить проблемный запрос из 1С с использованием прямого SQL-запроса через объект Соединение (например, Соединение.ВыполнитьSQL()) также приводит к зависанию.
  5. Тестовая программа через ODBC: Парадоксально, но если тот же запрос выполнить из сторонней тестовой программы, использующей ODBC-соединение, он работает без нареканий.

Дальнейшее изучение проблемы выявило, что при выполнении некоторых запросов через 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<='БУяяя' ))

Из этих примеров становится ясно, что проблема не в самой структуре запроса или данных, а в их обработке при определенных условиях, связанных с фильтрацией по данным, начинающимся на «БИ».

Ключевые зацепки и дополнительные наблюдения

Дальнейшее исследование проблемы позволило выделить несколько критически важных деталей:

  1. Зависимость от SELECT *: Если в проблемном запросе вместо SELECT * (выбора всех полей) явно перечислить необходимые поля, запрос начинает работать! Это крайне важный момент, указывающий на то, что проблема может быть связана с метаданными или тем, как ODBC-драйвер/1С обрабатывает информацию обо всех столбцах.
  2. Эффект SET NOCOUNT ON: Еще одно удивительное наблюдение: если перед проблемным запросом добавить оператор SET NOCOUNT ON, запрос также начинает выполняться без зависаний.

Эти зацепки привели нас к гипотезе: проблема явно кроется в прослойке ODBC -> MSSQL. Возможно, что-то в работе ODBC-драйвера или его взаимодействии с SQL Server некорректно обрабатывается 1С 7.7, особенно при получении метаданных или информации о количестве затронутых строк.

Корневая причина и окончательное решение

После тщательного анализа и экспериментов, была выявлена комбинация факторов, приводящая к описанным зависаниям:

Причина: Конфликт между обновлением Windows KB948963 и включенной опцией «Force Encryption» (принудительное шифрование) в настройках MS SQL Server для ODBC-соединений.

Рассмотрим эти два компонента подробнее:

  1. Обновление Windows KB948963: Это обновление безопасности от Microsoft, которое, как выяснилось, может вызывать проблемы совместимости с некоторыми ODBC-драйверами, особенно в контексте специфических сетевых взаимодействий или шифрования. Удаление этого обновления часто восстанавливает нормальную работу.
  2. «Force Encryption» в MSSQL: Эта настройка на сервере SQL Server принуждает все клиентские соединения использовать шифрование, независимо от того, запросил ли его клиент или нет. Более старые ODBC-драйверы, используемые 1С 7.7, или сама платформа 7.7 могли некорректно обрабатывать такие принудительно зашифрованные соединения, что приводило к ошибкам или зависаниям из-за проблем с рукопожатием, обменом ключами или обработкой зашифрованных пакетов данных.

Итоговое решение проблемы состоит в одном из двух действий:

  1. Удаление обновления KB948963: Если это обновление установлено на сервере 1С или на терминальных серверах, где наблюдаются проблемы, его удаление может немедленно решить проблему.
  2. Отключение «Force Encryption»: В настройках SQL Server Configuration Manager (или через SQL Server Management Studio) для используемого экземпляра SQL Server необходимо отключить принудительное шифрование для ODBC-соединений.

После выполнения одного из этих действий (или обоих для надежности) работа 1С 7.7 с MS SQL Server 2005 должна вернуться в нормальное русло.

Подробнее о механизмах, стоящих за решением

Чтобы глубже понять, почему именно это решение работает, давайте разберем, как влияют обнаруженные детали:

1. Почему возникает ошибка 24000: «недопустимое состояние курсора»?

Ошибка 24000, или SQLSTATE 24000, означает «invalid cursor state». Она обычно возвращается ODBC-драйвером версии 3.x и выше, когда приложение пытается выполнить операцию с курсором, который не находится в допустимом для этой операции состоянии (например, курсор не был открыт, или операция выполняется после закрытия курсора). В контексте проблем с KB948963 и force encryption, эта ошибка может указывать на:

  1. Потеря сетевого соединения: Шифрование или обновление Windows могли вызвать нестабильность в сетевом канале или некорректное завершение соединения, что приводило к тому, что открытый курсор становился «невалидным» для дальнейшей работы.
  2. Некорректная обработка состояния драйвером: Драйвер мог некорректно обрабатывать ответы сервера или состояния соединения при шифровании, особенно после получения пакета данных, что в итоге приводило к неправильной оценке состояния курсора.

2. Почему помогает SET NOCOUNT ON?

Оператор SET NOCOUNT ON указывает SQL Server не отправлять клиенту сообщения о количестве затронутых строк после выполнения каждого оператора Transact-SQL или хранимой процедуры. По умолчанию, SQL Server отправляет такие сообщения. Например, после выполнения INSERT, UPDATE, DELETE или SELECT, клиент получает информацию о количестве измененных/выбранных строк.

В данном случае:

  1. Снижение сетевого трафика: Отключение этих сообщений уменьшает объем данных, передаваемых по сети. В условиях нестабильного или некорректно обрабатываемого шифрованного соединения это может предотвратить таймауты или ошибки.
  2. Проблемы парсинга 1С 7.7: Возможно, 1С 7.7 или используемый ею ODBC-драйвер имеют специфические проблемы с парсингом или обработкой этих сообщений о количестве строк, особенно когда они приходят по зашифрованному каналу, который сам по себе работает нестабильно. Отключение NOCOUNT позволяет избежать этой потенциальной точки сбоя.

Использование SET NOCOUNT ON перед выполнением прямых SQL-запросов из 1С 7.7 является хорошей практикой в целом, так как это снижает нагрузку на сеть и клиентское приложение, улучшая производительность.

3. Почему явное перечисление полей (вместо SELECT *) решает проблему?

Когда мы используем SELECT *, SQL Server и ODBC-драйверу необходимо получить полную информацию обо всех столбцах таблицы, включая их имена, типы данных, размеры и другие метаданные. Эта информация передается клиенту перед началом передачи самих данных.

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

  1. Объем метаданных: Для таблиц с большим количеством столбцов или столбцами со сложными типами данных объем передаваемых метаданных может быть значительным. Сбой в этом процессе может привести к зависанию.
  2. Корректность метаданных: Возможно, некоторые поврежденные индексы (как предполагалось в одном из сообщений) или некорректные данные в таблице могут влиять на генерацию метаданных для SELECT *, что проявляется только при запросе всех полей.
  3. Ошибка обработки драйвером: ODBC-драйвер или 1С 7.7 могут некорректно обрабатывать полный набор метаданных, полученных по зашифрованному каналу, тогда как с небольшим, явно указанным набором полей таких проблем не возникает.

Явное перечисление полей уменьшает объем и сложность метаданных, которые необходимо обработать, и, таким образом, обходит узкое место, вызванное конфликтом шифрования и обновления Windows.

Шаги по применению решения

Давайте разберем по шагам, как можно применить предложенное решение:

  1. Проверка наличия обновления KB948963:

    На всех серверах, где работает 1С 7.7 (включая терминальные серверы), выполните следующие действия:

    1. Откройте «Панель управления» -> «Программы и компоненты».
    2. В левой части окна выберите «Просмотр установленных обновлений».
    3. В строке поиска (обычно в правом верхнем углу) введите «KB948963» и проверьте его наличие.
    4. Если обновление найдено, рассмотрите возможность его удаления. Обратите внимание, что удаление обновлений безопасности может повлиять на общую безопасность системы, поэтому прежде чем удалять, обязательно сделайте резервную копию системы и проконсультируйтесь с администратором безопасности.
  2. Проверка и отключение «Force Encryption» на SQL Server:

    Это действие выполняется на сервере MS SQL Server 2005. Для этого используйте «SQL Server Configuration Manager»:

    1. Откройте «SQL Server Configuration Manager».
    2. В левом меню разверните узел «SQL Server Network Configuration».
    3. Выберите «Protocols for MSSQLSERVER» (или имя вашего экземпляра SQL Server).
    4. В правой панели найдите пункт «Force Encryption» (или «Принудительное шифрование»).
    5. Щелкните по нему правой кнопкой мыши, выберите «Properties» (Свойства).
    6. Убедитесь, что для параметра «Force Encryption» установлено значение «No» (Нет). Если установлено «Yes», измените на «No».
    7. После изменения настроек обязательно перезапустите службу SQL Server для применения изменений.

    Также можно проверить и изменить эту настройку через реестр (но это менее предпочтительный способ и требует большей осторожности):

    
    // Путь в реестре (может отличаться в зависимости от версии и экземпляра)
    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+

Хотя официальная поддержка 1С 7.7 для MS SQL Server 2005 и более поздних версий отсутствует, на практике многие компании успешно используют такую связку, применяя ряд «ухищрений»:

  1. Режим аутентификации: Установите на SQL Server «Mixed Mode» (аутентификация Windows и SQL Server).
  2. Кодировка (collation): Для сервера SQL Server рекомендуется использовать сопоставление кодировки Cyrillic_General_CI_AS.
  3. Уровень совместимости БД: Для базы данных 1С на SQL Server часто требуется установить уровень совместимости с SQL Server 2000 (80).
  4. Патчинг BkEnd.dll: Иногда для обхода проверки версии SQL Server может потребоваться «патчинг» файла BkEnd.dll платформы 1С 7.7.
  5. Режим доступа к базе: Для многопользовательской работы убедитесь, что база данных SQL настроена в режиме Multiple («Properties - Options - State - Restrict access»).

Важно отметить, что переход на новые версии 1С:Предприятие (например, 8.3) для крупных самописных систем является сложным и дорогостоящим проектом. Он требует значительных временных и финансовых затрат на переписывание конфигурации, миграцию данных и покупку лицензий. При этом не всегда гарантирует мгновенный прирост производительности, особенно для систем, изначально оптимизированных под специфику 1С 7.7.

Мы надеемся, что данный подробный анализ и предложенное решение помогут вам успешно справиться с «непонятным поведением» 1С 7.7 в вашей инфраструктуре.

← На главную