2

我有两个在 Linux 上运行的 SQL Server 2019 实例。这两个实例都包含一个使用 AlwaysOn 可用性组同步的数据库。数据库中的数据是同步的,但问题是 SQL 代理作业不是数据库本身的一部分。

因此,当我在主副本上创建 SQL Server 代理作业时,此配置不会复制到辅助副本。所以,在创造了每个工作之后,我总是必须去中学并在那里创造工作。而且我必须一直跟踪我所做的所有更改。

使用可用性组时,是否有一种内置方法可以在 Linux 上自动执行 SQL Server 作业的这种跨副本同步?跨 AG 副本的作业同步似乎应该已经被 SQL Server/SQL Server 代理工具原生支持,但我没有从 Microsoft 找到任何东西,只有一个名为DBA Tools的第三方工具,我可以使用它来编写自己的自动化脚本在 PowerShell 中。

4

2 回答 2

1

dbatools 可以同步它们,但我还没有在 Linux 上运行的 AG 上尝试过。让我知道它是否有效!第一个参数是您的 AG 的名称,第二个参数是您的集群的虚拟网络名称。

param($AvailabilityGroup, $SqlInstance)
    try {
        $replicas = Get-DbaAgReplica -AvailabilityGroup $AvailabilityGroup -SqlInstance $SqlInstance
        $primary = $replicas | Where-Object Role -EQ Primary | Select-Object -ExpandProperty Name
        $secondaries = $replicas | Where-Object Role -EQ Secondary | Select-Object -ExpandProperty Name
        $primaryInstanceConnection = Connect-DbaInstance $primary -ClientName 'ScriptBorrowedFromStackOverFlow'
        $secondaries | ForEach-Object {
            $secondaryInstanceConnection = Connect-DbaInstance $_ -ClientName 'ScriptBorrowedFromStackOverFlow'
            Copy-DbaAgentJob -Source $primaryInstanceConnection -Destination $secondaryInstanceConnection -Force
        }
    }
    catch {
        $msg = $_.Exception.Message
        Write-Error "Error while syncing jobs for Availability Group '$($AvailabilityGroup): $msg'"
    }
于 2020-08-26T06:02:17.490 回答
1

经过反复试验,我最终得到了这个适用于 Ubuntu Linux 18.04 的脚本。非常感谢Derik Hammer 和他的博客为脚本提供了基础,也感谢 David Söderlund 的回复。

要使脚本正常工作,您需要安装适用于 Linux 的 PowerShell 以及 DBATools 和 SqlCmd2 PowerShell 模块。您还必须将 sql 凭据存储在某个文件中。我选择/var/opt/mssql/secrets/creds.xml了我的并将访问权限更改为仅 root。脚本可以将登录、DBmail 设置、SQL 代理类别、作业、操作员和计划从主副本同步到所有辅助副本(取消注释您需要的内容,但要小心,顺序很重要,有些东西不能在一个连接中同步,即操作员和作业) ,跳过配置副本(如果有)。

您可以以 root 身份设置计划执行,并使用 CRON 将输出记录到文件中。要进行此设置,请运行:

sudo crontab -e

并将这一行添加到文件中:

*/5 * * * * pwsh /<PATH>/sync-sql-objects.ps1 >> /<PATH>/sync-sql-objects.log

脚本:

<# 
.DESCRIPTION
This script will detect your Availability Group replicas and copy all of its instance level objects from primary replica to secondary replicas within the Availability Group. It will skip any configuration replicas.
 
.EXAMPLE
sudo pwsh sync-sql-objects.ps1
 
.NOTES
One limitation of this script is that it assumes you only have one availability group. This script should run on your configuration replica server.
 
.LINK
https://www.sqlhammer.com/synchronizing-server-objects-for-availability-groups/
 
DEBUG
To see logs on Ubuntu Linux, install Postfix Mail Transfer Agent and then go to see mails in /var/mail/<username>
#>  

