Почему закрывается 1С при работе с ADODB.RecordSet и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешними базами данных (такими как MySQL или MariaDB) через COM-объект ADODB разработчики нередко сталкиваются с крайне неприятной проблемой: внешнее соединение устанавливается успешно, запрос выполняется без видимых ошибок, однако при попытке обхода выборки (например, при проверке свойства EOF или вызове метода MoveNext) платформа 1С аварийно завершает работу с генерацией дампа памяти (Memory Access Violation). В этой статье мы подробно проанализируем причины этой проблемы и по шагам настроим стабильное подключение.

Выясняем причину: Конфликт разрядности драйверов и платформы

Самой распространенной причиной мгновенного падения платформы 1С при обращении к свойствам Recordset является несовпадение разрядности (битности) драйвера СУБД и исполняемого процесса 1С. Рассмотрим, как устроен этот механизм на практике.

Технология COM-соединения жестко привязана к разрядности процесса, который её вызывает:

  1. Если вы запускаете код в 32-разрядном клиенте 1С (клиентское приложение x86), то и драйвер ODBC в операционной системе Windows должен быть строго 32-разрядным (x86).
  2. Если код выполняется на стороне 64-разрядного сервера 1С (например, в фоновом задании или в серверном модуле при вызове &НаСервере), то драйвер ODBC на сервере обязательно должен быть 64-разрядным (x64).

Если разрядность не совпадает (например, у вас установлена платформа 1С x86, а коннектор драйвера MySQL установлен x64), попытка вызвать свойства объекта COM-объекта, требующие прямой передачи структуры данных из системной памяти (такие как Eof), приводит к нарушению адресации. Платформа не может обработать некорректный указатель памяти и аварийно завершает свою работу.

Важный нюанс администрирования в Windows x64:

Для настройки источников данных ODBC используются две разные утилиты, чьи пути могут ввести в заблуждение:

При настройке системных DSN обязательно используйте ту версию утилиты, которая соответствует разрядности вашего исполняемого процесса 1С.

Настройка правильного типа курсора и блокировок ADODB

По умолчанию COM-объект ADODB.RecordSet инициализирует однопроходный курсор, который оптимизирован для быстрого чтения, но крайне чувствителен к стабильности канала связи и специфике драйверов СУБД. Настройка параметров курсора вручную позволяет решить проблемы с закрытием объекта во время работы.

Разберем по шагам, какие свойства необходимо явно задавать перед открытием набора записей:

  1. CursorLocation (расположение курсора): Определяет, где будут обрабатываться данные — на сервере СУБД или на стороне клиента. Рекомендуется использовать значение 3 (adUseClient). В этом случае весь объем выборки сразу кэшируется в оперативной памяти клиента, минимизируя нагрузку на сеть во время обхода в цикле.
  2. CursorType (тип курсора): Значение 3 (adOpenStatic) создает статическую копию данных. Это самый стабильный вариант для обхода выборки в 1С.
  3. LockType (тип блокировки данных): Для простого чтения данных оптимально использовать значение 1 (adLockReadOnly), чтобы не накладывать транзакционные блокировки на таблицы СУБД.

Посмотрим на пример правильной инициализации и настройки объекта:


Соединение = Новый COMОбъект("ADODB.Connection");
// Настройка строки подключения...
Соединение.Open(Соединение_param);

НаборЗаписей = Новый COMОбъект("ADODB.RecordSet");
НаборЗаписей.CursorLocation = 3; // Клиентский курсор
НаборЗаписей.CursorType = 3;     // Статический курсор
НаборЗаписей.LockType = 1;       // Только чтение

НаборЗаписей.ActiveConnection = Соединение;
НаборЗаписей.Open("SELECT * FROM wp_wc_product_meta_lookup");

Пока НЕ НаборЗаписей.EOF Цикл
    // Обработка полученной строки
    ТекущееЗначение = НаборЗаписей.Fields("meta_key").Value;
    НаборЗаписей.MoveNext();
