Tugas cadangan yang dijadwalkan tidak selalu membuat cadangan semua basis data meskipun selalu mengatakan pekerjaan berhasil

9

Saya punya pekerjaan di SQL 2008 yang menjalankan proc tersimpan untuk membuat cadangan semua database. Ini berjalan setiap hari melalui pekerjaan agen server sql.

Itu berhenti dengan sukses setiap hari tetapi beberapa hari itu berhenti dengan sukses hanya setelah membuat cadangan beberapa database. Ini bisa menjadi jumlah database yang berbeda setiap kali. Hampir setiap hari berhasil mencadangkan semua basis data, tetapi terkadang 2 pencadangan berhasil, kadang-kadang 5, dll.

Saya tidak melihat kesalahan dalam riwayat pekerjaan, penampil acara, atau log server sql.

Pencadangan sedang berlangsung ke disk lokal, meskipun folder tersebut merupakan "persimpangan" ke folder pada volume penyimpanan yang dapat diperluas.

OS adalah Windows 2003 64bit yang menjalankan Sql Server 2008 edisi web 64 bit sebagai mesin virtual yang berjalan pada host Vmware ESXi 5.

Prosedur tersimpan:

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

Ada saran?

Andy Davies
sumber

Jawaban:

9

Saya akan menambahkan TRY / CATCH blok untuk menangani kesalahan dan mencatatnya. DB bisa dalam satu pengguna, sedang dipulihkan atau apa pun.

Tanpa ini, kesalahan dapat dibatalkan dengan cara yang tidak ada kesalahan dicatat (pernyataan, batch, ruang lingkup, koneksi dll)

Dengan TRY / CATCH maka semuanya kecuali untuk kompilasi atau kesalahan pembatalan koneksi dicatat? tapi saya ragu ini masalahnya.

Saya juga menggunakan sys.databases yang menggantikan sysdatabases dan membaca lebih banyak 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
gbn
sumber
+1 untuk saran untuk menggunakan sys.databases
Peter Schofield
2

Periksa kesalahan setelah perintah "cadangan", kirim email Anda sendiri untuk setiap kesalahan yang terdeteksi.

Ini akan memberi Anda titik awal untuk melihat apa yang sedang terjadi, dan menjamin untuk memberi tahu Anda tentang masalah apa pun sampai Anda menyelesaikan masalah pekerjaan.

Jimbo
sumber
2

Lakukan pemesanan pada kursor. Saya telah melihat kursor ke sys.databases memiliki "masalah" ketika Anda mengizinkan SQL untuk memilih urutan data dikembalikan. Memesan berdasarkan nama sudah cukup.

mrdenny
sumber
2

Apakah cadangan berjalan bersamaan dengan cadangan untuk direkam atau proses lain menyalin atau mengakses file cadangan? Jika demikian, saya berani bertaruh itu gagal menimpa file karena sedang digunakan. Jika Anda memiliki ruang untuk beberapa salinan cadangan, Anda bisa mengubah proc Anda untuk menambahkan cap tanggal ke file output, tetapi kemudian Anda akan memerlukan pembersihan rutin.

SqlACID
sumber
Bukannya aku sadar. Pencadangan dilakukan secara lokal kemudian rsync-ed di luar kantor beberapa jam kemudian.
Andy Davies
0

Dengan diperkenalkannya SQL Server 2005, loop kursor melalui sysdatabases dan bahkan sys.databases tampaknya berubah sehingga tidak dapat diandalkan - dan perubahan perilaku ini dapat dilihat dengan sp_foreachdb juga.

Saya menemukan mengubah jenis kursor membantu (saya pikir itu maju cepat), tetapi pada akhirnya saya beralih ke solusi seperti solusi cadangan dan pemeliharaan Ola Hallengren. Seperti kebanyakan hal yang sangat penting seperti cadangan, Anda masih perlu memeriksa silang semua database untuk memastikan mereka didukung bahkan dengan solusi potensial ini - dan tentu saja Anda lakukan, dilakukan dengan sangat baik!

Jenis kursor: http://msdn.microsoft.com/en-us/library/ms378405(v=SQL.90).aspx

Solusi pemeliharaan Ola: http://ola.hallengren.com/

Peter Schofield
sumber
0

Saya memiliki masalah yang sama, terutama saat membuat cadangan DB besar.

@@fetch_statusadalah variabel GLOBAL, jadi mungkin diubah (disetel ke 0) oleh kursor lain dari Anda. Saya menyelesaikannya dengan melakukan hal berikut (dalam pseudocode):

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
Gerrit
sumber
-1

Saya telah mencoba untuk mencari tahu masalah ini dan tampaknya banyak kali pengguna memposting solusi bahwa jika Anda membuat pernyataan kursor tidak sensitif maka itu mulai berfungsi. Jadi saya mengujinya dan ya itu hanya memastikan Anda menyatakan kursor statis dan mulai bekerja.

Fakta yang gagal adalah - Periksa pengaturan ambang batas kursor tingkat server Anda - jika dikonfigurasi sebagai -1 maka itu berarti semua kursor diisi secara serempak dengan kata lain saat mencoba membaca data kunci set data kursor yang sinkron dan semua dicoba untuk baca pada waktu bersamaan. Jika kami mengubah nilai ini ke 0 yang memberitahu SQL server untuk melakukan populasi asinkron dalam kata-kata sederhana kursor dapat mengambil catatan sementara set kunci masih akan diisi dan Anda akan melihat bahwa setelah melakukan perubahan ini di tingkat server Anda tidak akan pernah melewatkan database menggunakan kursor.

Solusi: Mengumumkan kursor Statis Atau Mengubah pengaturan level Server "Kursor Kursor" menjadi 0 dari -1.

Terima kasih, Gaurav Mishra | DBA senior

pengguna44716
sumber