如何在 Linux 上跨可用性组副本同步 SQL Server 代理作业?

Posted

技术标签:

【中文标题】如何在 Linux 上跨可用性组副本同步 SQL Server 代理作业?【英文标题】:How to synchronize SQL Server Agent jobs across availability group replicas on Linux? 【发布时间】:2020-08-26 05:48:06 【问题描述】:

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

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

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

【问题讨论】:

【参考方案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 'ScriptBorrowedFrom***'
        $secondaries | ForEach-Object 
            $secondaryInstanceConnection = Connect-DbaInstance $_ -ClientName 'ScriptBorrowedFrom***'
            Copy-DbaAgentJob -Source $primaryInstanceConnection -Destination $secondaryInstanceConnection -Force
        
    
    catch 
        $msg = $_.Exception.Message
        Write-Error "Error while syncing jobs for Availability Group '$($AvailabilityGroup): $msg'"
    

【讨论】:

我在 Windows 的生产环境中有一个变体。看到 copy-dbaagentjob 只与 sql server 管理对象 (SMO) 交互,我看不出这在 Linux 上不起作用的原因。 我今天会试一试,让你知道。 嘿,只是想让您知道这些命令可以工作,但大多数命令都需要 -SqlCredential 才能工作,所以我必须对脚本进行一些调整,以便在运行之前将凭据存储在一个变量中.完成此操作后,我将发布完成的脚本。 如果您使用 Windows 集成安全性,它们不需要 -sqlcredential。当然,如果您实际使用的是 sql 凭据,则需要它。【参考方案2】:

经过反复试验,我最终得到了这个在 Ubuntu Linux 18.04 上运行的脚本。非常感谢 Derik Hammer and his blog 提供脚本的基础,也感谢 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."

享受吧!

【讨论】:

回想一下,当然你并没有在你的 linux AG 设置中使用 windows 集成安全性! :) 可以从其他一些秘密保险库中获得 sql 凭据,但是 xml 中的安全字符串是不错的。感谢您提供完整的解决方案,非常有见地。

以上是关于如何在 Linux 上跨可用性组副本同步 SQL Server 代理作业?的主要内容,如果未能解决你的问题,请参考以下文章

sql server 2014 alwayson 可用性组 特性

SQL Server Always On 可用性组卡在“同步/恢复中”

SQL Server Alwayson概念总结

Windows版 SQL Server 2017 AlwaysOn AG 自动初始化测试报告

SQL Server Alwayson创建代理作业注意事项

在 SQL Server 2017 标准版的读取规模可用性组中无法访问副本数据库