L'attività di backup pianificata non esegue sempre il backup di tutti i database nonostante abbia sempre detto che il lavoro è andato a buon fine


9

Ho un lavoro in SQL 2008 che esegue un proc memorizzato per il backup di tutti i database. Questo viene eseguito quotidianamente tramite il lavoro dell'agente server SQL.

Si chiude con successo ogni giorno ma alcuni giorni si chiude con successo solo dopo aver eseguito il backup di alcuni database. Può essere ogni volta un numero diverso di database. Quasi tutti i giorni esegue correttamente il backup di tutti i database ma a volte 2 eseguono correttamente il backup, a volte 5, ecc.

Non vedo errori nella cronologia dei lavori, nel visualizzatore eventi o nel registro del server sql.

I backup vengono eseguiti su un disco locale, sebbene la cartella sia un "nodo" per una cartella su un volume di archiviazione espandibile.

Il sistema operativo è Windows 2003 a 64 bit con Sql Server 2008 Web Edition 64 bit come macchina virtuale in esecuzione su host Vmware ESXi 5.

Stored procedure:

ALTER PROCEDURE [dbo].[backup_all_databases] 
@path VARCHAR(255)='c:\backups\'

AS

DECLARE @name VARCHAR(50) -- database name  
DECLARE @fileName VARCHAR(256) -- filename for backup  
DECLARE @fileDate VARCHAR(20) -- used for file name 
DECLARE @dbIsReadOnly sql_variant -- is database read_only?
DECLARE @dbIsOffline sql_variant -- is database offline?

DECLARE db_cursor CURSOR FOR  
SELECT name 
FROM master.dbo.sysdatabases 
WHERE name NOT IN ('tempdb')
AND version > 0 AND version IS NOT NULL

OPEN db_cursor   
FETCH NEXT FROM db_cursor INTO @name   

WHILE @@FETCH_STATUS = 0   
BEGIN   
SET @fileName = @path + @name + '.bak'

SET @dbIsReadOnly = (SELECT DATABASEPROPERTY(@name, 'IsReadOnly')) -- 1 = Read Only
SET @dbIsOffline = (SELECT DATABASEPROPERTY(@name, 'IsOffline')) -- 1 = Offline

IF (@dbIsReadOnly = 0 OR @dbIsReadOnly IS NULL) AND @dbIsOffline =0
BEGIN
    BACKUP DATABASE @name TO DISK = @fileName  WITH INIT
    WAITFOR DELAY '00:00:20'
END

FETCH NEXT FROM db_cursor INTO @name 
END   

CLOSE db_cursor   
DEALLOCATE db_cursor

Qualche suggerimento per favore?

Risposte:


9

Aggiungerei blocchi TRY / CATCH per gestire gli errori e registrarli. Il DB potrebbe essere in un singolo utente, essere ripristinato o altro.

Senza questo, gli errori possono essere annullati in modo tale che non vengano registrati errori (istruzione, batch, ambito, connessione ecc.)

Con TRY / CATCH viene registrato tutto tranne gli errori di compilazione o di interruzione della connessione? ma dubito che sia così.

Vorrei anche usare sys.database che sostituisce sysdatabase e leggere più flag:

-- declares etc

BEGIN TRY

    DECLARE db_cursor CURSOR FOR  
    SELECT name, state, user_access
    FROM sys.databases 
    WHERE name NOT IN ('tempdb')

    OPEN db_cursor   
    FETCH NEXT FROM db_cursor INTO @name, @state, @user_access

    WHILE @@FETCH_STATUS = 0   
    BEGIN   

        SET @fileName = @path + @name + '.bak'
        IF @state = 0 AND user_access = 0
        BEGIN
            BEGIN TRY
                BACKUP DATABASE @name TO DISK = @fileName  WITH INIT
            END TRY
            BEGIN CATCH
                -- log but do not rethrow so loop continues
            END CATCH
            WAITFOR DELAY '00:00:20'
        END
        ELSE
           --log user and/or state issues

        FETCH NEXT FROM db_cursor INTO @name 
    END   

    CLOSE db_cursor   
    DEALLOCATE db_cursor