КонецЦикла;

НаборЗаписей.Close();
Соединение.Close();

Проблема использования "звездочки" (SELECT *) в запросах

Еще один фактор, из-за которого падает платформа 1С при вызове MoveNext — это несовместимость типов данных Windows с типами данных внешней СУБД. При выполнении запроса вида SELECT * драйвер пытается транслировать все имеющиеся поля таблицы.

Если в таблице MySQL присутствуют сложные типы данных, такие как огромные бинарные поля BLOB, специфические типы GEOMETRY, новые структуры JSON или поля с неподдерживаемой кодировкой, COM-объект ADO не сможет корректно сопоставить их с типами платформы 1С. Результатом этого сопоставления становится критический сбой памяти.

Рекомендация: Всегда перечисляйте только нужные поля в запросе. Если поле имеет сложный или нестандартный тип, принудительно приводите его к строковому или числовому представлению прямо на стороне СУБД с помощью SQL-функций:


ТекстЗапроса = "SELECT product_id, CAST(meta_value AS CHAR) AS meta_value_string FROM wp_wc_product_meta_lookup";
НаборЗаписей.Open(ТекстЗапроса);

Специфика синтаксиса обращения к свойствам COM-объекта в 1С

Обратите внимание на синтаксические конструкции языка 1С при работе с COM-объектами. Свойство EOF (признак окончания набора записей) является свойством объекта, а не методом. В коде 1С не следует использовать круглые скобки при обращении к нему.

Вместо ошибочного вызова:

Пока не НаборЗаписей.Eof() Цикл

Следует писать строго без скобок:

Пока НЕ НаборЗаписей.EOF Цикл

Использование скобок заставляет платформу искать метод EOF, которого нет у объекта, что в устаревших версиях драйверов также могло инициировать сбои обращения к памяти.

Влияние параметра Option в строке подключения

Драйверы MySQL ODBC очень чувствительны к флагам конфигурации, передаваемым в строке подключения через параметр Option (или OPTIONS). Эти флаги управляют низкоуровневой работой сокетов, кэшированием результатов и кодировками.

Например, добавление флага Option=3 (или других комбинаций, таких как Option=16384 для обработки больших пакетов данных) принудительно отключает кэширование результатов на стороне драйвера СУБД и активирует корректный возврат задействованных строк. Без правильных флагов драйвер может передавать некорректную информацию о размере буфера в ADO, провоцируя падение 1С.

Пример оптимизированной строки подключения с параметрами:


Соединение_param = "driver={MySQL ODBC 5.1 Driver}; server=" + СокрЛП(Сервер) + 
                   "; uid=" + СокрЛП(Пользователь) + 
                   "; pwd=" + СокрЛП(Пароль) + 
                   "; database=" + СокрЛП(База) + 
                   "; Option=3; STMT=SET CHARACTER SET utf8";

Современные альтернативы технологии ADODB

Поскольку технология COM/ADO считается устаревшей и сильно зависит от операционной системы Windows и разрядности процессов, мы рекомендуем рассмотреть более надежные архитектурные подходы интеграции 1С с СУБД MySQL:

  1. Внешние источники данных (ВИД): Это штатный механизм платформы 1С. Вы можете подключить таблицы MySQL непосредственно в дерево метаданных конфигурации. Вся работа по согласованию разрядностей, трансляции типов данных и управлению курсорами перекладывается на платформу. Вы сможете делать запросы к таблицам MySQL стандартным языком запросов 1С.
  2. Интеграция через REST API / HTTP: На стороне сервера СУБД разворачивается легковесный веб-сервис (например, на PHP или Python), который принимает запросы от 1С и отдает данные в формате JSON. В 1С подключение реализуется через объект HTTPСоединение. Данный подход полностью решает проблемы с установкой драйверов ODBC, разрядностью платформ и безопасностью портов СУБД.
← На главную