Как программно реализовать резервное копирование базы данных 1С при закрытии или запуске программы

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

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

Почему формат .dt не всегда является лучшим выбором

Прежде чем переходить к программному коду, разберем важный теоретический аспект. Часто начинающие разработчики стремятся автоматизировать именно выгрузку в формат .dt. Однако стоит помнить, что файл .dt — это логическое представление данных, созданное для перехода между лицензиями или версиями СУБД. Для регулярного бэкапа файловой базы гораздо надежнее использовать прямое копирование файла 1Cv8.1CD.

Рассмотрим основные риски формата .dt:

  1. Целостность данных: Если в базе есть логические ошибки в таблицах, выгрузка в .dt может пройти успешно, а вот восстановить из него базу (загрузить обратно) не удастся.
  2. Монопольный доступ: Выгрузка в .dt требует исключительно монопольного режима работы с конфигуратором, что технически сложнее реализовать "на лету" при закрытии сеанса пользователем.
  3. Ресурсоемкость: Процесс упаковки данных в .dt нагружает процессор и занимает значительное время при больших объемах данных.

Поэтому в наших примерах мы сделаем упор на копирование основного файла базы данных и его архивацию.

Реализация диалога при закрытии программы

Рассмотрим ситуацию, когда необходимо предложить пользователю сделать копию именно в момент выхода из системы. Для этого нам понадобится модуль управляемого приложения и процедура ПередЗавершениемРаботыСистемы. Проанализируем алгоритм: мы должны спросить пользователя о необходимости бэкапа и, если он согласен, запустить процесс.

Важный нюанс: Программа 1С не может скопировать свой собственный файл базы 1Cv8.1CD, пока он открыт и заблокирован самой же программой. Поэтому прямое использование функции КопироватьФайл() внутри 1С для текущей базы выдаст ошибку доступа. Мы обойдем это ограничение с помощью внешнего командного файла (bat-скрипта).

Разберем пример кода в модуле управляемого приложения:


Процедура ПередЗавершениемРаботыСистемы(Отказ)
    
    // Проверим, не делали ли мы уже бэкап сегодня (используем константу или параметр сеанса)
    ДатаПоследнейКопии = Константы.ДатаПоследнегоРезервногоКопирования.Получить();
    Если НачалоДня(ДатаПоследнейКопии) = НачалоДня(ТекущаяДата()) Тогда
        Возврат; // Сегодня копия уже создавалась
    КонецЕсли;

    ТекстВопроса = "Сформировать резервную копию базы данных перед выходом?";
    Ответ = Вопрос(ТекстВопроса, РежимДиалогаВопрос.ДаНет, 15, КодВозвратаДиалога.Да, "Резервное копирование");
    
    Если Ответ = КодВозвратаДиалога.Да Тогда
        ПутьКБазе = СтрокаСоединенияИнформационнойБазы();
        // Извлекаем путь к папке из строки соединения (File="C:\MyBase";)
        ЧистыйПуть = СтрЗаменить(ПутьКБазе, "File=""", "");
        ЧистыйПуть = СтрЗаменить(ЧистыйПуть, """;", "");
        
        ЗапуститьСкриптБэкапа(ЧистыйПуть);
    КонецЕсли;

КонецПроцедуры

Создание внешнего скрипта для копирования базы

Чтобы успешно скопировать заблокированный файл, мы создадим процедуру, которая генерирует временный .bat файл. Этот файл подождет несколько секунд (пока 1С полностью закроется), а затем скопирует базу. Проанализируем пример такой процедуры:


Процедура ЗапуститьСкриптБэкапа(ПутьКБазе)
    
    ИмяФайлаСкрипта = "C:\Backups\start_backup.bat";
    ТекстСкрипта = "timeout /t 5 /nobreak" + Символы.ПС; // Ждем 5 секунд закрытия 1С
    ТекстСкрипта = ТекстСкрипта + "xcopy """ + ПутьКБазе + "1Cv8.1CD"" ""C:\Backups\Backup_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd") + ".1CD*"" /y" + Символы.ПС;
    
    // Записываем скрипт в файл
    ТекстовыйДокумент = Новый ТекстовыйДокумент;
    ТекстовыйДокумент.УстановитьТекст(ТекстСкрипта);
    ТекстовыйДокумент.Записать(ИмяФайлаСкрипта, КодировкаТекста.OEM);
    
    // Запускаем скрипт без ожидания завершения
    ЗапуститьПриложение(ИмяФайлаСкрипта);
    
    // Обновляем дату последней копии в 1С
    Константы.ДатаПоследнегоРезервногоКопирования.Установить(ТекущаяДата());

