Pengantar
Anda dapat menemukan banyak panduan tentang cara membuat cadangan dan memulihkan basis data. Dalam hal ini, kami akan menunjukkan bagaimana hal ini dapat dilakukan dengan menggunakan standar MS SQL Server.
Contoh ini akan mencakup sejumlah pendekatan – mulai dari memeriksa integritas database sebelum mencadangkannya hingga memulihkan database dari salinan cadangan yang dibuat sebelumnya.
Solusinya
Pertama, mari kita lihat keseluruhan algoritme yang akan kita gunakan untuk mencadangkan database:
1) Menentukan basis data mana yang perlu dicadangkan
2) Memeriksa integritas basis data yang dipilih
3) Membuat cadangan (salinan log transaksi, diferensial, atau penuh) untuk setiap basis data yang dipilih
4) Memeriksa salinan cadangan yang dibuat
5) Mengompresi log transaksi (jika diperlukan)
Di bawah, Anda dapat menemukan contoh implementasi algoritme ini.
Untuk menentukan database mana yang perlu dicadangkan, kita akan membuat tabel berikut:
GUNAKAN [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[BackupSettings]( [DBID] [int] NOT NULL, [FullPathBackup] [nvarchar](255) NOT NULL, [DiffPathBackup] [nvarchar](255 ) NULL, [LogPathBackup] [nvarchar](255) NULL, [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_BackupSettings] PRIMARY KEY CLUSTERED ( [DBID] ASC)DENGAN (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, ALLOW_ROW_LOCKS =AKTIF, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY];GOALTER TABLE [srv].[BackupSettings] ADD CONSTRAINT [DF_BackupSettings_InsertUTCDate] DEFAULT (getutcdate()) FOR [InsertPengidentifikasi basis data terletak di kolom pertama, 'FullPathBackup' berisi jalur untuk pembuatan salinan cadangan lengkap (misalnya, 'disk:\…\'), dan DiffPathBackup dan LogPathBackup berisi jalur lengkap untuk pembuatan salinan log diferensial dan transaksi masing-masing. Jika kolom DiffPathBackup atau LogPathBackup kosong, maka salinan log diferensial dan/atau transaksi untuk database ini tidak akan dibuat.
Kami juga dapat membuat representasi berdasarkan tabel ini:
GUNAKAN [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE tampilan [srv].[vBackupSettings]asSELECT [DBID] ,DB_Name([DBID]) sebagai [DBName] ,[FullPathBackup] ,[DiffPathBackup] ,[LogPathBackup] ] DARI [srv].[BackupSettings];GORepresentasi ini memungkinkan Anda untuk secara efektif memeriksa database mana yang berpartisipasi dalam proses pencadangan.
Sekarang, mari kita buat representasi yang menampilkan informasi file database dari representasi sistem sys.master_files:
GUNAKAN [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE view [inf].[ServerDBFileInfo] asSELECT @@Servername AS Server , File_id ,--DB file identifier. Nilai dasar untuk file_id adalah 1 Type_desc ,--Type file description Name as [FileName] ,--DB logical file name LEFT(Physical_Name, 1) AS Drive ,--Drive flag dari lokasi file DB Physical_Name ,--File lengkap nama di OS RIGHT(physical_name, 3) AS Ext ,--File extension Size as CountPage, --Current file size in 8Kb pages round((cast(Size*8 as float))/1024,3) as SizeMb, - -Ukuran file dalam putaran Mb ((cast(Ukuran*8 sebagai float))/1024/1024,3) sebagai SizeGb, --Ukuran file dalam kasus Gb ketika is_percent_growth=0 maka Pertumbuhan*8 jika tidak 0 berakhir sebagai Pertumbuhan, -- Pertumbuhan file dalam kasus halaman 8Kb ketika is_percent_growth=0 lalu bulat((cast(Growth*8 as float))/1024,3) berakhir sebagai GrowthMb, --Pertumbuhan file dalam kasus Mb ketika is_percent_growth=0 lalu round((cast(Growth) *8 sebagai float))/1024/1024,3) diakhiri sebagai GrowthGb, --File pertumbuhan dalam kasus Gb ketika is_percent_growth=1 lalu Pertumbuhan lain 0 berakhir sebagai GrowthPercent, --File pertumbuhan dalam persen is_percent_growth, --Percent growth atribut database_id , DB_ Nama(database_id) as [DB_Name], State,--File state_desc as StateDesc,--Deskripsi status file is_media_read_only as IsMediaReadOnly,--File terletak di drive sebagai read-only (0 - dan untuk menulis) is_read_only sebagai IsReadOnly ,--file ditandai sebagai read-only (0 - dan untuk penulisan) is_sparse sebagai IsSpace,--File jarang is_name_reserved sebagai IsNameReserved,--1 - Nama file jarak jauh, dapat diakses untuk digunakan. --Hal ini diperlukan untuk mendapatkan cadangan log sebelum menggunakan nama yang sama (nama atau argumen nama_fisik) lagi untuk file baru ---0 - Nama file, tidak dapat diakses untuk digunakan create_lsn sebagai CreateLsn,--Nomor pendaftaran transaksi di log (LSN) yang digunakan untuk membuat file drop_lsn sebagai DropLsn,--LSN yang digunakan untuk menghapus file read_only_lsn sebagai ReadOnlyLsn,--LSN yang digunakan oleh grup file yang berisi file untuk mengubah jenis "baca dan tulis" menjadi "baca -only" (perubahan terbaru) read_write_lsn as ReadWriteLsn,--LSN yang digunakan oleh grup file yang berisi file untuk mengubah tipe "read-only" menjadi "read and write" (perubahan terbaru) differential_base_lsn sebagai DifferentialBaseLsn,- -Sebuah dasar untuk salinan cadangan diferensial. Luasan data yang diubah setelah LSN dimasukkan ke dalam cadangan diferensial. differential_base_guid as DifferentialBaseGuid,--Pengidentifikasi unik dari salinan cadangan dasar yang akan digunakan untuk membuat salinan diferensial. differential_base_time as DifferentialBaseTime,--Waktu yang sesuai dengan differential_base_lsn redo_start_lsn sebagai RedoStartLsn,--LSN digunakan untuk menentukan awal pengulangan berikutnya --Is NULL, kecuali untuk kasus di mana state =RESTORING atau state =RECOVERY_PENDING redo_start_fork_guid as RedoStart -Pengidentifikasi unik untuk titik garpu pemulihan --nilai argumen first_fork_guid dari salinan cadangan yang dipulihkan berikutnya harus sama dengan nilai ini redo_target_lsn sebagai RedoTargetLsn,--LSN yang berfungsi sebagai titik berhenti untuk pengulangan mode "online" dalam file ini -- Apakah NULL, kecuali untuk kasus di mana status =RESTORING atau status =RECOVERY_PENDING redo_target_fork_guid sebagai RedoTargetForkGuid,-- Garpu pemulihan tempat wadah dapat dipulihkan. Digunakan bersama dengan redo_target_lsn backup_lsn sebagai BackupLsn--LSN dari data terbaru atau salinan cadangan diferensial fileFROM sys.master_files--database_files;GOUntuk membuat salinan cadangan lengkap, mari terapkan prosedur tersimpan berikut:
[expand title =”Kode “]
GUNAKAN [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunFullBackupDB] @ClearLog bit=1 --menentukan apakah ukuran log transaksi harus dikurangiASBEGIN /* Membuat salinan cadangan DB lengkap dan memeriksa integritas DB sebelumnya */ SET NOCOUNT ON; mendeklarasikan @dt datetime=getdate(); nyatakan @tahun int=TAHUN (@dt); nyatakan @bulan int=BULAN(@dt); mendeklarasikan @hari int=DAY(@dt); deklarasikan @jam int=DatePart(jam, @dt); mendeklarasikan @menit int=DatePart(menit, @dt); mendeklarasikan @second int=DatePart(kedua, @dt); mendeklarasikan @pathBackup nvarchar(255); mendeklarasikan @pathstr nvarchar(255); mendeklarasikan @DBName nvarchar(255); mendeklarasikan @backupName nvarchar(255); mendeklarasikan @sql nvarchar(maks); mendeklarasikan @backupSetId sebagai int; mendeklarasikan @FileNameLog nvarchar(255); mendeklarasikan tabel @tbllog( [DBName] [nvarchar](255) NOT NULL, [FileNameLog] [nvarchar](255) NOT NULL ); mendeklarasikan tabel @tbl ( [DBName] [nvarchar](255) NOT NULL, [FullPathBackup] [nvarchar](255) NOT NULL ); --Mengambil nama DB dan path lengkap untuk pembuatan salinan cadangan penuh, masukkan ke @tbl ( [DBName] ,[FullPathBackup] ) pilih DB_NAME([DBID]), [FullPathBackup] dari [srv].[BackupSettings]; --Mengambil nama DB dan nama log transaksi yang sesuai (karena satu DB dapat memiliki banyak log) masukkan ke @tbllog([NamaDB], [NamaFileLog]) pilih t.[NamaDB], tt.[NamaFile] sebagai [NamaFileLog ] dari @tbl sebagai t batin bergabung [inf].[ServerDBFileInfo] sebagai tt pada t.[DBName]=DB_NAME(tt.[database_id]) di mana tt.[Type_desc]='LOG'; --secara berurutan memproses setiap DB yang kita dapatkan sebelumnya while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; pilih top(1) @DBName=[DBName], @pathBackup=[FullPathBackup] dari @tbl; setel @[email protected]+N'_Full_backup_'+cast(@tahun sebagai nvarchar(255))+N'_'+cast(@bulan sebagai nvarchar(255))+N'_'+cast(@hari sebagai nvarchar(255))--+N'_' --+cast(@hour sebagai nvarchar(255))+N'_'+cast(@minute sebagai nvarchar(255))+N'_'+cast(@ kedua sebagai nvarchar(255)); setel @[email protected]@sqldat.com+N'.bak'; --memeriksa DB untuk integritas set @sql=N'DBCC CHECKDB(N'+N''''[email protected]+N''''+N') WITH NO_INFOMSGS'; exec(@sql); --menjalankan prosedur pembuatan salinan cadangan set @sql=N'BACKUP DATABASE ['[email protected]+N'] TO DISK =N'+N''''[email protected]+N''''+ N' WITH NOFORMAT, NOINIT, NAME =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, REWIND, COMPRESSION, STATS =10;'; exec(@sql); --memeriksa salinan cadangan yang kita buat pilih @backupSetId =position from msdb..backupset where [email protected] dan backup_set_id=(select max(backup_set_id) from msdb..backupset where [email protected]); setel @sql=N'Kesalahan verifikasi. Informasi salinan cadangan untuk database "'[email protected]+'" tidak ditemukan.'; jika @backupSetId adalah null begin raiserror(@sql, 16, 1) end else begin set @sql=N'KEMBALIKAN VERIFYONLY DARI DISK =N'+''''[email protected]+N''''+N' DENGAN FILE ='+cast(@backupSetId as nvarchar(255)); exec(@sql); end --mengompresi log transaksi DB if(@ClearLog=1) begin while(exists(select top(1) 1 from @tbllog where [DBName][email protected])) start pilih top(1) @FileNameLog=FileNameLog dari @tbllog di mana [email protected]; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N'''[email protected]+N''''+N' , 0 , TERPUNCATEON)'; exec(@sql); hapus dari @tbllog di mana [email protected] dan [email protected]; akhiri hapus dari @tbl di mana [DBName][email protected]; akhirENDGO[/expand]
Menurut kodenya, kita dapat melihat bahwa prosedur ini memberikan solusi untuk langkah-langkah selanjutnya dari algoritme pembuatan salinan cadangan.
Prosedur yang membuat diferensial dan salinan log transaksi diimplementasikan dengan cara yang sama:
[expand title =”Kode “]
GUNAKAN [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunDiffBackupDB] @ClearLog bit=1 --menentukan apakah ukuran log transaksi harus dikurangiASBEGIN /* Membuat salinan cadangan DB diferensial */ SET NOCOUNT ON; mendeklarasikan @dt datetime=getdate(); nyatakan @tahun int=TAHUN (@dt); nyatakan @bulan int=BULAN(@dt); mendeklarasikan @hari int=DAY(@dt); deklarasikan @jam int=DatePart(jam, @dt); mendeklarasikan @menit int=DatePart(menit, @dt); mendeklarasikan @second int=DatePart(kedua, @dt); mendeklarasikan @pathBackup nvarchar(255); mendeklarasikan @pathstr nvarchar(255); mendeklarasikan @DBName nvarchar(255); mendeklarasikan @backupName nvarchar(255); mendeklarasikan @sql nvarchar(maks); mendeklarasikan @backupSetId sebagai int; mendeklarasikan @FileNameLog nvarchar(255); mendeklarasikan tabel @tbl ( [DBName] [nvarchar](255) NOT NULL, [DiffPathBackup] [nvarchar](255) NOT NULL ); mendeklarasikan tabel @tbllog( [DBName] [nvarchar](255) NOT NULL, [FileNameLog] [nvarchar](255) NOT NULL ); --Mengambil nama DB dan path lengkap untuk membuat salinan cadangan diferensial masukkan ke @tbl ( [DBName] ,[DiffPathBackup] ) pilih DB_NAME([DBID]), [DiffPathBackup] dari [srv].[BackupSettings] di mana [DiffPathBackup] tidak nol; --Mengambil nama DB dan nama lengkap dari file log transaksi yang sesuai (karena satu DB dapat memiliki banyak log) masukkan ke @tbllog([DBName], [FileNameLog]) pilih t.[DBName], tt.[FileName] as [FileNameLog] dari @tbl sebagai t batin bergabung dengan [inf].[ServerDBFileInfo] sebagai tt pada t.[DBName]=DB_NAME(tt.[database_id]) di mana tt.[Type_desc]='LOG'; --secara berurutan memproses setiap DB yang kita dapatkan sebelumnya while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; pilih top(1) @DBName=[DBName], @pathBackup=[DiffPathBackup] dari @tbl; setel @[email protected]+N'_Diff_backup_'+cast(@tahun sebagai nvarchar(255))+N'_'+cast(@bulan sebagai nvarchar(255))+N'_'+cast(@hari sebagai nvarchar(255))+N'_' +cast(@jam sebagai nvarchar(255))+N'_'+cast(@menit sebagai nvarchar(255))+N'_'+cast(@detik sebagai nvarchar( 255)); setel @[email protected]@sqldat.com+N'.bak'; --memeriksa DB untuk integritas set @sql=N'DBCC CHECKDB(N'+N''''[email protected]+N''''+N') WITH NO_INFOMSGS'; exec(@sql); --menjalankan prosedur pencadangan set @sql=N'BACKUP DATABASE ['[email protected]+N'] TO DISK =N'+N''''[email protected]+N''''+ N' WITH DIFFERENTIAL, NOFORMAT, NOINIT, NAME =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, REWIND, COMPRESSION, STATS =10;'; exec(@sql); --memeriksa salinan cadangan yang baru saja kita buat pilih @backupSetId =posisi dari msdb..backupset di mana [email protected] dan backup_set_id=(pilih maks(backup_set_id) dari msdb..backupset di mana [email protected]); setel @sql=N'Kesalahan verifikasi. Informasi salinan cadangan untuk database "'[email protected]+'" tidak ditemukan.'; jika @backupSetId adalah null begin raiserror(@sql, 16, 1) end else begin set @sql=N'KEMBALIKAN VERIFYONLY DARI DISK =N'+''''[email protected]+N''''+N' DENGAN FILE ='+cast(@backupSetId as nvarchar(255)); exec(@sql); end --mengompresi log transaksi DB if(@ClearLog=1) begin while(exists(select top(1) 1 from @tbllog where [DBName][email protected])) start pilih top(1) @FileNameLog=FileNameLog dari @tbllog di mana [email protected]; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N'''[email protected]+N''''+N' , 0 , TERPUNCATEON)'; exec(@sql); hapus dari @tbllog di mana [email protected] dan [email protected]; akhiri hapus dari @tbl di mana [DBName][email protected]; akhirENDGO[/expand]
Karena memeriksa integritas database membutuhkan banyak sumber daya, kami dapat menghilangkannya saat membuat salinan cadangan diferensial.
[expand title =”Kode “]
GUNAKAN [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunLogBackupDB] @ClearLog bit=1 --menentukan apakah ukuran log transaksi harus dikurangiASBEGIN /* Mencadangkan log transaksi DB */ SET NOCOUNT ON; mendeklarasikan @dt datetime=getdate(); nyatakan @tahun int=TAHUN (@dt); nyatakan @bulan int=BULAN(@dt); mendeklarasikan @hari int=DAY(@dt); deklarasikan @jam int=DatePart(jam, @dt); mendeklarasikan @menit int=DatePart(menit, @dt); mendeklarasikan @second int=DatePart(kedua, @dt); mendeklarasikan @pathBackup nvarchar(255); mendeklarasikan @pathstr nvarchar(255); mendeklarasikan @DBName nvarchar(255); mendeklarasikan @backupName nvarchar(255); mendeklarasikan @sql nvarchar(maks); mendeklarasikan @backupSetId sebagai int; mendeklarasikan @FileNameLog nvarchar(255); mendeklarasikan tabel @tbl ( [DBName] [nvarchar](255) NOT NULL, [LogPathBackup] [nvarchar](255) NOT NULL ); mendeklarasikan tabel @tbllog( [DBName] [nvarchar](255) NOT NULL, [FileNameLog] [nvarchar](255) NOT NULL ); --Mengambil nama DB dan jalur lengkap untuk membuat salinan cadangan dari log transaksi dengan model pemulihan yang tidak sederhana (penuh atau dicatat secara massal). Sistem DB juga dikecualikan masukkan ke @tbl ( [DBName] ,[LogPathBackup] ) pilih DB_NAME(b.[DBID]) ,b.[LogPathBackup] dari [srv].[BackupSettings] sebagai b inner join sys.databases sebagai d pada b.[DBID]=d.[database_id] di mana d.recovery_model<3 dan DB_NAME([DBID]) tidak di ( N'master', N'tempdb', N'model', N'msdb', N' ReportServer', N'ReportServerTempDB' ) dan [LogPathBackup] bukan null; --Mengambil nama DB dan nama lengkap dari file log transaksi yang sesuai (karena satu DB dapat memiliki banyak log) masukkan ke @tbllog([DBName], [FileNameLog]) pilih t.[DBName], tt.[FileName] as [FileNameLog] dari @tbl sebagai t batin bergabung dengan [inf].[ServerDBFileInfo] sebagai tt pada t.[DBName]=DB_NAME(tt.[database_id]) di mana tt.[Type_desc]='LOG'; --secara berurutan memproses setiap DB yang kita dapatkan sebelumnya while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; pilih top(1) @DBName=[DBName], @pathBackup=[LogPathBackup] dari @tbl; setel @[email protected]+N'_Log_backup_'+cast(@tahun sebagai nvarchar(255))+N'_'+cast(@bulan sebagai nvarchar(255))+N'_'+cast(@hari sebagai nvarchar(255))+N'_' +cast(@jam sebagai nvarchar(255))+N'_'+cast(@menit sebagai nvarchar(255))+N'_'+cast(@detik sebagai nvarchar( 255)); setel @[email protected]@sqldat.com+N'.trn'; --melaksanakan prosedur pencadangan set @sql=N'BACKUP LOG ['[email protected]+N'] TO DISK =N'+N''''[email protected]+N''''+ N' WITH NOFORMAT, NOINIT, NAME =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, REWIND, COMPRESSION, STATS =10;'; exec(@sql); --Memeriksa salinan cadangan log transaksi yang baru saja kita buat pilih @backupSetId =position from msdb..backupset where [email protected] dan backup_set_id=(select max(backup_set_id) from msdb..backupset where [email protected]); setel @sql=N'Kesalahan verifikasi. Informasi salinan cadangan untuk database "'[email protected]+'" tidak ditemukan.'; jika @backupSetId adalah null begin raiserror(@sql, 16, 1) end else begin set @sql=N'KEMBALIKAN VERIFYONLY DARI DISK =N'+''''[email protected]+N''''+N' DENGAN FILE ='+cast(@backupSetId as nvarchar(255)); exec(@sql); end --mengompresi log transaksi DB if(@ClearLog=1) begin while(exists(select top(1) 1 from @tbllog where [DBName][email protected])) start pilih top(1) @FileNameLog=FileNameLog dari @tbllog di mana [email protected]; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N'''[email protected]+N''''+N' , 0 , TERPUNCATEON)'; exec(@sql); hapus dari @tbllog di mana [email protected] dan [email protected]; akhiri hapus dari @tbl di mana [DBName][email protected]; akhirENDGO[/expand]
Seperti dikatakan di atas, memeriksa database untuk integritas adalah tugas yang membutuhkan banyak sumber daya. Dikombinasikan dengan fakta bahwa salinan cadangan log transaksi biasanya perlu dibuat cukup sering, ini memberi kami alasan untuk mengabaikan pemeriksaan integritas saat membuat salinan log transaksi.
Harap diingat juga bahwa salinan lengkap database 'master', 'msdb', dan 'model' perlu dilakukan secara berkala.
Untuk mengotomatiskan proses pembuatan salinan cadangan, Anda hanya perlu melakukan panggilan dari prosedur yang sebelumnya diterapkan ke Penjadwal Tugas Windows, tugas agen, atau layanan serupa yang tersedia.
Anda perlu menyetel frekuensi panggilan untuk masing-masing prosedur tersebut satu per satu berdasarkan puncak beban, tingkat aktivitas, dll.
Pendekatan dasarnya adalah sebagai berikut:
1) Membuat salinan cadangan lengkap sekali sehari
2) Membuat salinan cadangan diferensial setiap 2-4 jam
3) Membuat salinan cadangan log transaksi setiap 5-60 menitHarap diingat bahwa biasanya database berpartisipasi dalam sistem akses cepat dan aman-gagal. Dan, jika nanti menggunakan salinan cadangan log transaksi, sangat penting untuk tidak mengganggu prosedur. Lebih khusus lagi, ini berarti bahwa salinan log transaksi tidak boleh dibuat oleh beberapa proses yang berbeda – jika ini terjadi, urutan pencadangan dari salinan ini akan hilang.
Di sini, kita telah melihat contoh setiap database yang diproses secara berurutan, satu per satu. Namun, kami dapat mencapai pemrosesan paralel di lingkungan produksi – memungkinkan beberapa salinan cadangan dibuat secara bersamaan. Ini dapat didekati dengan beberapa cara berbeda. Misalnya, dengan memanggil prosedur tersimpan berikut:
GUNAKAN [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [inf].[RunAsyncExecute]( @sql nvarchar(max), @jobname nvarchar(57) =null, @database nvarchar(128)=null, @owner nvarchar( 128) =null)SEBAGAIMANA MULAI/* Eksekusi paket asinkron melalui pekerjaan Agen RunAsyncExecute - eksekusi asinkron dari perintah T-SQL atau prodecure tersimpan 2012 Antonin Foller, Perangkat Lunak Motobit, www.motobit.com http://www.motobit.com/ tips/detpg_async-execute-sql/ */ SET NOCOUNT ON; mendeklarasikan @id uniqueidentifier; --Buat nama pekerjaan unik jika nama tidak ditentukan jika (@namapekerjaan adalah null) set @namapekerjaan=''; set @namapekerjaan =@namapekerjaan + '_async_' + convert(varchar(64),NEWID()); if (@owner is null) set @owner ='sa'; --Buat pekerjaan baru, dapatkan ID pekerjaan, jalankan msdb..sp_add_job @jobname, @[email protected], @[email protected] OUTPUT; --Tentukan server pekerjaan untuk menjalankan pekerjaan msdb..sp_add_jobserver @[email protected]; --Tentukan langkah pertama pekerjaan - perintah SQL --(@on_success_action =3 ... Lanjutkan ke langkah berikutnya) jalankan msdb..sp_add_jobstep @[email protected], @step_name='Step1', @command =@sql, @database_name =@database, @on_success_action =3; --Tentukan langkah berikutnya dari pekerjaan - hapus pekerjaan tersebut menyatakan @deletecommand varchar(200); set @deletecommand ='jalankan msdb..sp_delete_job @job_name='''[email protected]+''''; jalankan msdb..sp_add_jobstep @[email protected], @step_name='Step2', @command =@deletecommand; --Mulai pekerjaan, jalankan msdb..sp_start_job @[email protected]; SELESAIDi sini, asinkroni dicapai dengan membuat tugas Agen secara dinamis, menjalankan dan menghapusnya setelahnya.
Sekarang, mari kita lihat algoritme umum untuk memulihkan basis data dari salinan cadangan yang sebelumnya dibuat di lingkungan pengujian/berbeda:
1) Menentukan basis data mana yang harus dipulihkan dan lokasi salinan cadangannya
2) Memulihkan basis data
3) Memeriksa integritas basis data yang dipulihkanSekarang, kita akan melihat implementasi algoritme yang memulihkan database dari salinan cadangan penuh. Untuk salinan diferensial, prosedurnya serupa – satu-satunya perbedaan adalah salinan cadangan lengkap harus dipulihkan secara langsung, diikuti oleh salinan diferensial.
Untuk menentukan database mana yang harus dipulihkan, serta lokasi salinan cadangannya, mari buat dua tabel seperti yang ditunjukkan di bawah ini:
GUNAKAN [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[RestoreSettings]( [DBName] [nvarchar](255) NOT NULL, [FullPathRestore] [nvarchar](255) NOT NULL, [DiffPathRestore] [nvarcharRestore] [nvarchar] ](255) NOT NULL, [LogPathRestore] [nvarchar](255) NOT NULL, [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_RestoreSettings] PRIMARY KEY CLUSTERED ( [DBName] ASC)DENGAN (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE , IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY];GOALTER TABLE [srv].[RestoreSettings] TAMBAHKAN CONSTRAINT [DF_RestoreSettings_InsertDi sini, tujuan kolom serupa dengan yang ada di tabel [srv].[BackupSettings]. Satu-satunya perbedaan adalah bahwa jalur lengkap akan digunakan untuk menemukan salinan cadangan untuk pemulihan, dan bukan untuk membuat yang baru.
GUNAKAN [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[RestoreSettingsDetail]( [Row_GUID] [uniqueidentifier] NOT NULL, [DBName] [nvarchar](255) NOT NULL, [SourcePathRestore] [nvarchar](255] ) NOT NULL, TargetPathRestore [nvarchar](255) NOT NULL, [Ext] [nvarchar](255) NOT NULL, [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_RestoreSettingsDetail] PRIMARY KEY CLUSTERED ( [Row_GUID] ASC)DENGAN ( PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY];GOALTER TABLE [srv].[srv_RestoreSettingsDetail] ADD_RestoreDetailPengaturan] UNTUK [Row_GUID];GOALTER TABLE [srv].[RestoreSettingsDetail] ADD CONSTRAINT [DF_RestoreSettingsDetail_InsertUTCDate] DEFAULT (getutcdate()) FOR [InsertUTCDate];GOTabel ini diperlukan untuk menentukan nama file lengkap dari database yang dipulihkan, yang kemudian digunakan untuk transfer lebih lanjut (misalnya, [SourcePathRestore]='Logical file name' dan [TargetPathRestore]='disk:\…\Nama file fisik ', while [Ext]='Ekstensi file')
Sebenarnya, kita dapat mendefinisikan nama logis dari file database menggunakan query berikut:
KEMBALIKAN FILELISTONLY FROM DISK ='disk:\...\backup copy.BAK';Mendapatkan informasi tentang salinan cadangan yang terletak di file dapat dilakukan dengan cara ini:
RESTORE HEADERONLYFROM DISK='disk:\...\backup copy.BAK';Selanjutnya, kami memiliki implementasi prosedur tersimpan yang digunakan untuk memulihkan database dari salinan cadangan lengkap dan memeriksa integritas datanya:
[expand title =”Kode “]
GUNAKAN [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunFullRestoreDB]ASBEGIN /* Memulihkan DB dari salinan cadangan penuh dan memeriksa integritas DB */ SET NOCOUNT ON; deklarasikan @dt datetime=TambahTanggal(hari,-2,getdate()); nyatakan @tahun int=TAHUN (@dt); nyatakan @bulan int=BULAN(@dt); mendeklarasikan @hari int=DAY(@dt); deklarasikan @jam int=DatePart(jam, @dt); mendeklarasikan @menit int=DatePart(menit, @dt); mendeklarasikan @second int=DatePart(kedua, @dt); mendeklarasikan @pathBackup nvarchar(255); mendeklarasikan @pathstr nvarchar(255); mendeklarasikan @DBName nvarchar(255); mendeklarasikan @backupName nvarchar(255); mendeklarasikan @sql nvarchar(maks); mendeklarasikan @backupSetId sebagai int; mendeklarasikan @FileNameLog nvarchar(255); mendeklarasikan @SourcePathRestore nvarchar(255); mendeklarasikan @TargetPathRestore nvarchar(255); mendeklarasikan @Ext nvarchar(255); mendeklarasikan tabel @tbl ( [DBName] [nvarchar](255) NOT NULL, [FullPathRestore] [nvarchar](255) NOT NULL ); mendeklarasikan tabel @tbl_files ( [DBName] [nvarchar](255) NOT NULL, [SourcePathRestore] [nvarchar](255) NOT NULL, [TargetPathRestore] [nvarchar](255) NOT NULL, [Ext] [nvarchar](255) TIDAK NULL ); --mengambil daftar nama DB dan jalur ke salinan cadangan penuh masukkan ke @tbl ( [DBName] ,[FullPathRestore] ) pilih [DBName] ,[FullPathRestore] dari [srv].[RestoreSettings]; --mengambil info detail tentang lokasi file DB baru yang dimasukkan ke @tbl_files ( [DBName] ,[SourcePathRestore] ,[TargetPathRestore] ,[Ext] ) pilih [DBName] ,[SourcePathRestore] ,[TargetPathRestore] ,[Ext] dari [ srv].[RestoreSettingsDetail]; --memproses setiap DB yang kita dapatkan sebelumnya while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; pilih top(1) @DBName=[DBName], @pathBackup=[FullPathRestore] dari @tbl; setel @[email protected]+N'_Full_backup_'+cast(@tahun sebagai nvarchar(255))+N'_'+cast(@bulan sebagai nvarchar(255))+N'_'+cast(@hari sebagai nvarchar(255))--+N'_' --+cast(@hour sebagai nvarchar(255))+N'_'+cast(@minute sebagai nvarchar(255))+N'_'+cast(@ kedua sebagai nvarchar(255)); setel @[email protected]@sqldat.com+N'.bak'; --membuat kueri cadangan dan menjalankannya, setel @sql=N'RESTORE DATABASE ['[email protected]+N'_Restore] FROM DISK =N'+N''''[email protected]+N''' '+ N' DENGAN FILE =1,'; while(exists(select top(1) 1 from @tbl_files where [DBName][email protected])) mulai pilih top(1) @SourcePathRestore=[SourcePathRestore], @TargetPathRestore=[TargetPathRestore], @Ext=[Ext] dari @tbl_files di mana [DBName][email protected]; set @[email protected]+N' PINDAHKAN N'+N''''[email protected]+N''''+N' KE N'+N''''[email protected]+N' _Restore.'[email protected]+N''''+N','; hapus dari @tbl_files di mana [DBName][email protected] dan [SourcePathRestore][email protected] dan [Ext][email protected]; akhir set @[email protected]+N' NOUNLOAD, REPLACE, STATS =5'; exec(@sql); --memeriksa DB untuk integritas set @sql=N'DBCC CHECKDB(N'+N''''[email protected]+'_Restore'+N''''+N') WITH NO_INFOMSGS'; exec(@sql); hapus dari @tbl di mana [DBName][email protected]; akhirEND[/expand]
Untuk menentukan salinan cadangan lengkap mana yang harus digunakan untuk pemulihan, nama file terstruktur khusus digunakan:
_Full_backup_ _ _ .bak Untuk mengotomatiskan proses pemulihan basis data ini, panggilan prosedur tersimpan yang kami terapkan harus ditempatkan ke dalam Penjadwal Tugas Windows, pekerjaan Agen, atau layanan serupa yang tersedia.
Anda dapat melihat salinan cadangan database terbaru menggunakan representasi berikut:
GUNAKAN [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE VIEW [inf].[vServerLastBackupDB] aswith backup_cte as( pilih bs.[database_name], backup_type =case bs.[type] ketika 'D' lalu 'database' ketika 'L ' lalu 'log' ketika 'saya' lalu 'diferensial' else 'other' berakhir, bs.[first_lsn], bs.[last_lsn], bs.[backup_start_date], bs.[backup_finish_date], cast(bs.[backup_size] sebagai desimal(18,3))/1024/1024 sebagai BackupSizeMb, rownum =row_number() over ( partisi oleh bs.[nama_basis data], ketik urutan berdasarkan bs.[backup_finish_date] desc ), LogicalDeviceName =bmf.[logical_device_name], PhysicalDeviceName =bmf.[nama_perangkat_fisik], bs.[nama_server], bs.[nama_pengguna] FROM msdb.dbo.backupset bs INNER GABUNG msdb.dbo.backupmediafamily bmf AKTIF [bs].[media_set_id] =[bmf].[media_set_id]) pilih [nama_server] sebagai [NamaServer], [nama_basis data] sebagai [Nama_DB], [nama_pengguna] sebagai [NamaPengguna], [jenis_cadangan] sebagai [Jenis Cadangan], [tanggal_mulai_cadangan] sebagai [Tanggal Mulai Cadangan], [tanggal_akhir_cadangan] sebagai [TanggalBackupFinish], [UkuranUkuran Cadangan], -- ukuran tidak terkompresi [LogicalDeviceName], [PhysicalDeviceName], [first_lsn] sebagai [FirstLSN], [last_lsn] sebagai [LastLSN]dari backup_ctewhere rownum =1;Hasilnya
Dalam panduan ini, kita telah melihat implementasi proses pencadangan otomatis pada satu server dan pemulihan berikutnya pada server yang berbeda (server uji, misalnya).
Metode ini memungkinkan kami untuk mengotomatiskan proses pembuatan salinan cadangan, untuk memeriksa salinan cadangan dengan memulihkannya dan menyempurnakan proses yang ditunjukkan di atas.
Sumber:
Cadangan
Pulihkan
Backupset
CHECKDB
SHRINKFILE
sys.master_files