Programma PHP che esegue backup e ripristino di database SQL SERVER

Ferie80

Nuovo Utente
12 Apr 2012
9
0
0
Ciao a tutti, spiego subito il problema che mi ritrovo: devo eseguire dei backup su un SQL SERVER 2000, copiarli su un nuovo server che supporta SQL 2008 ed eseguire quindi i ripristini uno alla volta.
Tenete presente che questo programma dovrebbe spostare circa un migliaio di database anche molto pesanti, relativi ad anni passati e, soprattutto, 146 database del corrente anno una volta al giorno.

Ho creato un programma che esegue i vari passaggi:
- Esegue i vari backup (uno alla volta) dei database che si trovano su un SQL SERVER 2000 con relativa query BACKUP DATABASE che si crea di volta in volta un file di backup in base al nome del database, alla data e all'ora in cui viene eseguito.
- Verifica il corretto backup con la query RESTORE VERIFYONLY.
- Copia il file backup appena creato sul nuovo server e cancella quello presente sul vecchio server.
- Fa il restore sul nuovo server (che come detto, è un SQL SQRVER 2008) con la query di RESTORE DATABASE.

Tutto questo in teoria... perchè il problema principale è che il comando che lancia la query (sqlsrv_query , preciso che il mio programma è lanciato da un terzo server che supporta le librerie PHP di SQL SERVER 2008) è come se venisse interrotto e la query va sempre in errore nonostante i backup o le verifiche o gli stessi ripristini siano andati a buon fine (e questo vuol dire che le query sono corrette anche perchè sono state verificate con il Management Studio).

Io penso che come accade sul Management Studio, dove all'esecuzione della query mi vengono restituiti dei messaggi di completamento delle varie operazioni (ad esempio quando viene eseguito il backup, Man Studio mi ritorna messaggio che mi dicono l'avanzamento della fase di backup, ad esempio "41 percent backed up.") e che questi messaggi vengano interpretati da sqlsrv_query come messaggi di errore e che quindi vada in errore.
Sul manuale ho trovato alcuni stati di errore SQLSTATE che potrebbero anche essere evitati ed infatti ho dovuto creare una funzione di rilevazione di questo tipo di stati e che quindi mi evita la rilevazione dell'errore, di seguito il codice di esempio.

PHP:
sqlsrv_query($connect, $sql) or trigger_error("La query ha ritornato falso : ".erroriQuerySql2008($backup, $bkPathFile, "Errore durante il Backup del database", $bkDBName, $Log));


