У SQL Server есть встроенный механизм бэкапа: команда BACKUP DATABASE пишет файл .bak, который восстанавливается на любом сервере той же или более новой версии. Сама команда простая, но от опций зависит многое: сломает ли ваш бэкап цепочку, которую ведёт другой инструмент, заметит ли он повреждённые страницы и не вырастет ли файл до размера диска. Ниже — модели восстановления, типы бэкапов, нужные опции, проверка, расписание для Standard, Express и Linux, хранение копий вне сервера и восстановление.
Модель восстановления: какие бэкапы вообще нужны
У каждой базы SQL Server есть модель восстановления (recovery model). Она определяет, что происходит с журналом транзакций и какие бэкапы вам доступны.
- SIMPLE. Журнал усекается автоматически на контрольных точках, бэкапы журнала сделать нельзя. Восстановить базу можно только на момент последнего полного или разностного бэкапа. Подходит, если потеря данных между ночными бэкапами допустима.
- FULL. Журнал хранит все изменения, пока вы не сделаете бэкап журнала. Это даёт восстановление на любой момент времени, но без регулярных
BACKUP LOGфайл.ldfрастёт, пока не займёт весь диск. - BULK_LOGGED. Вариант FULL, в котором массовые операции журналируются минимально. Нужен редко, обычно на время больших загрузок.
SELECT name, recovery_model_desc FROM sys.databases;
ALTER DATABASE [Shop] SET RECOVERY SIMPLE;
Новые базы наследуют модель от системной базы model. Частая история: база создана в FULL, бэкапы журнала никто не настроил, через полгода .ldf весит больше самих данных. Решите заранее: либо SIMPLE и полные бэкапы, либо FULL и регулярные бэкапы журнала.
Типы бэкапов: полный, разностный, журнал
| Тип | Команда | Что содержит | Для восстановления нужен |
|---|---|---|---|
| Полный | BACKUP DATABASE | всю базу и нужную часть журнала | только этот файл |
| Разностный | BACKUP DATABASE … WITH DIFFERENTIAL | экстенты, изменённые с последнего полного бэкапа | последний полный + этот разностный |
| Журнал | BACKUP LOG | записи журнала с прошлого бэкапа журнала | полный, (разностный) и все бэкапы журнала по порядку |
BACKUP DATABASE [Shop] TO DISK = N'D:\Backup\Shop_full.bak' WITH CHECKSUM, INIT;
BACKUP DATABASE [Shop] TO DISK = N'D:\Backup\Shop_diff.bak' WITH DIFFERENTIAL, CHECKSUM, INIT;
BACKUP LOG [Shop] TO DISK = N'D:\Backup\Shop_log_0315.trn' WITH CHECKSUM, INIT;
Типичная схема для базы в FULL: полный бэкап раз в неделю или каждую ночь, разностный — ежедневно, журнал — каждые 15–60 минут. Для SIMPLE достаточно полного бэкапа по расписанию и, если база большая, разностных между ними.
COPY_ONLY: если бэкапы уже делает другой инструмент
Разностный бэкап считается от последнего полного — его называют differential base. Если параллельно с основной системой бэкапа (агентом, планом обслуживания, решением хостера) вы запустите обычный полный бэкап, он станет новой базой для разностных. Следующий разностный бэкап основной системы будет ссылаться на ваш файл, о котором она ничего не знает. Если ваш файл потом удалят, восстановить базу из её разностных копий будет нельзя.
Опция COPY_ONLY делает полный бэкап, который не влияет на последовательность:
BACKUP DATABASE [Shop] TO DISK = N'D:\Backup\Shop_adhoc.bak'
WITH COPY_ONLY, CHECKSUM, INIT;
Для журнала BACKUP LOG … WITH COPY_ONLY не усекает журнал, поэтому не разрывает цепочку бэкапов журнала. Правило простое: любой разовый или «дополнительный» бэкап — с COPY_ONLY. Перед миграцией, для передачи базы разработчику, для отдельной копии в облаке.
Опции, которые стоит указывать всегда
BACKUP DATABASE [Shop]
TO DISK = N'D:\Backup\Shop-20261007T030000Z.bak'
WITH CHECKSUM, COMPRESSION, INIT, STATS = 10;
CHECKSUM. SQL Server при чтении проверяет контрольные суммы страниц (если у базы включён PAGE_VERIFY CHECKSUM, по умолчанию это так) и записывает контрольную сумму всего бэкапа. Если найдена повреждённая страница, бэкап завершится ошибкой. Без этой опции вы можете месяцами аккуратно сохранять уже испорченную базу.
COMPRESSION. Сжатый бэкап обычно заметно меньше и пишется быстрее, потому что узкое место чаще диск, а не процессор. Насколько меньше, зависит от данных: текст и числа сжимаются хорошо, уже сжатые файлы в varbinary — плохо. Создавать сжатые бэкапы умеют не все редакции: в Express команда с COMPRESSION завершится ошибкой 1844. Восстановить сжатый бэкап можно и в Express. Если нужно сжатие по умолчанию для всех бэкапов сервера:
EXEC sp_configure 'backup compression default', 1;
RECONFIGURE;
INIT и FORMAT. По умолчанию действует NOINIT: если файл уже существует, новый бэкап дописывается в него. Файл растёт, а при восстановлении нужно указывать FILE = N, иначе возьмётся первый, самый старый набор. INIT перезаписывает наборы в файле, FORMAT дополнительно создаёт новый заголовок носителя. Надёжная практика — уникальное имя файла с меткой времени плюс INIT.
Куда пишется файл. Путь в TO DISK интерпретирует сервер, а не клиент. Файл создаёт служебная учётная запись SQL Server (например, NT Service\MSSQLSERVER), и у неё должны быть права на запись в каталог. Сетевой путь \\nas\backup\ работает, если доступ к шаре выдан этой учётной записи или учётной записи компьютера. Для бэкапа достаточно роли db_backupoperator в базе — sysadmin не обязателен.
RESTORE VERIFYONLY и чего он не проверяет
RESTORE VERIFYONLY FROM DISK = N'D:\Backup\Shop-20261007T030000Z.bak' WITH CHECKSUM;
RESTORE HEADERONLY FROM DISK = N'D:\Backup\Shop-20261007T030000Z.bak';
RESTORE FILELISTONLY FROM DISK = N'D:\Backup\Shop-20261007T030000Z.bak';
VERIFYONLY проверяет, что набор полный, файл читается целиком и, если бэкап делался WITH CHECKSUM, контрольные суммы сходятся. Это быстрая проверка, что файл не обрезан и не испорчен при записи или копировании.
Чего она не делает: не восстанавливает базу и не проверяет логическую целостность данных. Если повреждение было в базе до бэкапа и не затрагивало контрольные суммы страниц, VERIFYONLY скажет «всё хорошо». Настоящая проверка — восстановление в отдельную базу и DBCC CHECKDB:
RESTORE DATABASE [Shop_verify]
FROM DISK = N'D:\Backup\Shop-20261007T030000Z.bak'
WITH MOVE N'Shop' TO N'E:\Verify\Shop_verify.mdf',
MOVE N'Shop_log' TO N'E:\Verify\Shop_verify_log.ldf',
RECOVERY, STATS = 10;
DBCC CHECKDB ([Shop_verify]) WITH NO_INFOMSGS, ALL_ERRORMSGS;
DROP DATABASE [Shop_verify];
Логические имена файлов (Shop, Shop_log) берите из RESTORE FILELISTONLY. Делайте такую проверку хотя бы раз в неделю, лучше на отдельном сервере: CHECKDB заметно нагружает диск. Общий подход к проверкам описан в статье как проверить, что бэкап рабочий.
Расписание: SQL Server Agent, планировщик Windows, cron
Standard и Enterprise: SQL Server Agent
В платных редакциях бэкап обычно запускает SQL Server Agent: задание (job) с шагом T-SQL или план обслуживания (Maintenance Plan) из SSMS. Агент ведёт историю запусков и умеет отправлять уведомления через Database Mail.
Express: планировщик заданий и sqlcmd
В Express нет SQL Server Agent, поэтому бэкап запускает планировщик заданий Windows через sqlcmd. Скрипт C:\Scripts\backup-shop.sql с уникальным именем файла:
DECLARE @file nvarchar(400) =
N'D:\Backup\Shop-' + FORMAT(SYSUTCDATETIME(), 'yyyyMMddTHHmmss') + N'Z.bak';
BACKUP DATABASE [Shop] TO DISK = @file WITH CHECKSUM, INIT; -- без COMPRESSION: Express его не поддерживает
RESTORE VERIFYONLY FROM DISK = @file WITH CHECKSUM;
Командный файл C:\Scripts\backup-shop.cmd:
@echo off
sqlcmd -S .\SQLEXPRESS -E -b -i C:\Scripts\backup-shop.sql -o C:\Scripts\backup-shop.log
if errorlevel 1 exit /b 1
forfiles /p D:\Backup /m Shop-*.bak /d -14 /c "cmd /c del @path"
Флаг -b важен: без него sqlcmd вернёт код 0 даже при ошибке в T-SQL, и планировщик покажет успешный запуск. -E — вход через Windows-аутентификацию. Регистрация задачи:
schtasks /Create /TN "SQL backup Shop" /TR "C:\Scripts\backup-shop.cmd" /SC DAILY /ST 03:00 /RU "SRV01\sqlbackup"
schtasks спросит пароль учётной записи. Этой учётной записи нужен логин в SQL Server с ролью db_backupoperator в базе Shop. Не запускайте задачу от SYSTEM в расчёте на права администратора: в современных версиях SQL Server у NT AUTHORITY\SYSTEM нет роли sysadmin по умолчанию.
Linux: cron и mssql-tools18
На Linux sqlcmd входит в пакет mssql-tools18 и лежит в /opt/mssql-tools18/bin. Пароль не пишите в командную строку: sqlcmd читает его из переменной SQLCMDPASSWORD.
# /etc/mssql-backup.env (chmod 600)
export SQLCMDPASSWORD='очень-длинный-пароль'
# crontab -e
0 3 * * * . /etc/mssql-backup.env && /opt/mssql-tools18/bin/sqlcmd -S localhost -U backup -C -b -i /opt/backup/backup-shop.sql >> /var/log/mssql-backup.log 2>&1
-C доверяет сертификату сервера: драйвер ODBC 18 по умолчанию включает шифрование и без него откажется подключаться к серверу с самоподписанным сертификатом. Путь в скрипте — серверный, например /var/opt/mssql/backup, и каталог должен принадлежать пользователю mssql. SQL Server Agent на Linux тоже есть, его включают командой sudo /opt/mssql/bin/mssql-conf set sqlagent.enabled true.
Ola Hallengren: готовое решение вместо своих скриптов
Многие администраторы не пишут скрипты бэкапа сами, а ставят бесплатный SQL Server Maintenance Solution Олы Халленгрена. Это набор хранимых процедур для бэкапа, проверки целостности и обслуживания индексов. Пример:
EXECUTE dbo.DatabaseBackup
@Databases = 'USER_DATABASES',
@Directory = N'D:\Backup',
@BackupType = 'FULL',
@Verify = 'Y',
@CheckSum = 'Y',
@CleanupTime = 168; -- удалять бэкапы старше 168 часов
Процедура сама строит имена файлов, раскладывает их по каталогам и удаляет старые копии. В Express её вызывают из sqlcmd по расписанию планировщика Windows, как в примере выше.
Копия вне сервера: правило 3-2-1
Файл .bak на том же диске, что и база, защищает от DELETE без WHERE, но не от отказа диска, шифровальщика или потери сервера. Правило 3-2-1: три копии данных, на двух разных носителях, одна — вне площадки.
На Windows копию на NAS удобно делать через robocopy D:\Backup \\nas\sql-backup *.bak /XO, в S3-совместимое хранилище — через aws s3 cp или rclone. SQL Server 2022 умеет писать бэкап напрямую в S3-совместимое хранилище через BACKUP … TO URL, но для этого нужны учётные данные CREATE CREDENTIAL и поддержка со стороны провайдера. Ключи, которыми сервер пишет в хранилище, по возможности ограничьте правами только на запись: тогда злоумышленник с доступом к серверу не удалит архив.
Восстановление: MOVE, REPLACE и цепочка
Сначала смотрим содержимое файла, затем восстанавливаем в новую базу:
RESTORE FILELISTONLY FROM DISK = N'D:\Backup\Shop-20261007T030000Z.bak';
RESTORE DATABASE [Shop_restore]
FROM DISK = N'D:\Backup\Shop-20261007T030000Z.bak'
WITH MOVE N'Shop' TO N'D:\Data\Shop_restore.mdf',
MOVE N'Shop_log' TO N'D:\Data\Shop_restore_log.ldf',
RECOVERY, STATS = 10;
MOVE нужен, когда пути из бэкапа не совпадают с путями на сервере или файлы с такими именами уже заняты рабочей базой. Если действительно нужно заменить рабочую базу:
USE master;
ALTER DATABASE [Shop] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
RESTORE DATABASE [Shop] FROM DISK = N'D:\Backup\Shop-20261007T030000Z.bak'
WITH REPLACE, RECOVERY, STATS = 10;
ALTER DATABASE [Shop] SET MULTI_USER;
REPLACE отключает проверки безопасности, в том числе ошибку 3159 о том, что хвост журнала не сохранён. В модели FULL вместо этого лучше сначала сохранить хвост журнала: BACKUP LOG [Shop] TO DISK = … WITH NORECOVERY. База перейдёт в состояние восстановления, изменения после последнего бэкапа журнала останутся в файле, и RESTORE пройдёт без REPLACE.
Цепочка для FULL: полный бэкап WITH NORECOVERY, затем разностный WITH NORECOVERY, затем бэкапы журнала по порядку, последний — WITH RECOVERY. Чтобы откатиться к моменту до ошибки, добавьте к последнему журналу STOPAT = '2026-10-07T14:29:00'.
Ещё два момента. Бэкап восстанавливается только на ту же или более новую версию SQL Server, на старую — никогда. При переносе базы на другой сервер пользователи базы могут остаться без логинов. Привяжите их заново: ALTER USER [app] WITH LOGIN = [app];. Подробнее о безопасном порядке действий — в статье как восстановить базу из бэкапа.
Как это сделать в dbsend
dbsend хранит бэкапы как версии и сообщает, если очередной бэкап не пришёл. Для SQL Server в CLI версии 0.4.0 и новее есть команда dbsend mssql. Её запускают на машине с SQL Server (или там, где каталог бэкапов доступен и CLI, и службе SQL Server):
npm install --global @dbsend/sdk
dbsend login --key sqv_pk_…
dbsend mssql --sql-database Shop -d <id> --server ".\SQLEXPRESS" --backup-dir D:\Backup
Что делает команда: выполняет BACKUP DATABASE … WITH COPY_ONLY, CHECKSUM, INIT, COMPRESSION в файл с меткой времени. Если сервер не поддерживает сжатие (Express), она повторяет бэкап без COMPRESSION и пишет об этом. Затем проверяет файл через RESTORE VERIFYONLY … WITH CHECKSUM, загружает его в dbsend и удаляет локальную копию (оставить её можно флагом --keep-local). Благодаря COPY_ONLY команда не мешает агенту, плану обслуживания или скриптам Олы Халленгрена, если они уже работают. Если проверка не прошла, CLI завершится с кодом 6 и ничего не загрузит.
Без --user используется Windows-аутентификация. Для SQL-логина пароль передаётся только через переменную окружения, в командной строке его нет:
$env:SQLCMDPASSWORD = 'очень-длинный-пароль'
dbsend mssql --sql-database Shop --server "db01,1433" --user backup -d <id> --trust-server-certificate
--backup-dir лучше указывать явно: по умолчанию CLI использует временный каталог текущего пользователя, а служба SQL Server может не иметь прав писать туда. Если у вас уже есть свои .bak, загрузите их как есть: dbsend backup D:\Backup\Shop.bak --engine mssql_backup -d <id>. Расписание остаётся вашим: задача планировщика Windows или cron вызывает dbsend mssql, а dbsend следит, чтобы версии приходили вовремя. На платных тарифах, если бэкап пропущен, приходит уведомление в Telegram, на почту или в webhook.
Восстановление: dbsend restore <snapshotId> D:\Restore\Shop.bak --yes скачивает версию и сверяет SHA-256 с тем, что было при загрузке. Дальше — обычный RESTORE DATABASE … WITH MOVE из раздела выше.
Чего dbsend не делает для .bak: не показывает таблицы и diff между версиями, как для SQLite или SQL-дампов. Формат бинарный, поэтому сервис хранит файл, размер и контрольную сумму. Также есть лимит на размер одного файла, он считается по исходному размеру: 100 МБ на бесплатном тарифе, 500 МБ на «Старте», 2 ГБ на «Про» и «Команде», 50 ГБ на «Бизнесе». Тариф «Бизнес» рассчитан на крупные базы: файлы до 50 ГБ и 1 ТБ хранилища. Для .bak больше 50 ГБ остаётся BACKUP в собственное хранилище, о котором шла речь выше, или индивидуальные условия — напишите на hello@dbsend.ru. Подробности — на странице бэкапа MS SQL Server, в документации CLI и на странице тарифов. Если на SQL Server у вас работает 1С, посмотрите статью как сделать бэкап базы 1С.
Частые вопросы
Нужно ли останавливать базу для бэкапа SQL Server?
Нет. BACKUP DATABASE работает на живой базе и даёт согласованную копию: в бэкап попадает часть журнала, достаточная, чтобы при восстановлении довести базу до состояния на момент окончания бэкапа. Нагрузку на диск бэкап создаёт, поэтому крупные базы бэкапят ночью.
Почему растёт файл журнала .ldf?
Почти всегда база в модели FULL, а бэкапов журнала нет. Журнал не усекается, пока не сделан BACKUP LOG. Либо настройте бэкапы журнала по расписанию, либо, если восстановление на произвольный момент не нужно, переведите базу в SIMPLE.
Чем .bak отличается от .bacpac?
.bak — физический бэкап средствами SQL Server: быстрый, согласованный, с журналом. .bacpac — экспорт схемы и данных, которым пользуются, например, для переноса в Azure SQL. Экспорт работающей базы не гарантирует транзакционной согласованности и на больших базах идёт долго, поэтому как основной бэкап он не подходит.
Можно ли восстановить бэкап на более старую версию SQL Server?
Нет. Бэкап, сделанный на SQL Server 2022, не восстановится на 2019. Для переноса «вниз» остаются экспорт данных, скрипты схемы и bcp.
Как часто делать бэкап MS SQL Server?
Столько, сколько данных вы готовы потерять. Для небольшой базы в SIMPLE хватит ночного полного бэкапа. Если потеря дня работы недопустима, переходите на FULL и бэкапы журнала каждые 15–30 минут. Общие принципы расписаний — в статье о настройке автоматических бэкапов.



