Статьи

Запланированные резервные копии SQL Server с помощью NAnt

При установке и использовании производственных веб-приложений резервное копирование всегда необходимо. Я уже писал о SQL Server Backup, и этот пост будет посвящен этому вопросу. Основной целью здесь является создание решения, которое периодически создает резервную копию вашей базы данных. Для этого мы будем использовать скрипт резервного копирования из предыдущего поста, использовать NAnt для выполнения скрипта и заархивировать созданную резервную копию. Наконец, мы планируем выполнение сценария сборки NAnt с помощью планировщика задач Windows или команды «at». Эта процедура может сделать резервную копию локального или удаленного сервера SQL (если удаленный сервер находится в одной сети).

Предпосылки

  • Установленная и настроенная версия NAnt (см. Начало работы с NAnt — .NET Build Tool )
  • Установленные задачи NAntContrib (для задачи SQL см. NAntContrib на SourceForge)
  • Служба планировщика заданий включена в Панель управления / Инструменты администратора / Службы
  • Вход в SQL с правами dbo для базы данных (для установки процедуры backupDatabase)
  • Логин SQL, который имеет «публичные» права на базу данных (чтобы он мог выполнять резервное копирование)

Процедура резервного копирования SQL

Сценарий ниже с созданием хранимой процедуры SQL-сервера для создания файла резервной копии данной базы данных. Требуется два параметра:

  1. databaseName — база данных сервера SQL, для которой нужно создать резервную копию
  2. backupDirectory — каталог, в котором будет создан файл резервной копии.

Вам необходимо выполнить его для базы данных, для которой вы будете выполнять резервное копирование, и дать «публичной» роли права на выполнение процедуры.

Код

exec dbo.sp_executesql @statement = N'
/*
Created:
07.18.2008 by Boyan Kostadinov ([email protected])

Dependencies:
None

Usage:
exec dbo.backupDatabase ''ensembleVideo'', ''C:\Temp''

Parameters:
@databaseName - varchar
- The database to backup

@backupDirectory - varchar
- The path to where the database should be
backed up. This should be an existing directory on
the SQL Server where the database is located

Description:
Backsup a given database to the specified directory
*/
create procedure dbo.backupDatabase
@databaseName varchar(100),
@backupDirectory varchar(1000)
as
declare @backupFileName varchar(100),
@databaseDataFilename varchar(100), @databaseLogFilename varchar(100),
@databaseDataFile varchar(100), @databaseLogFile varchar(100),
@execSql varchar(1000)

-- If the backup directory does not end with ''\'', append one
if charindex(''\'', reverse(@backupDirectory)) > 1
set @backupDirectory = @backupDirectory + ''\''

-- Create the backup file name based on the backup directory, the database name and today''s date
set @backupFileName = @backupDirectory + @databaseName + ''-'' + replace(convert(varchar, getdate(), 110), ''-'', ''.'') + ''.bak''