Write-Output ("Sync started: " + (Get-Date -Format G))
 
#Error handling
$ErrorActionPreference = "stop";
 
Trap 
{
    $err = $_.Exception
    while ( $err.InnerException )
    {
 
        $err = $err.InnerException
        Write-Output $err.Message
 
    };
}
 
# Prerequisites
try
{
    Write-Output "Valiating prerequisites."

    # You need to have these modules installed in advance, otherwise the import will fail

    if ((Get-Module -Name dbatools) -eq $null)
    {
        Import-Module dbatools | Out-Null
    }

    if ((Get-Module -Name Invoke-SqlCmd2) -eq $null)
    {
        Import-Module Invoke-SqlCmd2 | Out-Null
    }

    Write-Output "Prerequisites loaded."
 
}
catch
{
    Write-Error $_.Exception.Message -EA Continue
    Write-Error "One or more of the prerequisites did not load. Review previous errors for more details." -EA Continue
    return
}

# Detect Availability Group replicas
Write-Output "Begin query for Availability Group replicas"
 
$ConfigurationMode = "CONFIGURATION_ONLY"
$Hostname = hostname 
$Credentials = Import-CliXml -Path /var/opt/mssql/secrets/creds.xml

$ReplicasQuery = @"
SELECT replica_server_name,
availability_mode_desc,
primary_replica
FROM sys.availability_replicas AR
INNER JOIN sys.dm_hadr_availability_group_states HAGS
INNER JOIN sys.availability_groups AG ON AG.group_id = HAGS.group_id
    ON HAGS.group_id = AR.group_id;
"@

$Replicas = Invoke-Sqlcmd2 -ServerInstance $Hostname -Query $ReplicasQuery -ConnectionTimeout 30 -Credential $Credentials
 
if(([DBNull]::Value).Equals($Replicas[0].primary_replica))
{
    Write-Error "Availability Group query returned no results. Confirm that you connected to a SQL Server instance running an Availability Group. No work was accomplished."
    return
}
 
Write-Output "Completed query of Availability Group replicas"
 
foreach($replica in $Replicas)
{
    # Skip if destination replica is primary replica itself
    if($replica.primary_replica.CompareTo($replica.replica_server_name) -eq 0)
    {
        continue
    }
 
    # Skip configuration replicas
    if($replica.availability_mode_desc.CompareTo($ConfigurationMode) -eq 0)
    {
        continue
    }

    #Connect
    $PrimaryReplica = Connect-DbaInstance $replica.primary_replica -ClientName 'ConfigurationReplica' -SqlCredential $Credentials
    $SecondaryReplica = Connect-DbaInstance $replica.replica_server_name -ClientName 'ConfigurationReplica' -SqlCredential $Credentials

    Write-Output "Copying instance objects from $sourceReplica to $replica"

    # Copy objects
    # Write-Output "Copying Logins."
    # Copy-DbaLogin -Source $PrimaryReplica -Destination $SecondaryReplica

    # Write-Output "Copying DBMail."
    # Copy-DbaDbMail -Source $PrimaryReplica -Destination $SecondaryReplica -Force

    # Write-Output "Copying Agent Categories."
    # Copy-DbaAgentJobCategory -Source $PrimaryReplica -Destination $SecondaryReplica -Force

    # Write-Output "Copying Agent Schedules."
    # Copy-DbaAgentSchedule -Source $PrimaryReplica -Destination $SecondaryReplica -Force

    # Write-Output "Copying Operators."
    # Copy-DbaAgentOperator -Source $PrimaryReplica -Destination $SecondaryReplica -Force

    Write-Output "Copying Jobs."
    Copy-DbaAgentJob -Source $PrimaryReplica -Destination $SecondaryReplica -Force
       
    Write-Output "Copy complete from $PrimaryReplica to $SecondaryReplica"
}

Write-Output "SQL Instance object sync complete."

享受!

于 2020-09-07T21:38:25.817 回答