Почему отчеты в 1С 7.7 DBF выдают разные данные при активной работе пользователей и как это исправить

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

В этой статье мы подробно разберем, почему возникает эта серьезная проблема, как работает скрытый механизм СУБД, приводящий к порче выборок, и рассмотрим все практические способы решения — от установки системных патчей до оптимизации структуры базы данных.

Выясним истинную причину этой проблемы, которая в кругах разработчиков 1С 7.7 получила название «проблема 1 Гигабайта».

Выясним причину: коллизия блокировок Windows API и СУБД CodeBase

Описанное поведение системы — это не случайный сбой индексов и не ошибка в коде отчета. Это фундаментальное ограничение файлового движка CodeBase, на котором построена DBF-версия платформы 1С 7.7. Ошибка начинает проявлять себя только тогда, когда размер хотя бы одного из файлов движений регистра (файл вида RA*.dbf) или таблицы бухгалтерских итогов превышает критический порог в 1 ГБ (1 073 741 824 байт).

Разберем физику процесса по шагам:

  1. Для обеспечения многопользовательской работы и предотвращения одновременного изменения одних и тех же записей движок базы данных использует стандартные механизмы операционной системы Windows, а именно функции блокировки файлов LockFile и UnlockFile из библиотеки kernel32.dll.
  2. Чтобы чтение данных другими пользователями не блокировалось полностью во время записи (проведения документов), разработчики систем управления базами данных DBF применили обходное решение: транзакционные блокировки накладываются не на реальные физические адреса записей в файле, а со смещением в виртуальную область. Традиционно в DBF-системах это смещение начинается ровно с границы 1 ГБ.
  3. Пока ваш файл регистра движения RA*.dbf имеет физический размер менее 1 ГБ, все блокировки операционной системы проецируются на несуществующие (виртуальные) адреса файла. База данных работает стабильно: один пользователь пишет новые движения, а второй без проблем читает старые данные для отчета.
  4. Как только файл RA*.dbf перешагивает отметку в 1 ГБ, его реальные физические секторы с данными начинают пересекаться с областью, куда операционная система накладывает виртуальные блокировки.
  5. В результате, когда один пользователь проводит документ и записывает движения в регистр, Windows физически блокирует чтение соответствующего сектора файла. Другой пользователь в этот же момент запускает сложный отчет. Движок 1С пытается прочитать данные из заблокированного сектора, натыкается на системный запрет чтения и, вместо ожидания или вывода ошибки, просто молча пропускает этот кусок данных (происходит так называемое «грязное» или неполное чтение).

В итоге ваш отчет формируется без части движений и выдает некорректные остатки. Как только активная запись в базу прекращается (например, в обеденный перерыв или вечером), блокировки снимаются, и тот же самый отчет внезапно начинает показывать абсолютно правильные данные. Рассмотрим, как решить эту проблему раз и навсегда.

Способ 1. Установка патча Kernel3x (исправление библиотек платформы)

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

Для этого используется известная в сообществе 1С утилита/патч Kernel3x (разработки специалистов Hogik, Romix и др.).

Проанализируем механизм работы данного решения:

Важно: Перед установкой патча обязательно сделайте полную резервную копию каталога базы данных и исполняемых файлов платформы! Установка патча производится путем замены оригинальных библиотек в каталоге установки платформы 1С 7.7 (обычно в папке C:\Program Files (x86)\1Cv77\bin\) на пропатченные версии или использованием специального загрузчика.

Способ 2. Быстрый ручной пересчет итогов для одного регистра

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

