image

Беда пришла откуда не ждали… У клиента завис процесс “Касса”, так что не смог снять процесс через Диспетчер задач. Рабочее место “Касса” — одновременно сервер всей системы.

Клиент принял решение ресетнуть через кнопку.

В итоге умерла DB. FireBird 2.5

Backup’ы настроены не были, так что последняя версия БД, которая случайно лежала у меня на винте, была минус 8 дней. Подняли по-быстрому с неё. Но суть дальше.

Как делать бекапы для FireBird.

Я написал скрипт, который, когда его запускают, делает резервное копирование базы данных с именем БазаДаннах_30_05_2017_23_07_51.fbk

@echo off
set "currentTime=%Time: =0%"
set now=%date:~-4%_%date:~3,2%_%date:~0,2%_%currentTime:~0,2%_%currentTime:~3,2%_%currentTime:~6,2%
  
set user=SYSDBA
set password=masterkey
set database_name=PARKDB.FDB
set backup_name=Backup\PARKDB
set ext=.fbk
 
set backup_filename=%backup_name%_%now%%ext%
echo %backup_filename%
 
nbackup -U %user% -P %password% -B 0 %database_name% %backup_filename%

%date:~3,2%

Это означает взять из результата date (это системная функция Windows), 2 символа, начиная с 3 позиции в строке. Обычный %date% = 31.05.2017

set "currentTime=%Time: =0%"

Означает брать время, учитывая 0, когда часы меньше 10, то есть без этой команды, мы при выполнении команд:

set now=%date:~-4%_%date:~3,2%_%date:~0,2%_%currentTime:~0,2%_%currentTime:~3,2%_%currentTime:~6,2%

получили бы, что now=2017_05_31_ 0_44_33, а имя файла выглядело бы так: Backup\PARKDB_2017_05_31_ 0_44_33.fbk. Пробел не сильно виден, но он неприемлем в названии файла для nbackup дата и время берутся из текущего времени системы. Это вроде рассказал :) Далее, чтобы скрипт выполнялся постоянно, я добавил задачу в планировщик задач виндовс, он каждые 4 часа запускает мой скрипт и создается новая БД, далее я научился создавать задачи в планировщике задач через командную строку:

@echo off
set script_name=e:\SoftBuild\Parking\DB\DB_Backup.bat
set task_name=LotParkingBackup
SCHTASKS /Create /SC DAILY /TN %task_name% /TR %script_name% /HRESULT /F /RI 240 /DU 24:00 /v1

Детали параметров можете посмотреть в хелпе. SCHTASKS /Create /?

Потом добавил в инсталлятор создание скрипта, который делает то, что я описал только что, и запуск из инсталлятора:

function NextButtonClick(CurPageID: Integer): Boolean;
var
  ServerHost, ServerPort, DBFileName, FBDirPath: string;
  ResultCode, ErrorCode: Integer;
  UDFFrom, UDFTo, ReaderPort: string;
  RegistryTaskFile, DBDirPath, BackupScriptPath, RegistryFileName: string;
begin
  if CurPageID = SettingsPage.ID then
  begin
    ServerHost := SettingsPage.Values[0];
    ServerPort := SettingsPage.Values[1];
    DBFileName := SettingsPage.Values[2];
 
    if IsComponentSelected(cDB) then
    begin
      DBDirPath := Copy(DBFileName, 1, Pos('PARKDB.FDB', DBFileName) - 1);
      BackupScriptPath := DBDirPath + 'DB_Backup.bat'
      RegistryTaskFile := '@echo off' + #13#10 + 
                          'set script_name=' + BackupScriptPath + #13#10 + 
                          'set task_name=LotParkingBackup' + #13#10 + 
                          'SCHTASKS /Create /SC DAILY /TN %task_name% /TR %script_name% /HRESULT /F /RI 240 /DU 24:00 /v1' + #13#10;
      
      RegistryFileName := DBDirPath + 'DB_RegistryBackup.bat';
      SaveStringToFile(RegistryFileName, RegistryTaskFile, False);
      
      Exec(ExpandConstant(RegistryFileName), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
    end;    
  end;
end;

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

@echo off
set task_name=LotParkingBackup
SCHTASKS /DELETE /TN %task_name% /F

И добавил в инсталлятор. что если мы делаем удаление программы Парковка, то нужно запустить скрипт, который удалит задачу из Планировщика:

[UninstallRun]
Filename: "{app}\DB\DB_DeleteTask.bat"; WorkingDir: "{app}\DB\"; Flags: runhidden waituntilterminated; Components: DB

В итоге у нас каждые 4 часа есть бекап, и если мы делаем UnInstall, то всё чисто :)