END TRY
BEGIN CATCH
  -- some useful stuff here
END CATCH

+1 per il consiglio di utilizzare i database sys
Peter Schofield il

2

Controlla gli errori dopo il comando "backup", invia la tua e-mail per eventuali errori rilevati.

Questo ti darà un punto di partenza per vedere cosa sta succedendo e garantendoti di avvisarti di eventuali problemi fino a quando non avrai risolto il problema del lavoro.


2

Metti un ordine vicino al cursore. Ho visto i cursori dei database sys avere "problemi" quando si consente a SQL di selezionare l'ordine in cui i dati vengono restituiti. Ordinare per nome dovrebbe essere sufficiente.


2

Il backup è in esecuzione contemporaneamente al backup su nastro o ad altri processi che copiano o accedono ai file di backup? In tal caso, scommetto che non è in grado di sovrascrivere il file perché è in uso. Se si dispone di spazio per più copie di backup, è possibile modificare il proprio proc per aggiungere un timbro data al file di output, ma è necessario una routine di pulizia.


Non che ne sia consapevole. Il backup viene eseguito localmente, quindi rsincronizzato offsite poche ore dopo.
Andy Davies,

0

Con l'introduzione di SQL Server 2005, il ciclo del cursore attraverso i database sys e persino i database sys sembrava cambiare, quindi non era affidabile - e questo cambiamento nel comportamento poteva essere visto anche con sp_foreachdb.

Ho trovato utile cambiare il tipo di cursore (penso che fosse un avanzamento veloce), ma alla fine sono passato a soluzioni come la soluzione di backup e manutenzione di Ola Hallengren. Come la maggior parte delle cose critiche come i backup, è comunque necessario effettuare un controllo incrociato di tutti i database per assicurarsi che venga eseguito il backup anche con queste potenziali soluzioni - e ovviamente lo hai fatto, così ben fatto!

Tipi di cursori: http://msdn.microsoft.com/en-us/library/ms378405(v=SQL.90).aspx

La soluzione di manutenzione di Ola: http://ola.hallengren.com/


0

Ho avuto lo stesso problema, soprattutto durante il backup di DB di grandi dimensioni.

@@fetch_statusè una variabile GLOBALE, quindi potrebbe essere modificata (impostata su 0) da un cursore diverso dal tuo. L'ho risolto nel modo seguente (in pseudocodice):

create a temp table with dbNames
select top 1 in a variable (use order by)
while variable is null
do your thing

set variable = null
delete top 1(use order by)
select top 1 in a variable (use order by)
loop

-1

Ho provato a capire questo problema e sembra che molte volte gli utenti abbiano pubblicato la soluzione che se si rende insensibile la dichiarazione del cursore, allora inizia a funzionare. Quindi l'ho provato e sì, mi assicuro solo che il cursore dichiari sia statico e inizi a funzionare.

Il fatto per cui ha esito negativo è - Controlla l'impostazione della soglia del cursore a livello del server - se è configurato come -1, significa che tutti i cursori vengono popolati in modo sincrono in altre parole mentre si tenta di leggere i dati del set di chiavi del cursore è sincrono e si tenta di leggi allo stesso tempo. Se cambiamo questo valore su 0 che dice a SQL Server di eseguire una popolazione asincrona in parole semplici, il cursore può recuperare i record mentre il set di chiavi continuerà a essere popolato e vedrai che dopo aver apportato questa modifica a livello di server non perderai mai alcun database utilizzando cursori.

Soluzioni: dichiarare Cursor Statico o modificare l'impostazione del livello del server "Soglia cursore" su 0 da -1.

Grazie, Gaurav Mishra | DBA senior

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.