//funzione per segnalare più esplicitamente gli errori derivanti dalle query SQL 2008
function erroriQuerySql2008($result, $path, $errore, $bkDBName, $Log){
    $errText="";
    if($result===false){
        if(($errors=sqlsrv_errors())!=null){
            foreach($errors as $error){
                $errText.="SQLSTATE: ".$error[ 'SQLSTATE']."\n";
                $errText.="code: ".$error[ 'code']."\n";
                $errText.="message: ".$error[ 'message']."\n";
                if($error['SQLSTATE'] == '01000' || $error[ 'SQLSTATE'] == '01001' || $error[ 'SQLSTATE'] == '01003' || $error[ 'SQLSTATE'] == '01S02' ){
                    $errText = "ma non ci sono errori!!! \n";
                    return $errText;
                }else{
                    echo $errore;
                    $array = explode("\", $path);
                    $Log->BackupLog("Server: ".$array[2]." DB: ".$bkDBName, $errore, basename($_SERVER["PHP_SELF"]));
                    $GLOBALS['erroriBackup']++;
                    return $errText;
                }
            }
        }
    }
}

Il problema persiste nel momento in cui mi ritrovo di cmq che i restore non vengono effettuati in nessun caso.
In più nel momento in cui provo a fare anche solamente eseguire il tutto per i db del 2012 senza fare i restore molte volte durante la verifica del backup mi ritrovo errori di questo tipo:

Codice:
SQLSTATE: 42000
code: 3201
message: [Microsoft][SQL SERVER Native  Client 10.0][SQL server]Cannot open backup device <percorso del file di backup>. Device error or device off-line. See the SQL Server error log for more details.  in <percorso del programma> on line <nr linea>

L'sql server non riesce ad aprire il backup il device, nonostante questo sia online e funzionante: il risultato di tutto ciò è che in genere di 146 db del 2012, circa 35/38 a seconda, e non sempre gli stessi, non vengono copiati nel nuovo server...

Qualche idea? Non so se sono stato abbastanza chiaro su quello che sto cercando di risolvere...

Tenete anche presente che ho provato ad effettuare anche con il Man Studio le copie dei database con il comando di Wizard, ma questo non parte nemmeno perchè mi dà errore durante la "configurazione del pacchetto di Integration Services" e quindi andando in errore subito senza nemmeno eseguire una sola azione.
 

Ferie80

Nuovo Utente
12 Apr 2012
9
0
0
Davvero nessuno ha qualche idea??

Al momento siamo riusciti ad aggirare parzialmente il problema, creando poi un programmino che durante il fine settimana ha fatto il detach di alcuni database degli anni passati, li ha copiati sul nuovo server e ne ha fatto il reattach. Certo è che andando aventi così ci vorranno parecchi fine settimana.

In più il problema persiste per i database del corrente anno dei quali si vorrebbe avere un backup giornaliero da spostare.

HELP!! :crying:
 

Eliox

Utente Attivo
25 Feb 2005
4.390
3
0
Fammi capire, il problema sono soltanto i messaggi di errore? I backup vengono eseguiti correttamente?
Perché diversamente potrebbe essere un problema di timeout.
 

Ferie80

Nuovo Utente
12 Apr 2012
9
0
0
Ciao e grazie per la risposta, intanto.
Dunque, i backup che vengano fatti non sempre sono corretti anche perchè molte volte la RESTORE VERIFYONLY non li verifica correttamente ed infatti ritorna l'errore alla query che la esegue.
Infatti io faccio fare questa verifica apposta per evitare di spostare backup che non sono riusciti.
Quello che mi stupisce è che questi errori siano variabili e che quindi non li si possano monitorare anche se è vero che i database più pesanti non vengono mai verificati correttamente forse proprio perchè già il backup non è andato a buon fine. Ma allora come mai a volte capita che anche i più piccoli non siano corretti?

Tu mi parli di timeout, come posso risolvere questo problema?
 

Eliox

Utente Attivo
25 Feb 2005
4.390
3
0
Da come descrivi il problema (malfunzionamenti anche in caso di trasferimenti di masse di dati non critiche), tenderei ad escludere che si tratti di un problema di timeout; sembrerebbe più una questione di overhead con richieste eccessive di risorse accessorie (riferisci che i backup più grandi contengono spesso errori). Hai la possibilità di eliminare qualche processo non indispensabile per il funzionamento del server?
 

Ferie80

Nuovo Utente
12 Apr 2012
9
0
0
I due server, sia quello iniziale che quello di destinazione sono in esecuzione esclusivamente per il funzionamento dei database.
Il primo è un sistema operativo Windows 2000 SP 3, macchina che dovrà essere dismessa; supporta SQL SERVER 2000.
La macchina di destinazione è un Windows Server 2008 R2 SP 1 sulla quale gira appunto SQL 2008 R2.
Non vi sono altri processi pesanti in funzione nè sulla prima nè sulla seconda proprio per permettere al meglio il loro funzionamento dato che sono consultati in continuazione durante l'orario lavorativo.
A questo punto potresti dirmi che i problemi ci sono per via dei troppi accessi o troppe connessioni: il problema rimane nel momento in cui si è anche provato a far girare il programma durante la notte in orari di chiusura dell'azienda constatando poi la mattina successiva, che i problemi rimanevano.

Ad ogni modo è possibile impostare una priorità di esecuzione per il mio thred su tutti gli altri in PHP?
 

Ferie80

Nuovo Utente
12 Apr 2012
9
0
0
Non ho la possibilità di toccare i thred attivi sui server.
Per questo motivo chiedevo se esisteva una qualche funzione che in PHP attivasse una qualche sorta di priorità di esecuzione...
 

Ferie80

Nuovo Utente
12 Apr 2012
9
0
0
Forse ci siamo, come suggeritomi in altri forum, l'errore era proprio nella query!!!

Eliminando le opzioni REWIND, NOUNLOAD e soprattutto STATS = 10 perlomeno i backup vengono eseguiti tutti correttamente. La nuova funzione è quindi la seguente con l'opzione RETAINDAYS = 3 per mantenere i db del corrente anno 3 giorni sul nuovo server:

PHP:
function backupDatabase($bkDBName, $bkPathFile, $bkSet, $Log){
    sqlsrv_configure("WarningsReturnAsErrors", 0);
    $dbSenzaParentesi = filtraParentesiDb($bkDBName);
    $serverName = <nome_server>;
    $connectionInfo = array("UID" => <user_name>, "PWD" => <password>, "Database" => $dbSenzaParentesi);
    $connect = sqlsrv_connect($serverName, $connectionInfo) or trigger_error('Impossibile collegarsi al database '.$dbSenzaParentesi);
    
    //$sql = "ALTER DATABASE ".$bkDBName." SET RECOVERY FULL";
    echo "\n Backup del database ".$bkDBName." in corso \n";
    $sql = "BACKUP DATABASE ".$bkDBName." 
            TO  DISK = N'".$bkPathFile."' 
            WITH  RETAINDAYS = 3, NOFORMAT, NOINIT,  NAME = N'".$bkSet."', SKIP";
    echo " Query sql per il backup del database ".$bkDBName." in corso \n";
    $backup = sqlsrv_query($connect, $sql) or trigger_error("La query ha ritornato falso : ".erroriQuerySql2008($backup, $bkPathFile, "Errore durante il Backup del database: ", $bkDBName, $Log));
    //sqlsrv_close($connect);
}
Resta il problema sul restore... :incazz:

La funzione di restore non ha mai funzionato e a questo punto mi viene il dubbio che possa essere ancora qualche opzione del comando RESTORE che mi ha sempre dato noie in quanto non ha mai funzionato e quando dico mai intendo che nemmeno per i db piccoli funziona.
Cioè la chiamata della query non dà errori però se provo a visualizzare i db con Man Studio li vedo in costatnte ripristino e mi vengono creati dei file di checkRestore.
Effettivamente poi questo ripristino non va mai a buon fine nel senso che non viene mai completato.
Questa la funzione di restore:

PHP:
//Funzione per il restore del database
function restoreDatabese($bkDBName, $bkNuovoPathFile, $Log){
    sqlsrv_configure("WarningsReturnAsErrors", 0);
    $dbSenzaParentesi = filtraParentesiDb('<nome_database_esistente>');
    $serverName = "<nome_server>";
    $connectionInfo = array("UID" => "<nome_user>", "PWD" => "<password>", "Database" => $dbSenzaParentesi);
    $connect = sqlsrv_connect($serverName, $connectionInfo) or trigger_error('Impossibile collegarsi al database '.$dbSenzaParentesi);
    
    echo "\n Restore del Backup del database ".$bkDBName." in corso sul nuovo server \n";
    $sql = "RESTORE DATABASE ".$bkDBName."
            FROM DISK = '".$bkNuovoPathFile."'
            WITH REPLACE, 
            MOVE '".$bkDBName."_Data' TO '<percorso>".$bkDBName."_Data.MDF',
            MOVE '".$bkDBName."_Log' TO '<percorso>".$bkDBName."_Log.LDF'";
    echo "\n Query sql per il restore del database ".$bkDBName." in corso \n";
    $restore = sqlsrv_query($connect, $sql) or trigger_error("La query ha ritornato falso : ".erroriQuerySql2008($restore, $bkNuovoPathFile, "Errore durante il Restore del database", $bkDBName, $Log));
    //sqlsrv_close($connect);
}

Che errore può essere dato che se la stessa query eseguita sul Man Studio va a buon fine :confused: ?
 
Ultima modifica:

Ferie80

Nuovo Utente
12 Apr 2012
9
0
0
CI SIAMO RAGA!!!

La soluzione potrebbe essere sostanzialmente la funzione sqlsrv_next_result() molto più semplice di quello che uno si possa aspettare:

PHP:
if ( ($restore = sqlsrv_query($connect, $sql)) ){
	do{
		$array = sqlsrv_errors();
		echo " Risposta del server: ".$array[0]['message']."\n";
	} while ( sqlsrv_next_result($restore) ) ;
	sqlsrv_free_stmt($restore);
}

Successivamente si può anche chiudere la connessione senza problemi.
Resta solo da testarla al meglio! Vi farò sapere con esattezza se è questa la risposta definitiva forse anche per i problemi del backup!

:elvis:
 

Ferie80

Nuovo Utente
12 Apr 2012
9
0
0
In pratica con questo ciclo si prendono tutti i risultati che la query ritorna ed interpreta come errori e glieli si fa leggere tutti di modo che il restore alla fine venga portato effettivamente a termine.
E' in pratica come avere una query select alla quale mi faccio restituire con il fetch array tutti i risultati, in questo caso mi faccio restituire tutti quelli che PHP interpreta come errori per far sì che la query SQL venga effettivamente portata a termine e che quindi venga effettuato il restore.
:jolly:
Per il mio caso, l'interesse sarà che siano visualizzati i messaggi che SQL SERVER mi ritorna quindi mi farò leggere solo gli errori di sqlsrv_errors() che si trovano in 'message' anche solo per verificare che una volta portata a termine la query, come sul Man Studio, l'ultimo messaggio visualizzato alla fine di ogni ciclo, sarà quello di operazione avvenuta con successo.
La nuova funzione di restore sarà quindi così composta:

PHP:
function restoreDatabese($bkDBName, $bkNuovoPathFile, $restorePath, $file, $Log){
    sqlsrv_configure("WarningsReturnAsErrors", 0);
    $dbSenzaParentesi = filtraParentesiDb('');
    $serverName = "";
    $connectionInfo = array("UID" => "", "PWD" => "", "Database" => $dbSenzaParentesi);
    $connect = sqlsrv_connect($serverName, $connectionInfo) or trigger_error('Impossibile collegarsi al database '.$dbSenzaParentesi);

    if(strpos($file, "_Data")){
        $moveBkDBFile = $bkDBName."_Data";
        $moveBkDBFileLog = $bkDBName."_Log";
    }else if(strpos($file, "_data")){
        $moveBkDBFile = $bkDBName."_data";
        $moveBkDBFileLog = $bkDBName."_log";
    }else{
        $moveBkDBFile = $bkDBName;
        $moveBkDBFileLog = $bkDBName."_log";
    }
    echo "n Restore del Backup del database ".$bkDBName." in corso sul nuovo server n";
    $sql = "RESTORE DATABASE ".$bkDBName."
            FROM DISK = N'".$bkNuovoPathFile."'
            WITH REPLACE, RECOVERY,
            MOVE N'".$moveBkDBFile."' TO N'".$restorePath."\\".$moveBkDBFile.".MDF',
            MOVE N'".$moveBkDBFileLog."' TO N'".$restorePath."\\".$moveBkDBFileLog.".LDF'";
    echo " Query sql per il restore del database ".$bkDBName." in corso n";
    //$restore = sqlsrv_query($connect, $sql) or trigger_error("La query ha ritornato falso : ".erroriQuerySql2008($restore, $bkNuovoPathFile, "Errore durante il Restore del database: ", $bkDBName, $Log));
    if ( ($restore = sqlsrv_query($connect, $sql)) ){
        do{
            $array = sqlsrv_errors();
            echo " Risposta del server: ".$array[0]['message']."n n";
        } while ( sqlsrv_next_result($restore) ) ;
        sqlsrv_free_stmt($restore);
    }
    sqlsrv_close($connect);
}

Alla fine si riesce anche a chiudere la connessione senza problemi.

Dovrà essere testata a fondo in settimana ma penso che questa sia la soluzione definitiva.
Con lo stesso trucchetto potranno essere modificate anche le funzioni di Backup e di verifica del backup.
:fonzie:
 

Ferie80

Nuovo Utente
12 Apr 2012
9
0
0
Per dovere di completezza e per essere corretti fino in fondo nell'uso della programmazione, al posto dei cicli if per trovare il nome del file logico, la cosa migliore da fare è sostituirli con la chiamata SQL RESTORE FILELISTONLY.

Quindi al posto di

PHP:
     if(strpos($file, "_Data")){
         $moveBkDBFile = $bkDBName."_Data";
         $moveBkDBFileLog = $bkDBName."_Log";
     }else if(strpos($file, "_data")){
         $moveBkDBFile = $bkDBName."_data";
         $moveBkDBFileLog = $bkDBName."_log";
     }else{
         $moveBkDBFile = $bkDBName;
         $moveBkDBFileLog = $bkDBName."_log";
     }

è più corretto e soprattutto più sicuro (possono capitare errori di riferimenti tra i vari file) usare:

PHP:
     $sql = "RESTORE FILELISTONLY
               FROM DISK = '".$bkNuovoPathFile."'";
     $restoreFileList = sqlsrv_query($connect, $sql) or trigger_error("La query RESTORE
         FILELISTONLY ha ritornato falso : ".erroriQuerySql2008($restoreFileList, $bkNuovoPathFile,
         "Errore durante la RESTORE FILELISTONLY: ", $bkDBName, $Log));
     while($logicalName = sqlsrv_fetch_array($restoreFileList)){
         if($logicalName['Type'] == 'D'){
             $moveBkDBFile = $logicalName['LogicalName'];
         }else if ($logicalName['Type'] == 'L'){
             $moveBkDBFileLog = $logicalName['LogicalName'];
         }
     }
     @sqlsrv_free_stmt($restoreFileList);