Разберем этот алгоритм по шагам:

  1. Выполните резервное копирование всей информационной базы. Все пользователи должны выйти из системы.
  2. Перейдите в каталог базы данных и найдите файлы проблемного регистра. Имя файлов можно узнать в конфигураторе (в описании структуры таблиц) или по словарю данных 1cv7.dd. Файлы регистра будут иметь вид RA***.dbf (таблица движений) и RG***.dbf (таблица итогов), где вместо звездочек указан уникальный числовой идентификатор объекта.
  3. Полностью удалите файл итогов регистра RG***.dbf и соответствующий ему индексный файл RG***.cdx. Файл движений RA***.dbf (который весит 1.2 ГБ) трогать нельзя — в нем хранятся все ваши исторические данные.
  4. Создайте временную папку вне каталога базы данных и временно переместите туда все остальные файлы итогов RG*.dbf и движений RA*.dbf других регистров вашей системы. В рабочем каталоге базы данных из файлов регистров должен остаться только один-единственный файл движений нужного нам регистра RA***.dbf.
  5. Запустите программу 1С:Предприятие в монопольном режиме.
  6. Перейдите в меню «Операции» -> «Управление оперативным учетом».
  7. Переместите Точку Актуальности (ТА) на самый первый документ в системе. Затем переместите ТА обратно на самый последний проведенный документ.
  8. В процессе этого перемещения платформа 1С обнаружит отсутствие файла RG***.dbf для оставшегося регистра, автоматически создаст его заново и последовательно пересчитает в него итоги на основе движений из файла RA***.dbf. Поскольку все остальные регистры были временно удалены из каталога, этот процесс займет считанные минуты вместо часов.
  9. Закройте программу 1С.
  10. Верните все временно перемещенные файлы RA и RG обратно в рабочий каталог базы данных с заменой файлов.
  11. Запустите монопольно Конфигуратор и выполните процедуру «Реиндексация», чтобы перестроить общие индексные файлы *.cdx.

После этой процедуры итоги по проблемному регистру будут полностью и корректно пересчитаны.

Способ 3. Переход на SQL-версию платформы 1С 7.7

Если ваша база данных активно растет, а размер файлов приближается к критическому лимиту в 2 ГБ, установка патчей блокировок — это лишь временная полумера. Единственным кардинальным решением является перенос базы данных на клиент-серверную СУБД (Microsoft SQL Server).

Проанализируем преимущества и особенности этого перехода:

Способ 4. Альтернатива: Использование Advantage Database Server (ADS)

Если переходить на полноценный SQL-сервер долго и дорого, рассмотрите технологию Advantage Database Server (ADS). Это специализированный клиент-серверный движок для работы с DBF-файлами.

При использовании ADS блокировки файлов обрабатываются не средствами операционной системы Windows по сети, а непосредственно службой (сервером) ADS. Это полностью исключает возникновение коллизии 1 ГБ, устраняет сетевой трафик по прокачке индексов и значительно повышает скорость работы файловой версии 1С 7.7, сохраняя привычный формат хранения данных DBF.

Способ 5. Оптимизация отчетов через «прямые запросы» (ВК 1С++)

В обсуждении было упомянуто, что сложный отчет на базе регистров строится около 1 часа. Это критически долго и само по себе создает повышенную нагрузку на дисковую подсистему и сеть, усугубляя проблему блокировок.

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

Посмотрим на пример логики прямого запроса к DBF-файлу с помощью класса ODBCRecordset из состава ВК 1С++:


// Создаем объект для выполнения прямого запроса к таблицам базы данных
Запрос = СоздатьОбъект("ODBCRecordset");

// Формируем текст SQL-подобного запроса непосредственно к файлу движений регистра
ТекстЗапроса = "
|SELECT 
|    Reg.SP1234 AS [Товар $Справочник.Номенклатура],
|    SUM(Reg.SP1235) AS [КоличествоОборот]
|FROM 
|    [Регистр.Продажи] AS Reg
|WHERE 
|    Reg.Date_Time_IDDoc BETWEEN :НачДата AND :КонДата~
|GROUP BY 
|    Reg.SP1234
|";

Запрос.УстановитьТекстовыйПараметр("НачДата", ВыбНачПериода);
Запрос.УстановитьТекстовыйПараметр("КонДата", ВыбКонПериода);

// Выполняем запрос и получаем результат в таблицу значений за доли секунды
ТабРезультат = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);

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

Способ 6. Свертка информационной базы данных

Если вы хотите остаться на стандартной платформе 1С 7.7 DBF без внедрения сторонних патчей и утилит, единственным легальным способом уменьшить размер файлов регистров и вернуть базу в безопасную зону (менее 1 ГБ) является проведение процедуры свертки базы данных.

Свертка включает в себя:

  1. Фиксацию остатков по всем регистрам и счетам на определенную дату (например, на начало текущего или прошлого года).
  2. Создание документов ввода остатков на эту дату.
  3. Удаление всех старых документов и их движений, предшествующих дате свертки.
  4. Сжатие таблиц базы данных через процедуру «Упаковка» (Pack) в монопольном режиме.

Это позволит физически уменьшить размер файлов RA*.dbf и RG*.dbf, разгрузить систему и вернуть стабильность при формировании регламентированной отчетности.

← На главную