Оригинал.
Поделиться с друзьями
-->

Комментарии (29)


  1. nikolayvaganov
    31.05.2017 16:30
    +5

    1. Оформление выглядит крайне вырвиглазно
    2. Бекапы складывать на том же сервере, где находится БД — так себе затея.


  1. instigator21
    31.05.2017 16:35

    Без сомнения, в данном случае за хранение бекапов отвечает заказчик. На объекте есть только мобильный интернет, который включается именно для таких случаев


  1. old_bear
    31.05.2017 17:35
    +3

    Рабочее место “Касса” — одновременно сервер всей системы.

    Разве за такое не четвертуют сразу, не дожидаясь появления пушных зверей?


  1. instigator21
    31.05.2017 17:45
    +1

    пожелание заказчика ради экономии, ну и надежда на авось и так сойдет, все варианты ему озвучены были


  1. aalebedev
    31.05.2017 18:51
    +1

    Я же понимаю, что бекапы идут на тот же физический жесткий диск, что и БД?

    Кстати, насчет планировщика, я заметил, что иногда с ним бывают проблемы, если задача выполняется чаще раза в день. Пропуски или двойное выполнение, редко но бывает.

    Мы используем nnCron, тут хватит даже Lite.

    Но главное, что надо разобраться почему завис процесс и его нельзя было вырубить.


    1. instigator21
      31.05.2017 19:00

      судя по логам была проблема с считывателем карт mifare, но всё равно так зависнуть не могло, списываю на кривые руки охранников парковки


    1. NakonechnyS
      31.05.2017 19:56

      Двойное выполнение (параллельный запуск, правильно понял?) с nbackup вряд ли возможно, т.к. файл БД блокируется.


      1. aalebedev
        31.05.2017 20:14

        Да, параллельный запуск.


  1. instigator21
    31.05.2017 19:00

    в данном случае да, там компьютер моноблок с touch экраном


    1. aalebedev
      31.05.2017 19:13

      USB и внешний диск?


  1. instigator21
    31.05.2017 19:22

    как-то так, можно правда ещё батник написать который охранник просто запускает когда флешку вставляет


  1. NakonechnyS
    31.05.2017 19:40
    +1

    Зачем делаете nbackup уровня 0? Лучше уж тогда gbak, после него копия будет сжатой и проверенной на ошибки.

    Я делаю ночью nbackup уровня 0, а в течение дня каждый час уровня 1. На одной БД nbackup ведет себя очень нестабильно, иногда снимая копию уровня 1 больше часа.


    1. instigator21
      31.05.2017 19:41

      у меня довольно не большая БД, клиент забирает(будет забирать) бекапы вручную, парить ему мозг несколькими файлами, решил излишним


      1. NakonechnyS
        31.05.2017 19:49

        Ну у меня тоже 2 БД примерно по 2ГБ. Вот только бэкап от gbak весит мегов 600, а nbackup уровня 0 слепит точную копию БД исходного размера. Экономия места приличная получается.
        Время снятия копии посредством nbackup — примерно минута, gbak — чуть дольше (минут 5), но она и целостность страниц проверяет, и сжимает на лету.


        1. instigator21
          31.05.2017 20:05

          есть элегантное решение которое советую сами разработчики о том что бы выходной поток nbackup сразу отправлять в архиватор, у меня пока меньше 100 мб %)


  1. Siemargl
    31.05.2017 21:50
    -4

    Дельфи, Файрберд, Надежность — выберите любые два


    1. FMA
      31.05.2017 22:35
      +2

      А чем плох Delphi и Firebird? Наговнокодить можно на любом языке и любой СУБД. Сам много лет использовал Delphi и Firebird. И разработанные системы работаю до сих пор без нареканий и проблем.


    1. instigator21
      31.05.2017 22:35
      +1

      а что не так?


    1. Siemargl
      01.06.2017 12:21

      А. Дельфи — слишком низкий порог входа приводит к избытку идиотских вопросов на форумах, а синтаксис и возможности языка — равны С++ без шаблонов. Синдром CheckBox28Click
      Средняя квалификация коммунити в итоге весьма «впечатляет»

      Б. Файрберд — хорошая СУБД для рабочих групп, но с ньюананасами —
      1. Недуракоустойчивая. Можно сделать невосстановимый бэкап gbak, например (я даже сначала не поверил такому нонсенсу).
      2. MVCC без лога приводит к тому, что при транзакциях нужно делать много изменений по всему файлу данных.
      Соответственно, при сбое питания или внезапном ресете шанс похерить базу возрастает многократно.

      Умножаем теперь А. на Б. и получаем Н надежность

      P.S. Автор топика, возможно, еще не знает, как на самом деле устроен nbackup, что на него полагается. Я даже не знаю, как пояснить. Упрощая — это эмуляция лога в БД, которая лог не использует. В целом — вполне можно получить бэкап, с которого не восстановишься.


      1. instigator21
        01.06.2017 14:19

        Знаю только то что из мануала прочитал:

        Несколько слов о внутренних механизмах

        На заметку: то, что здесь будет описано, не является необходимыми знаниями для использования nbackup. Это описание дает грубое представление о том, что происходит при работе программы nbackup с параметром -B:

        Прежде всего, основной файл базы данных блокируется установкой внутреннего флага состояния. С этого момента абсолютно все изменения в базе данных записываются во временный файл, называемый файлом разницы (difference file) или файлом дельты.

        После этого создается резервная копия. Это не обычная копия файла базы данных — восстановление из полученной копии необходимо производить также при помощи nbackup.

        По завершении резервирования содержимое файла дельты объединяется с основным файлом базы данных. После этого база данных разблокируется (флаг возвращается в «нормальное» состояние) и файл дельты удаляется.


        1. Siemargl
          01.06.2017 15:51

          Именно. Только я предпочитаю читать в исходниках, а не в мануалах.

          А резюме такое — после бекапа Птички обязательно надо делать тестовое восстановление и срочно орать «бадуга» если оно не проходит.

          Собственно, скрипт надо прилично так дописать.

          P.S А еще nbackup архивирует данные вместе с мусором (старые версии MVCC), который не успел убрать Garbage Collector. Да, это именно та же технология, за которую ругают Яву, дотнет и тп. Только для дисковых операций в СУБД это в сотни раз медленнее.


  1. Lelik13a
    01.06.2017 06:18
    +1

    * Необходимо добавить обработку кодов возврата иначе о том, что что-то пошло не так, узнаете внезапно.
    * Желательно проверять размер получившегося бекапа на адекватность.
    * Хорошо слать отчёт на почту, особенно если что-то не так.
    * Можно добавить сжатие, лучше многопоточное, например через 7zip.
    * А после этого добавить автоматическую очистку старых бекапов.

    И будет вполне себе велосипед.


    1. instigator21
      01.06.2017 10:36

      согласен, так и планирую дальше делать


  1. jo_b1ack
    01.06.2017 09:05
    +2

    разве 3 строчки в cmd это уже статья на хабре? не в обиду… просто вспомнил какой раньше была жесткой редактура хабра.


  1. hexman
    01.06.2017 10:36

    Прекрасно это всё. Только до краха сервера или винтов на нём. Как я понял, бэкапы складываются там же, да небось ещё и на том же винте? Если это так, то всё плохо.
    из замечаний:
    1. Нет бэкапа на альтернативный носитель. В идеале, второй винт + облако.
    2. Бэкапы никак не контролируются. Т.е. они только создаются, а подчищать кто будет?


    1. instigator21
      01.06.2017 10:36

      я писал выше в коментариях, всё это на совести заказчика


  1. aaalllsss
    01.06.2017 10:37

    если база не большая, могли бы хоть настроить бекап в какую нибудь бесплатную mega.nz


  1. aynur_safin
    05.06.2017 12:18

    Для создания бекапов Firebird, есть прекрасная утилита «Time To Backup»,
    бесплатна для пользователей экс-СССР.
    http://www.sqlly.com/timetobackup.html
    Серверная часть есть под Win и Linux, на Win работает как сервис, консоль только на Win.
    Есть планировщик запуска, нотификация на емейл, сжатие бекапов, проверка бекапа на рестор, автоименование файлов по шаблонам (дата/время/инкремент).


    1. instigator21
      05.06.2017 12:25

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