Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Резервное копирование и восстановление БД MS SQL средствами PowerShell (http://forum.oszone.net/showthread.php?t=356079)

maximallist 24-01-2025 07:43 3035369

Резервное копирование и восстановление БД MS SQL средствами PowerShell
 
Вложений: 1
Приветствую вас, уважаемые форумчане! Прошу вашей помощи в решении проблемы работы скриптов PS.

Вводные данные:
Имеется "боевой" сервер MS SQL 2022, совмещенный с ролью сервера 1С8.
Все нижеописанные действия проводятся на одном сервере.
Для экономии дискового пространства (а оно ограничено), тестовая база для бэкапов одна, а кол-во баз на текущий момент 3, далее может быть и больше.
Скрипты выполняются по расписанию в планировщике Windows.

Для реализации бэкапов БД 1С8 написаны скрипты на PowerShell (PS), в которых реализована следующая логика работы (упрощённо):
  1. Из исходной "боевой" скульной БД выгружается полный сжатый бэкап (.bak) с помощью оснастки PS "Backup-SqlDatabase";
  2. Полученный бэкап восстанавливается в тестовую скульную БД с помощью оснастки PS "Restore-SqlDatabase";
  3. После восстановления, файл бэкапа (.bak) удаляется;
  4. Далее идет подключение к базе 1С8 в режиме конфигуратора, в которую на скуле был восстановлен бэкап, и производится выгрузка дампа БД 1С8 в формате .dt
Код скрипта PowerShell №1

Код:

# Load SQL Server cmdlets
Import-Module SqlServer

# Set variables SQL Server
$ServerInstance = "1C8SQLERP\SQL1C8ERP"
$DatabaseNameSource = "doc_prod"
$DatabaseNameDestination = "forbackup"
$BackupDir = "F:\BackUp"
$StartTime = (Get-Date)
$Timestamp = Get-Date -Format "yyyyMMdd"
$BackupFile = "${BackupDir}\${DatabaseNameSource}_${Timestamp}.bak"

Write-Host "Job Started in $StartTime" -ForegroundColor Yellow

# Create backup and archive directories if they don't exist
if (!(Test-Path $BackupDir)) {
    New-Item -ItemType Directory -Path $BackupDir
}

# Backup the SQL Server database
Backup-SqlDatabase -ServerInstance $ServerInstance -Database $DatabaseNameSource -BackupFile $BackupFile -CompressionOption On -CopyOnly
Write-Host "Database backup completed successfully." -ForegroundColor Green

# Restore the SQL Server database
Restore-SqlDatabase -ServerInstance $ServerInstance -Database $DatabaseNameDestination -BackupFile $BackupFile -ReplaceDatabase
Write-Host "Database restore completed successfully." -ForegroundColor Green

# Remove the original backup file
Remove-Item $BackupFile
Write-Host "Original backup file removed." -ForegroundColor Green

# Set variables 1C8
$PatchBackup = "\\data3\BackUP\1CBases\DO\" + $DatabaseNameSource + "_" + $Timestamp + "_" + ".dt"
$1cexe = '"C:\Program Files\1cv8\common\1cestart.exe"'
$BaseServer = "/S1C8SQLERP\" + $DatabaseNameDestination
$AdminLogin = '"/NBackUP"'
$Pswd = "/P123456"
$UC = "sudo"
$Argument = " ENTERPRISE $BaseServer $AdminLogin $Pswd /DisableStartupMessages"
$ArgumentBackup = "DESIGNER $BaseServer $AdminLogin $Pswd /UC $UC /DumpIB" + $PatchBackup

# Backup 1C8 Base
Start-Process $1cexe $ArgumentBackup
# Loop for checking the created dt file
While($true)
{
    if (Test-Path $PatchBackup)
    {
    $EndTime = (Get-Date)
    $TotalTime = $EndTime-$StartTime
    Write-Host "Database 1C8 backup completed successfully." -ForegroundColor Green
    Write-Host "Job Finished in $EndTime" -ForegroundColor Yellow
    Write-Host "Total time:" -ForegroundColor Red
    '{0:mm} min {0:ss} sec' -f $TotalTime
    exit
    }
    Start-Sleep -Seconds 10
}


Код скрипта PowerShell №2
Код:

# Load SQL Server cmdlets
Import-Module SqlServer

# Set variables SQL Server
$ServerInstance = "1C8SQLERP\SQL1C8ERP"
$DatabaseNameSource = "doc3_prod"
$DatabaseNameDestination = "forbackup"
$BackupDir = "F:\BackUp"
$StartTime = (Get-Date)
$Timestamp = Get-Date -Format "yyyyMMdd"
$BackupFile = "${BackupDir}\${DatabaseNameSource}_${Timestamp}.bak"

Write-Host "Job Started in $StartTime" -ForegroundColor Yellow

# Create backup and archive directories if they don't exist
if (!(Test-Path $BackupDir)) {
    New-Item -ItemType Directory -Path $BackupDir
}

# Backup the SQL Server database
Backup-SqlDatabase -ServerInstance $ServerInstance -Database $DatabaseNameSource -BackupFile $BackupFile -CompressionOption On -CopyOnly
Write-Host "Database backup completed successfully." -ForegroundColor Green

# Restore the SQL Server database
Restore-SqlDatabase -ServerInstance $ServerInstance -Database $DatabaseNameDestination -BackupFile $BackupFile -ReplaceDatabase
Write-Host "Database restore completed successfully." -ForegroundColor Green

# Remove the original backup file
Remove-Item $BackupFile
Write-Host "Original backup file removed." -ForegroundColor Green

# Set variables 1C8
$PatchBackup = "\\data3\BackUP\1CBases\DO\" + $DatabaseNameSource + "_" + $Timestamp + "_" + ".dt"
$1cexe = '"C:\Program Files\1cv8\common\1cestart.exe"'
$BaseServer = "/S1C8SQLERP\" + $DatabaseNameDestination
$AdminLogin = '"/NBackUP"'
$Pswd = "/P123456"
$UC = "sudo"
$Argument = " ENTERPRISE $BaseServer $AdminLogin $Pswd /DisableStartupMessages"
$ArgumentBackup = "DESIGNER $BaseServer $AdminLogin $Pswd /UC $UC /DumpIB" + $PatchBackup

# Backup 1C8 Base
Start-Process $1cexe $ArgumentBackup
# Loop for checking the created dt file
While($true)
{
    if (Test-Path $PatchBackup)
    {
    $EndTime = (Get-Date)
    $TotalTime = $EndTime-$StartTime
    Write-Host "Database 1C8 backup completed successfully." -ForegroundColor Green
    Write-Host "Job Finished in $EndTime" -ForegroundColor Yellow
    Write-Host "Total time:" -ForegroundColor Red
    '{0:mm} min {0:ss} sec' -f $TotalTime
    exit
    }
    Start-Sleep -Seconds 10
}


Код скрипта PowerShell №3
Код:

# Load SQL Server cmdlets
Import-Module SqlServer

# Set variables SQL Server
$ServerInstance = "1C8SQLERP\SQL1C8ERP"
$DatabaseNameSource = "erp_prod"
$DatabaseNameDestination = "forbackup"
$BackupDir = "F:\BackUp"
$StartTime = (Get-Date)
$Timestamp = Get-Date -Format "yyyyMMdd"
$BackupFile = "${BackupDir}\${DatabaseNameSource}_${Timestamp}.bak"

Write-Host "Job Started in $StartTime" -ForegroundColor Yellow

# Create backup and archive directories if they don't exist
if (!(Test-Path $BackupDir)) {
    New-Item -ItemType Directory -Path $BackupDir
}

# Backup the SQL Server database
Backup-SqlDatabase -ServerInstance $ServerInstance -Database $DatabaseNameSource -BackupFile $BackupFile -CompressionOption On -CopyOnly
Write-Host "Database backup completed successfully." -ForegroundColor Green

# Restore the SQL Server database
Restore-SqlDatabase -ServerInstance $ServerInstance -Database $DatabaseNameDestination -BackupFile $BackupFile -ReplaceDatabase
Write-Host "Database restore completed successfully." -ForegroundColor Green

# Remove the original backup file
Remove-Item $BackupFile
Write-Host "Original backup file removed." -ForegroundColor Green

# Set variables 1C8
$PatchBackup = "\\data3\BackUP\1CBases\ERP\" + $DatabaseNameSource + "__" + $Timestamp + ".dt"
$1cexe = '"C:\Program Files\1cv8\common\1cestart.exe"'
$BaseServer = "/S1C8SQLERP\" + $DatabaseNameDestination
$AdminLogin = '"/NBackUP"'
$Pswd = "/P123456"
$UC = "sudo"
$Argument = " ENTERPRISE $BaseServer $AdminLogin $Pswd /DisableStartupMessages"
$ArgumentBackup = "DESIGNER $BaseServer $AdminLogin $Pswd /UC $UC /DumpIB" + $PatchBackup

# Backup 1C8 Base
Start-Process $1cexe $ArgumentBackup
# Loop for checking the created dt file
While($true)
{
    if (Test-Path $PatchBackup)
    {
    $EndTime = (Get-Date)
    $TotalTime = $EndTime-$StartTime
    Write-Host "Database 1C8 backup completed successfully." -ForegroundColor Green
    Write-Host "Job Finished in $EndTime" -ForegroundColor Yellow
    Write-Host "Total time:" -ForegroundColor Red
    '{0:mm} min {0:ss} sec' -f $TotalTime
    exit
    }
    Start-Sleep -Seconds 10
}


Проблема в следующем:
Размер .dt при выполнении скрипта с очередностью 2 и далее (т.е. выполняемый после окончания работы первого), совпадает с размером первого выгруженного .dt,
подозреваю что ошибка возникает на этапе восстановления скульной БД (лишний или недостающий аргумент в оснастке PS "Restore-SqlDatabase").
Соответственно создается некорректный бэкап 2-ой БД с содержимым 1-ой БД.

Sham 24-01-2025 11:22 3035375

у вас везде $DatabaseNameDestination = "forbackup". Так и должно быть? $DatabaseNameSource при этом разный.

maximallist 24-01-2025 11:36 3035377

Цитата:

Цитата Sham
у вас везде $DatabaseNameDestination = "forbackup". Так и должно быть? $DatabaseNameSource при этом разный. »

Цитата:

Цитата maximallist
Для экономии дискового пространства (а оно ограничено), тестовая база для бэкапов одна, а кол-во баз на текущий момент 3, далее может быть и больше. »

Да, всё верно.

Sham 24-01-2025 16:01 3035389

Тестовая база блокируется на время работы 1cestart.exe? Насколько вижу, выбран неудачный способ ожидания завершения работы 1cestart.exe. Скрипт завершается по факту появления dt-файла, а не по факту окончания работы софта. Сам файл появился, скрипт завершается, но заполнение файла ещё может быть не окончено. Т.е. я бы убрал асинхронный start-process с While($true) {...}, заменив его обычным синхронным вызовом команды. У start-process есть флаг -wait, можно его добавить для синхронности.

maximallist 27-01-2025 06:53 3035469

Цитата:

Цитата maximallist
Скрытый текст
# Backup 1C8 Base
Start-Process $1cexe $ArgumentBackup
# Loop for checking the created dt file
While($true)
{
if (Test-Path $PatchBackup)
{
$EndTime = (Get-Date)
$TotalTime = $EndTime-$StartTime
Write-Host "Database 1C8 backup completed successfully." -ForegroundColor Green
Write-Host "Job Finished in $EndTime" -ForegroundColor Yellow
Write-Host "Total time:" -ForegroundColor Red
'{0:mm} min {0:ss} sec' -f $TotalTime
exit
}
Start-Sleep -Seconds 10
}
»

Благодарю за ответ, подскажите, правильно я понял, что нужно добавить в кусок кода флаг -wait:
Часть кода скрипта №1
Код:

Start-Process $1cexe $ArgumentBackup -wait
# Loop for checking the created dt file
While($true)
{
 if (Test-Path $PatchBackup)
 {
 $EndTime = (Get-Date)
 $TotalTime = $EndTime-$StartTime
 Write-Host "Database 1C8 backup completed successfully." -ForegroundColor Green
 Write-Host "Job Finished in $EndTime" -ForegroundColor Yellow
 Write-Host "Total time:" -ForegroundColor Red
 '{0:mm} min {0:ss} sec' -f $TotalTime
 exit
 }
 Start-Sleep -Seconds 10


Sham 27-01-2025 14:51 3035484

Цитата:

Цитата maximallist
While($true)
{ »

Если по каким-то причинам dt-файл не создастся, то этот цикл никогда не закончится и скрипт зависнет. While($true){} лучше убрать и оставить только if (Test-Path $PatchBackup) { .... } else { Write-Host 'Database 1C8 backup failed.' } (добавив else {...} для сообщения).

maximallist 28-01-2025 13:23 3035522

Sham, верно я понял, что код итогового скрипта будет выглядеть так:
Часть кода скрипта
Код:

Start-Process $1cexe $ArgumentBackup -wait
if (Test-Path $PatchBackup)
 {
 $EndTime = (Get-Date)
 $TotalTime = $EndTime-$StartTime
 Write-Host "Database 1C8 backup completed successfully! :-)" -ForegroundColor Green
 Write-Host "Job Finished in $EndTime" -ForegroundColor Yellow
 Write-Host "Total time:" -ForegroundColor Red
 '{0:mm} min {0:ss} sec' -f $TotalTime
 exit
 }
else
 {
 Write-Host "Database 1C8 backup failed! :-("
 }
Start-Sleep -Seconds 10



И нужен ли здесь командлет Start-Sleep?

Sham 29-01-2025 07:42 3035565

Цитата:

Цитата maximallist
нужен ли здесь командлет Start-Sleep? »

Это практический вопрос. Если скрипты отрабатывают корректно без паузы, то не нужна, а если возникают ошибки доступа, то лучше притормозить перед выполнением следующего скрипта.


Время: 02:28.

Время: 02:28.
© OSzone.net 2001-