КонецПроцедуры

Резервное копирование при первом запуске (автоматический вариант)

Если мы не хотим беспокоить пользователя при закрытии, рассмотрим вариант с проверкой при начале работы. Выясним причину, по которой это удобнее: пользователь полон сил в начале дня и готов подождать лишние 30 секунд, пока создается архив. Логика размещается в процедуре ПриНачалеРаботыСистемы.

Для контроля периодичности нам понадобится Регистр сведений (например, "ИсторияБэкапов") или Константа. Рассмотрим вариант с использованием объекта ЗаписьZipФайла, который позволяет сжать базу объемом 3 Мб до нескольких сотен килобайт средствами самой 1С.

Пример кода для создания ZIP-архива при запуске:


Процедура ПриНачалеРаботыСистемы()
    
    ДатаПоследнейКопии = Константы.ДатаПоследнегоРезервногоКопирования.Получить();
    
    Если НачалоДня(ДатаПоследнейКопии) < НачалоДня(ТекущаяДата()) Тогда
        
        Попытка
            // Определяем пути
            ПутьКФайлуБазы = "C:\MyBase\1Cv8.1CD";
            ПутьАрхива = "D:\Backups\Archive_" + Формат(ТекущаяДата(), "ДФ=yyyy_MM_dd") + ".zip";
            
            // Создаем архив
            Архив = Новый ЗаписьZipФайла(ПутьАрхива, , , МетодСжатияZip.Сжатие, УровеньСжатияZip.Максимальный);
            Архив.Добавить(ПутьКФайлуБазы, РежимСохраненияПутейZip.НеСохранятьПути);
            Архив.Записать();
            
            // Фиксируем успех
            Константы.ДатаПоследнегоРезервногоКопирования.Установить(ТекущаяДата());
            Сообщить("Автоматическое резервное копирование успешно завершено.");
        Исключение
            // Если файл занят другим пользователем, Zip вызовет исключение
            ЗаписьЖурналаРегистрации("Бэкап", УровеньЖурналаРегистрации.Ошибка, , , "Ошибка создания копии: " + ОписаниеОшибки());
        КонецПопытки;
        
    КонецЕсли;

КонецПроцедуры

Использование специализированных утилит

Если конфигурация становится сложной или пользователей становится больше одного, рассмотрим использование внешнего софта, такого как Effector Saver. Это профессиональное решение, которое умеет:

Это зачастую надежнее, чем самописный код, так как внешние утилиты используют технологию VSS (Volume Shadow Copy), позволяющую копировать файлы "на лету" без остановки работы программы.

Рекомендации по хранению и безопасности

Проанализируем ситуацию: вы настроили копирование, база сохраняется в соседнюю папку на диске C:. Выясним, почему это опасно. Если жесткий диск выйдет из строя, вы потеряете и рабочую базу, и все копии.

Посмотрим на "Правило 3-2-1" для резервного копирования:

  1. 3 копии данных: Оригинал и два бэкапа.
  2. 2 разных носителя: Например, основной SSD компьютера и внешний жесткий диск или сетевая папка.
  3. 1 копия вне офиса: Используйте облачные хранилища (Яндекс.Диск, Google Drive). Программно в 1С можно настроить путь сохранения архива в папку, которая автоматически синхронизируется с облаком.

Также важно предусмотреть очистку дискового пространства. Если ваша база весит 3 Мб, это не критично, но со временем архивов станет слишком много. Проанализируем код для удаления файлов старше 30 дней:


МассивФайлов = НайтиФайлы("D:\Backups\", "*.zip");
Для Каждого Файл Из МассивФайлов Цикл
    Если (ТекущаяДата() - Файл.ПолучитьВремяИзменения()) > (30 * 24 * 60 * 60) Тогда
        Попытка
            УдалитьФайлы(Файл.ПолноеИмя);
        Исключение
            // Файл может быть занят другим процессом
        КонецПопытки;
    КонецЕсли;
КонецЦикла;

Таким образом, мы разобрали комплексный подход к созданию системы резервного копирования. Для небольших самописных конфигураций оптимальным будет сочетание проверки даты последнего бэкапа при запуске и использование объекта ЗаписьZipФайла с последующим копированием архива в "облачную" папку.

← На главную