Página 1 de 2

Rotina de Backup/Restore para MariaDb

Enviado: 03 Mar 2020 13:00
por asimoes
Prezados,

Preciso de ajuda para saber como criar uma rotina de backup/restore pro MariaDB

Rotina de Backup/Restore para MariaDb

Enviado: 03 Mar 2020 13:31
por JoséQuintas
Eu fiz de backup apenas, inclusive preciso agilizar.
A de restore, isso é algo eventual, faço pelo HeidiSQL mesmo.

Como criei: fiz pelo HeidiSQL e olhei como ele fez.

Note que ainda não criei pra VIEW e FUNCTIONS e coisas extras, por enquanto só contém o básico que eu uso.
ze_sqlbackup.prg
(4.52 KiB) Baixado 625 vezes
Este é o limite da linha de comando SQL:
#define MYSQL_MAX_CMDINSERT 500000

Estou pra tentar agilizar isso.

ValueSQL() é uma função pra transformar o valor em algo válido para o backup.
Exemplos: Ltrim(Str( xValue )) ou ['] + xValue + ['] ou [Stod('2020-01-01')] ou etc.

O uso de [`] em nomes de campos, acabei copiando do HeidiSQL na época, mas nem precisa, exceto se usar nomes especiais nos campos.

Estou pensando em alterar pra quantidade de registros, assim não precisa somar string, nem ficar testando Len()

Rotina de Backup/Restore para MariaDb

Enviado: 03 Mar 2020 14:48
por JoséQuintas
Só complemento:

Meu aplicativo faz uso do MySQL, então sem sentido restaurar por dentro do aplicativo.
Uso o HeidiSQL e mando executar esse arquivo SQL e pronto.
Uso assim fazem anos, e raramente tem problema, talvez uma vez a cada 6 meses, provavelmente queda de internet durante a salva em FTP.

Rotina de Backup/Restore para MariaDb

Enviado: 03 Mar 2020 20:02
por asimoes
Adaptei minha rotina de backup para dbf para fazer backup do banco usando mysqldump

Código: Selecionar todos

METHOD TBackup() 
LOCAL hZip, cPathBase, cPathZIP, aDir1, aDir2, aDir3, aDirC, I, lBackup := .F., lApaga := .F., lOk := .F.
LOCAL cTemp := Hb_GetEnv("TEMP"), cPastaBackup := "C:\BACKUP", aFilesDir, aFiles
LOCAL cMensErro := "Erro no backup, informar ao Analista Alexandre Simões!"
LOCAL nSecIni, dData, aDrive := {}, oElemento
     
      nSecIni         := Seconds()  
         
      dData           := Date() 
      
      cPathBase       := Hb_DirBase() + [BACKUPBANCO\]
      
      cPathZIP        := Hb_DirBase() + [BACKUPBANCO\]
      
      cPathDropBoxZIP :=  Hb_DirBase() + [DROPBOX\BACKUP\] //Grava no DropBox
      
      cPathBCK        := cPastaBackup + [\]
      
      aDir1           := Directory( cPathBase + "*.*" )
        
      aDirZ           := Directory( cPathZIP + "*.ZIP" )
      
      aDirZDropBox    := Directory( cPathDropBoxZIP + "*.ZIP" )
        
      nLenZ           := Len( aDirZ )
      
      nLenZDropBox    := Len( aDirZDropBox )

      IF nLenZ > 0
         aSort( aDirZ, , , {|x,y| DTOS( x[3] ) + x[4] > DTOS( y[3] ) + y[4] } )
      ENDIF

      IF nLenZDropBox > 0
         aSort( aDirZDropBox, , , {|x,y| DTOS( x[3] ) + x[4] > DTOS( y[3] ) + y[4] } )
      ENDIF
      
      FOR EACH oElemento IN aDirZ
         IF oElemento:__enumIndex > 2
            fErase( cPathZIP + oElemento[1] )
         ENDIF
      NEXT
      
      FOR EACH oElemento IN aDirZDropBox
          IF oElemento:__enumIndex > 2
             fErase( cPathDropBoxZIP + oElemento[1] )
          ENDIF
      NEXT
      
      aFiles := {}
      
      IF Len( aDir1 ) > 0
         FOR EACH aFilesDir IN aDir1
            aAdd( aFiles, aFilesDir[1] )
         NEXT
      ENDIF

      IF nLenZ > 0 .AND. Len( aFiles ) > 0
         lBackup := ( dData - aDirZ[1, 3] ) >= 1
      ELSE
         lBackup := .T.
      ENDIF

      IF nLenZDropBox > 0 .AND. Len( aFiles ) > 0
         lBackup := ( dData - aDirZDropBox[1, 3] ) >= 1
      ELSE
         lBackup := .T.
      ENDIF
      
      IF lBackup
         ::Notificar( "Aguarde, preparando backup.", "Monitor AsaPrev" )
         fErase( "backupbanco\backupbanco.sql" )
         ::Execute( "mysqldump", "--databases asaprev -u root -psenha >> backupbanco\backupbanco.sql ", .T. ) 
         aFiles := {}
         FOR EACH aFilesDir IN Directory( cPathBase + "*.*" )
            aAdd( aFiles, aFilesDir[1] )
         NEXT
      ENDIF
            
      IF lBackup  
         ::Notificar( "Aguarde, compactando arquivos do backup.", "Monitor Backup" )
         IF ::CompactaDBF( cPastaBackup, aFiles, dData )
            IF nLenZ > 0
               IF lBackup .AND. nLenZ >= 2
                  fErase( Hb_DirBase() + [DRIVE\BACKUP\] + aDirZ[nLenZ, 1] )
               ENDIF
            ENDIF
            IF nLenZDropBox > 0
               IF lBackup .AND. nLenZDropBox >= 2
                  fErase( Hb_DirBase() + [DROPBOX\BACKUP\] + aDirZDropBox[nLenZDropBox, 1] )
               ENDIF
            ENDIF
            ::Notificar( "Backup concluído em: " + SecToTime( Seconds() - nSecIni ), "Monitor AsaPrev", .T. )
        ENDIF
     ENDIF
    
RETURN Nil

METHOD CompactaDBF( cPastaBackup, aFiles, dData ) 
LOCAL aArq := {}, lOk := .T., I, oElemento, oErro
   
   BEGIN SEQUENCE WITH __BreakBlock()
      FOR EACH oElemento IN aFiles
          aAdd(aArq, cPastaBackup + [\] + oElemento)
          DO EVENTS
      NEXT
      Hb_SetZipComment( "Backup dos dados sistema AsaPrev em: " + Hb_DtoC(dData, "DD/MM/YYYY") )
      Hb_ZipFile( cPastaBackup + [\] + "ASABCK_" + Hb_DtoC(dData, "YYYYMMDD") + ".ZIP", ;
                  aArq, ;
                   9, ;
                   , ;
                   .T., ;
                   "asaprev*" + Hb_DtoC( Date(), "yyyy" ), ;
                   , ;
                   , ;
                   , ;
                   .T. )
      ::Copy_Arq( cPastaBackup + [\] + ;
                  "ASABCK_" + Hb_DtoC(dData, "YYYYMMDD") + ".ZIP", ;
                  Hb_DirBase() + [DRIVE\BACKUP\], .T. )
      ::Copy_Arq( cPastaBackup + [\] + ;
                  "ASABCK_" + Hb_DtoC(dData, "YYYYMMDD") + ".ZIP", ;
                  Hb_DirBase() + [DROPBOX\BACKUP\], .T. )            
                  
   RECOVER USING oErro 
      lOk := .F.
   End
   
RETURN lOk

METHOD Execute( cProgram, cParameter, lEspera ) 
LOCAL oShell, lOk := .T., nStyle, oErro

   lEspera := Hb_DefaultValue(lEspera, .T.)
   
   BEGIN SEQUENCE WITH __BreakBlock()
      oShell := Win_OleCreateObject( "WScript.Shell" )
   RECOVER
      lOk := .F.
   END
   
   IF lOk
      BEGIN SEQUENCE WITH __BreakBlock()
         /*
         intWindowStyle
         Description
         0  Hides the window and activates another window.
         1  Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
         2  Activates the window and displays it as a minimized window.
         3  Activates the window and displays it as a maximized window.
         4  Displays a window in its most recent size and position. The active window remains active.
         5  Activates the window and displays it in its current size and position.
         6  Minimizes the specified window and activates the next top-level window in the Z order.
         7  Displays the window as a minimized window. The active window remains active.
         8  Displays the window in its current state. The active window remains active.
         9  Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window.
         10 Sets the show-state based on the state of the program that started the application. 
         */
         nStyle := 0
         oShell:Run("%comspec% /c " + cProgram + " " + cParameter, nStyle, lEspera) 
      RECOVER
         MsgStop("Erro executando " + cProgram, "Erro")
         lOk := .F.
      END
      
      oShell := Nil
      
   ENDIF
   
RETURN lOk

Rotina de Backup/Restore para MariaDb

Enviado: 03 Mar 2020 21:44
por asimoes
Usando 7Zip com senha

Código: Selecionar todos

METHOD TBackupAsaPrev() 
LOCAL hZip, cPathBase, cPathZIP, aDir1, aDir2, aDir3, aDirC, I, lBackup := .F., lApaga := .F., lOk := .F.
LOCAL cTemp := Hb_GetEnv("TEMP"), cPastaBackup := "C:\BACKUP", aFilesDir, aFiles
LOCAL cMensErro := "Erro no backup, informar ao Analista Alexandre Simões!"
LOCAL nSecIni := Seconds(), dData, aDrive := {}, oElemento

      IF Hb_FileExists( Upper( GetStartupFolder() ) + [\MANUTENCAO.SIS] )
         Form_Principal.Release
      ENDIF
   
      nSecIni         := Seconds()  
         
      dData           := Date() 
      
      cPathBase       := Upper( GetStartupFolder() ) + [\BACKUPBANCO\]
      
      cPastaBackup    := Upper( GetStartupFolder() ) + [\BACKUPBANCO\]
      
      cPathZIP        := Upper( GetStartupFolder() ) + [\BACKUPBANCO\]
      
      cPathDropBoxZIP := Upper( GetStartupFolder() ) + [\DROPBOX\BACKUP\]
      
      cPathBCK        := cPastaBackup + [\]
      
      aDir1           := Directory( cPathBase + "*.SQL" )
        
      aDirZ           := Directory( cPathZIP + "*.7Z" )
      
      aDirZDropBox    := Directory( cPathDropBoxZIP + "*.7Z" )
        
      nLenZ           := Len( aDirZ )
      
      nLenZDropBox    := Len( aDirZDropBox )

      IF nLenZ > 0
         aSort( aDirZ, , , {|x,y| DTOS( x[3] ) + x[4] > DTOS( y[3] ) + y[4] } )
      ENDIF

      IF nLenZDropBox > 0
         aSort( aDirZDropBox, , , {|x,y| DTOS( x[3] ) + x[4] > DTOS( y[3] ) + y[4] } )
      ENDIF
      
      FOR EACH oElemento IN aDirZ
          IF oElemento:__enumIndex > 2
             fErase( cPathZIP + oElemento[1] )
          ENDIF
      NEXT
      
      FOR EACH oElemento IN aDirZDropBox
          IF oElemento:__enumIndex > 2
             fErase( cPathDropBoxZIP + oElemento[1] )
          ENDIF
      NEXT
      
      aFiles := {}
      
      IF Len( aDir1 ) > 0
         FOR EACH aFilesDir IN aDir1
            aAdd( aFiles, aFilesDir[1] )
         NEXT
      ENDIF

      IF nLenZ > 0 .AND. Len( aFiles ) > 0
         lBackup := ( dData - aDirZ[1, 3] ) >= 1
      ELSE
         lBackup := .T.
      ENDIF

      IF nLenZDropBox > 0 .AND. Len( aFiles ) > 0
         lBackup := ( dData - aDirZDropBox[1, 3] ) >= 1
      ELSE
         lBackup := .T.
      ENDIF
      
      SetEnvironmentVariable( "PATH", "C:\Program Files\MariaDB 10.4\bin;C:\Program Files\7-Zip" )
  
      IF lBackup
         ::Notificar( "Aguarde, preparando backup.", "Monitor AsaPrev" )
         fErase( cPastaBackup + "BACKUPBANCO.SQL" ) //apaga para recriar
         ::Execute( "mysqldump", "--databases asaprev -u root -psenha >> backupbanco\backupbanco.sql ", .T. ) //faz dump da base
         aFiles := {}
         FOR EACH aFilesDir IN Directory( cPathBase + "*.*" )
            aAdd( aFiles, aFilesDir[1] )
         NEXT
      ENDIF
            
      IF lBackup  
         ::Notificar( "Aguarde, compactando arquivos do backup.", "Monitor AsaPrev" )
         IF ::CompactaDBF( cPastaBackup, aFiles, dData )
            IF nLenZ > 0
               IF lBackup .AND. nLenZ >= 2 //Deleta backups com mais de 2 dias no Google Drive
                  fErase( Hb_DirBase() + [DRIVE\BACKUP\] + aDirZ[nLenZ, 1] )
               ENDIF
            ENDIF
            IF nLenZDropBox > 0
               IF lBackup .AND. nLenZDropBox >= 2 //Deleta backups com mais de 2 dias no DropBox
                  fErase( Hb_DirBase() + [DROPBOX\BACKUP\] + aDirZDropBox[nLenZDropBox, 1] )
               ENDIF
            ENDIF
            ::Notificar( "Backup concluído em: " + SecToTime( Seconds() - nSecIni ), "Monitor AsaPrev", .T. )
        ENDIF
     ENDIF
    
RETURN Nil

METHOD CompactaDBF( cPastaBackup, aFiles, dData ) 
LOCAL aArq := {}, lOk := .T., I, oElemento, oErro, cParameter
   
   BEGIN SEQUENCE WITH __BreakBlock()
      FOR EACH oElemento IN aFiles
          aAdd(aArq, cPastaBackup + [\] + oElemento)
          DO EVENTS
      NEXT
       
      cParameter := "-t7z -mx=9 -psaprev*" + Hb_DtoC( Date(), "YYYY") + " a " + cPastaBackup + "ASABCK_" + Hb_DtoC(dData, "YYYYMMDD") + " " + aarq[1]
       
      ::Execute( "7z", cParameter, .T., 0 )  

      ::Copy_Arq( cPastaBackup + [\] + ;
                  "ASABCK_" + Hb_DtoC(dData, "YYYYMMDD") + ".7Z", ;
                  Hb_DirBase() + [DRIVE\BACKUP\], .T. )
                  
      ::Copy_Arq( cPastaBackup + [\] + ;
                  "ASABCK_" + Hb_DtoC(dData, "YYYYMMDD") + ".7Z", ;
                  Hb_DirBase() + [DROPBOX\BACKUP\], .T. )   
      
      fErase( cPastaBackup + [\] + "ASABCK_" + Hb_DtoC(dData, "YYYYMMDD") + ".7Z")                     
          
   RECOVER USING oErro 
      lOk := .F.
   END
   
RETURN lOk

#pragma BEGINDUMP

#include <windows.h>
#include "hbapi.h"
#include "hbapiitm.h"
#include <Shellapi.h>

HB_FUNC( EMPTYTRASH )
{
SHEmptyRecycleBin( NULL,
                   NULL,
                   SHERB_NOCONFIRMATION |
                   SHERB_NOPROGRESSUI   |
                   SHERB_NOSOUND );
}

HB_FUNC ( EMPTYRECYCLEBIN )
{
	hb_retnl( SHEmptyRecycleBin(NULL,NULL,SHERB_NOCONFIRMATION + SHERB_NOPROGRESSUI) );
}

HB_FUNC( SETENVIRONMENTVARIABLE )
{
   hb_retl( SetEnvironmentVariableA( (LPCSTR) hb_parcx( 1 ),
                                     (LPCSTR) hb_parcx( 2 )
                                     ) ) ;
}

#pragma ENDDUMP

Rotina de Backup/Restore para MariaDb

Enviado: 15 Mar 2020 13:20
por JoséQuintas
Acabei achando um jeito simples de testar o tamanho do comando:

Código: Selecionar todos

nPos := fSeek( nHandle, 0, 2 )
...
IF cnSQL:RS:Eof() .OR. fSeek( nHandle, 0, 2 ) - nPos > SQL_MAX_CMDINSERT
   EXIT
ENDIF
Pensei nisso depois de encontrar como salvar parcial:

Código: Selecionar todos

fWrite( nHandle, ";" + hb_Eol() )
fClose( nHandle )
nHandle := fOpen( SQL_FILE_BACKUP, FO_READWRITE )
fSeek( nHandle, 0, 2 )
Fecho o arquivo, e reabro posicionando no final
Desse jeito o Windows vai salvando o buffer.

Vantagem? nenhuma, é que dava aflição ver o arquivo sempre com tamanho zero até terminar kkkk
backup1.png
backup2.png
Tô achando demorado quase 2 minutos pra salvar 250.000 registros.

Rotina de Backup/Restore para MariaDb

Enviado: 15 Mar 2020 13:30
por JoséQuintas
Vixe. este tá demorando mais ainda, mas também, tem campo adoidado.
Só campo de impostos... vixe... um monte...
backup3.png

Rotina de Backup/Restore para MariaDb

Enviado: 15 Mar 2020 19:24
por lucimauro
Asimoes

Você terá problema apenas se seu arquivo .SQL for maior que 4gb, nesse caso a função hb_zipfile() não ira funcionar já que esse é o limite do harbour 32 bits para o tamanho do arquivo se é que você usa a versão 32.

No caso do 7zip você usa um aplicativo externo e isso?

Se você desejar compactar direto no comando do mysqldump você pode usar a -GZIP(aplicativo gzip.exe) na linha de comando do mysqldump para compactar direto e saída do arquivo será .GZ

isso estou falando para quem usa mysql, não sei se no mariadb e a mesma coisa.

Rotina de Backup/Restore para MariaDb

Enviado: 15 Mar 2020 19:24
por asimoes
Tem que comparar com mysqldump pra ver o que é mais rápido, o mysqldump grava tudo triggers, indices, etc..

Rotina de Backup/Restore para MariaDb

Enviado: 15 Mar 2020 19:36
por lucimauro
E vejo também que quando você faz backup o sistema fica quase ou todo travado já que o mysqldump faz bloqueio das tabelas para poder fazer o dump, falando da minha experiência com mysql.

Rotina de Backup/Restore para MariaDb

Enviado: 15 Mar 2020 22:55
por asimoes
lucimauro escreveu:E vejo também que quando você faz backup o sistema fica quase ou todo travado já que o mysqldump faz bloqueio das tabelas para poder fazer o dump, falando da minha experiência com mysql.
É por isso que rotina de backup é feita de madrugada quando todos estão "dormindo", claro que o servidor nunca "dorme", ou quando o servidor é ligado, eu uso um utilitário que faz isso na inicialização do servidor, nunca tive problemas.
O meu backup leva menos de 30 segundos, uma base com mais de 1 milhão de registros. O utilitário compacta o.sql com senha e coloca em uma pasta no google drive e outra no dropbox no final compactado com 7zip -mx9 máximo de compactação gera um zipado com 13 mb

Rotina de Backup/Restore para MariaDb

Enviado: 15 Mar 2020 23:04
por asimoes
Eu tentei usar o gzip.exe mas não vi como zipar com senha, o meu utilitário, chama o 7zip passando os parâmetros necessários, tá postado aqui.

Rotina de Backup/Restore para MariaDb

Enviado: 15 Mar 2020 23:45
por lucimauro
Realmente o GZIP não tem como colocar senha.

Rotina de Backup/Restore para MariaDb

Enviado: 16 Mar 2020 04:23
por JoséQuintas
lucimauro escreveu:Você terá problema apenas se seu arquivo .SQL for maior que 4gb, nesse caso a função hb_zipfile() não ira funcionar já que esse é o limite do harbour 32 bits para o tamanho do arquivo se é que você usa a versão 32.
Não tinha pensado numa coisa antes...
O limite não vai ser 4GB.

Código: Selecionar todos

   ? "inicio"
   Inkey(0)
   FOR EACH cLine IN hb_RegExSplit( hb_Eol(), MemoRead( "backup.sql" ) )
      nLen := Max( nLen, Len( cLine ) )
      ? nLen
   NEXT
Isso já é problema pra arquivo menor.
Simples: mesmo que o arquivo SQL tenha somente 2GB, se passar pra uma função, já vão ser necessários 2GB na função que chama e 2GB na função que recebe o parâmetro.

Talvez já tenha que pensar em dividir o backup em arquivos de no máximo 1GB, por precaução.

Rotina de Backup/Restore para MariaDb

Enviado: 16 Mar 2020 05:10
por JoséQuintas
Pois é....
Acho que acabo de começar a ter problema com isso.
Pode ser coincidência, porque no erro é no upload do zip, mas pode ser que é resultado de sobrecarga.
Vamos ver se minha solução resolve.