set @execSql = ''
backup database ['' + @databaseName + '']
to disk = '''''' + @backupFileName + ''''''
with
noformat,
noinit,
name = '''''' + @databaseName + '' backup'''',
norewind,
nounload,
skip''

exec(@execSql)'
go

Сценарий резервного копирования NAnt

Сценарий несколько сложен. Вот список возможностей:

  • Сделайте резервную копию локального экземпляра SQL Server или экземпляра SQL Server в той же сети. Ключевым моментом является то, что файловая система сетевого экземпляра должна быть доступна через общие ресурсы UNC для машины, на которой выполняется сценарий резервного копирования.
  • Используйте указанную строку подключения или прочитайте строку подключения из файла конфигурации .NET (или другого типа XML).

Я не буду углубляться в сам скрипт, так как его свойства и процесс документированы достаточно хорошо.

Код

<project name="backupDatabase" default="run" xmlns="http://nant.sf.net/release/0.86-beta1/nant.xsd">
<!-- Set the name of the backup file that will be created -->
<property name="zipFileName" value="databaseBackup" overwrite="false" />

<!-- Set the path where the backup file will be finally stored -->
<property name="localBackupDirectory" value="C:\Temp" overwrite="false" />

<!-- Set the local path (relative to the SQL Server instance) where SQL Server will write the backup file -->
<!-- This has to always be a local path since SQL server can't write to network paths -->
<property name="sqlServerLocalBackupDirectory" value="C:\Temp" overwrite="false" />

<!-- Set the UNC path to the above "sqlServerLocalBackupDirectory" local path -->
<!-- This is only needed if you are backing up SQL server on the network -->
<property name="sqlServerUNCBackupDirectory" value="\\beehive\windows$\Temp" overwrite="false" />
<!-- For backing up a local SQL Server instance, commented the first "sqlServerUNCBackupDirectory" property -->
<!-- and uncommented the one below this line, or set the "sqlServerUNCBackupDirectory" property to "" -->
<!--<property name="sqlServerUNCBackupDirectory" value="" overwrite="false" />-->

<!-- Set the .NET connection string for connecting to the database -->
<!-- This setting always takes precedence over the config file below -->
<!-- To use a config file instead, set this property to "" (like so value="") -->
<property name="connectionString" value="Data Source=beehive\sql2005;Initial Catalog=ensembleVideo;User ID=test;Password=test;" overwrite="false" />

<!-- Alternatively set the path to where the build script should get the connection string from -->
<!-- This is usually a app.config or connectionString.config file -->
<property name="connectionStringConfigFilePath" value="C:\Inetpub\wwwroot\myApp\config\connectionStrings.config" overwrite="false" />

<!-- Set the XPath expression that will be used to grab the connection string from the config file -->
<property name="connectionStringXPath" value="/connectionStrings/add[@name = 'sqlServerConnection']/@connectionString" overwrite="false" />

<!-- Set the regular expression that's needed to get the database name from the connection string -->
<property name="getDatabaseNameFromConnecionStringRegEx" value="Initial Catalog=(?'databaseName'.*?);" overwrite="false" />

<property name="todaysDate" value="${string::substring(string::replace(datetime::to-string(datetime::now()), '/', '.'), 0, 10)}" />
<property name="todaysLocalBackupDirectory" value="${path::combine(localBackupDirectory, todaysDate)}" />

<target name="run">
<!-- If the SQL Server UNC directory was not specified and the local backup directory exists -->
<if test="${string::get-length(sqlServerUNCBackupDirectory) == 0 and directory::exists(localBackupDirectory)}">
<!-- This is a back of a local SQL Server instance -->
<mkdir dir="${todaysLocalBackupDirectory}" />

<property name="todaysSqlServerLocalBackupDirectory" value="${todaysLocalBackupDirectory}" />
<property name="todaysSqlServerUNCBackupDirectory" value="${todaysLocalBackupDirectory}" />

<property name="localSqlServer" value="true" />
</if>

<if test="${string::get-length(sqlServerUNCBackupDirectory) > 0 and directory::exists(sqlServerUNCBackupDirectory) }" >
<property name="todaysSqlServerLocalBackupDirectory" value="${path::combine(sqlServerLocalBackupDirectory, todaysDate)}" />
<property name="todaysSqlServerUNCBackupDirectory" value="${path::combine(sqlServerUNCBackupDirectory, todaysDate)}" />

<!-- This is a back of a networked SQL Server instance -->
<mkdir dir="${todaysSqlServerUNCBackupDirectory}" />

<property name="localSqlServer" value="false" />
</if>

<!-- If the connection string is empty,
the connection string file exists and the XPath to find the connection string is not empty -->
<if test="${string::get-length(connectionString) == 0 and file::exists(connectionStringConfigFilePath)
and string::get-length(connectionStringXPath) > 0}" >
<!-- Get the connection string to the database from the connection string config file -->
<xmlpeek
file="${connectionStringConfigFilePath}"
xpath="${connectionStringXPath}"
property="connectionString">
</xmlpeek>
</if>

<!-- If the connectionString property is not empty and the regular expression to get the database name is not empty -->
<if test="${string::get-length(connectionString) > 0 and string::get-length(getDatabaseNameFromConnecionStringRegEx) > 0}">
<!-- Get the database name from the connection string -->
<regex pattern="${getDatabaseNameFromConnecionStringRegEx}" input="${connectionString}" />

<!-- Execute the stored procedure to bckup the database -->
<sql connstring="Provider=SQLOLEDB;${connectionString}" transaction="false" delimiter=";" delimstyle="Normal">
exec dbo.backupDatabase '${databaseName}', '${todaysSqlServerLocalBackupDirectory}';
</sql>

<!-- Zip up the created databse backup file -->
<zip zipfile="${path::combine(todaysSqlServerUNCBackupDirectory, zipFileName + '-' + todaysDate + '.zip')}" ziplevel="9">
<fileset basedir="${todaysSqlServerUNCBackupDirectory}">
<exclude name="**/*.zip" />
<include name="*.*" />
</fileset>
</zip>

<!-- Delete all other files in the today's backup directory except for the created zip files -->
<delete>
<fileset basedir="${todaysSqlServerUNCBackupDirectory}">
<exclude name="**/*.zip" />
<include name="*.*" />
</fileset>
</delete>

<!-- Move the contents of today's backup directory to the local backup directory -->
<move todir="${localBackupDirectory}">
<fileset basedir="${todaysSqlServerUNCBackupDirectory}">
<include name="*.*" />
</fileset>
</move>

<!-- Delete the "todays" directories -->
<if test="${localSqlServer}">
<delete dir="${todaysLocalBackupDirectory}" />
</if>

<if test="${not localSqlServer}">
<delete dir="${todaysSqlServerUNCBackupDirectory}" />
</if>
</if>
</target>
</project>

Настройка резервного копирования и планирования

Просмотрите скрипт сборки и задайте следующие свойства, соответствующие вашим настройкам:

  • zipFileName — имя zip-файла, который будет создан для резервного копирования базы данных.
  • localBackupDirectory — локальный каталог, в котором будет храниться резервная копия
  • sqlServerLocalBackupDirectory — локальный путь (относительно экземпляра SQL Server), куда SQL Server будет записывать файл резервной копии. Это всегда должен быть локальный путь, поскольку сервер SQL не может записывать в сетевые пути.
  • sqlServerUNCBackupDirectory — UNC-путь к указанному выше локальному пути «sqlServerLocalBackupDirectory». Это необходимо только в случае резервного копирования SQL-сервера в сети. Для резервного копирования локального экземпляра SQL Server установите это «».
  • connectionString — Строка подключения .NET для подключения к базе данных. Этот параметр всегда имеет приоритет над параметром «connectionStringConfigFilePath». Чтобы использовать вместо этого файл конфигурации, установите для этого свойства значение «».
  • connectionStringConfigFilePath — в качестве альтернативы укажите путь, по которому сценарий сборки должен получить строку подключения. Обычно это файл app.config или connectionString.config.
  • connectionStringXPath — выражение XPath, которое будет использоваться для извлечения строки подключения из файла конфигурации.
  • getDatabaseNameFromConnecionStringRegEx — регулярное выражение, необходимое для получения имени базы данных из строки подключения.

Следующим шагом является создание расписания либо с помощью планировщика заданий, либо с помощью команды «at».

Чтобы использовать планировщик заданий:

  1. Создайте файл .bat со следующим: «driveLetter: \ path \ to \ nant.exe /f:pathToNAntBackupScript.build» и, конечно, замените его фактическим путем к nant.exe и сценарию сборки NAnt, который вы получили здесь.
  2. Перейдите в Панель управления / Запланированные задачи / Добавить запланированное задание
  3. Найдите файл .bat, который вы создали в # 1
  4. Настройте расписание запуска так часто, как вы хотите

Чтобы использовать команду «at»:

  1. Сделайте так же, как # 1 выше.
  2. Откройте командную строку и выполните команду «at»:
    »в 23:00 / каждые: M, T, W, Th, F pathToBatFileFromStep1.bat».

    Это позволит запланировать выполнение задачи каждый день недели в 23:00. Вы можете получить больше информации о команде «at» в разделе Как использовать AT-команду для планирования задач .

бонус

Вам не нужно жестко кодировать значения в сценарии сборки NAnt. Вы можете передать их из командной строки. Таким образом, вы можете повторно использовать один и тот же скрипт для другой базы данных. Вам просто нужно вызвать сценарий с параметром –D: propertyName = «value», например:

path \ to \ nant.exe /f:pathToNAntBackupScript.build –D: zipFileName = «myDatabase» –D: localBackupDirectory = «D: \ Temp «

Загрузки

http://tech-cats.net/blog/downloads/sql/procedure-dbo.backupDatabase.txt
http://tech-cats.net/blog/nantScripts/backupDatabase.build
http://tech-cats.net/ блог / nantScripts / backupDatabase.bat