e lasciare tutto il resto inalterato.
 
Discussioni simili
Autore Titolo Forum Risposte Data
L Aiuto per programma web php/mySQL PHP 2
G Programma alternativo all'Easy PHP PHP 7
F aprire programma video da script php PHP 2
L installazione programma php PHP 6
T programma php divisori di u numero PHP 11
S debug programma php PHP 2
G Finestra di dialogo che non si apre - programma NUENDO Windows e Software 0
M Start-up programma di affiliazione Vendere e Acquistare pubblicita' online 0
miglior servizio1 programma per incrementare seguaci su instagram Annunci servizi di Social Media Marketing 0
L Programma per registrare solo schermo Mac e Software 4
F programma che vi permette di ottenere like e followers! senza limiti Annunci servizi di Social Media Marketing 0
M [HTML] come si chiama questo programma HTML e CSS 1
G Programma per monitorare cpu e memoria Windows e Software 6
A con che programma creo il mio sito? Webdesign e Grafica 1
Alias85 Programma per un gioco Offerte e Richieste di Lavoro e/o Collaborazione 3
K [javascript] Aiuto per programma subnetting Javascript 0
D programma creare siti web Windows e Software 9
F Programma C per la gestione di grandi quantità di dati C/C++ 0
J C# Programma console che calcola il volume di una scatola .NET Framework 2
J Programma che prende continuamente input da console .NET Framework 1
A Affiliatery - Italia programma affiliati Guadagnare col Sito 0
N Programma di Affiliazione / Mondo Trading Guadagnare col Sito 0
MarcoGrazia Il programma non invia i dati richiesti AJAX jQuery 3
C Programma di conversione da Immagine a PDF Windows e Software 5
filippino Programma di affiliazione che remunera in Bitcoin? Guadagnare col Sito 3
1 Errore di istallazione programma vb2010 con access in allegato MS Access 8
1 Problema riscontrato nell'esecuzione da programma istallato Programmazione 0
felino Edit video: quale programma consigliate? Windows e Software 2
N Programma per gestire Cookies secondo disposizioni del Garante Privacy 3/6/2014 G.U. 126 Leggi, Normative e Fisco 0
N nuovo utente - programma di affiliazione Presentati al Forum 6
il_bauscia errori di file system: programma free per correggere? Hardware 1
filippino Programma per criptare cartelle in windows 8 Windows e Software 1
filippino Programma per fare l'immagine dell'hard disk Windows e Software 2
Sevenjeak Controllare dipendenze del programma Java 1
F problema con programma ecomerce PHP 0
felino Web Scraping: qualche programma usare? Windows e Software 2
P Problemi disinstallazione programma Windows e Software 1
A Aiuto distribuzione programma VC++ C/C++ 0
S programma affiliazione Guadagnare col Sito 0
H Debugger per programma? .NET Framework 1
F Esiste un programma che verifica la home page e la corregge automaticamente? HTML e CSS 7
H Programma in vb che logga in un sito? Visual Basic 1
P Programma per estrarre email...consigli ! Email Marketing 0
F programma di affiliazione 24option. Guadagnare col Sito 0
C Problemi con il programma Gimp Webdesign e Grafica 0
Frank10 Quale programma usate per fare siti? HTML e CSS 48
A spiegazione del programma che implementa gli alberi in java Java 7
max_400 Programma pubblicitario nel broswer!! AIUTO!!!!, Google Chrome.... Discussioni Varie 5
B Programma in Joomla Joomla 2
orlakio esiste un programma che richiede il tuo nome all'entrata di un sito e poi ti saluta?!?!?!? Javascript 4

Discussioni simili