SQL Server sp_replmonitorsubscriptionpendingcmds

运行sp_replmonitorsubscriptionpendingcmds,将结果以邮件的形式发送告警

sql 复制代码
$Credential = Get-SQLVaultCredential 

$mail_to = "xxx@xxx.com"
$mail_bcc = "xxx@xxx.com"
$mail_from = "xxx@xxx.com"
$mail_subject = "Repl: sp_replmonitorsubscriptionpendingcmds"
$mail_smtpserver = "xxx.xxx.xxx.xxx"

$sql_instances = @"
select CONCAT(ip, ',', port) from dbadmin_ms_instance where enable=1
"@

$sql_get_distdb=@"
SELECT name from sys.databases where is_distributor=1 and DATABASEPROPERTYEX(name, 'Updateability')='READ_WRITE'
"@



$outfile = "$($MyInvocation.MyCommand.Path).log"
if (Test-Path $outfile) {
	Remove-Item $outfile
}


$outfile_error = "$($MyInvocation.MyCommand.Path).err"
if (Test-Path $outfile_error) {
	Remove-Item $outfile_error
} 

$target_db_list=@()
$db_instance_list = Invoke-Sqlcmd -ServerInstance "xxx.xxx.xxx.xxx,1433" -Database DBMonitor -Credential $Credential -TrustServerCertificate -Query $sql_instances
$target_db_list=$db_instance_list | ForEach-Object -Parallel {
	try {
		$SQL_instance = $_[0]
		#Write-Host $SQL_instance

		$dbs = Invoke-Sqlcmd -ServerInstance $SQL_instance -Database master -Credential $using:Credential -TrustServerCertificate -Query $using:sql_get_distdb  -Verbose -IncludeSqlUserErrors -ErrorAction Stop -OutputSqlErrors $true

		$dbs | ForEach-Object {
		        [PSCustomObject]@{
		            Instance = $SQL_instance
		            Database = $_.name
		        }
		   
		}
	}
	catch {
		"$($SQL_instance):$($_.Exception.Message)" | Out-File -FilePath $using:outfile_error -Append
		Continue

	}
}


$all_pending_cmds_results = @()
foreach ($row in $target_db_list) {
    $instance = $row.Instance
    $db = $row.Database
    
    #Write-Host "正在连接 [$instance] 上的分发库 [$db] 获取订阅列表..." -ForegroundColor Cyan

    try {
        # 1. 纯粹获取当前分发库下的所有订阅参数(不包含任何 exec 嵌套)
        $sql_get_subscriptions = @"
        SELECT DISTINCT 
            srv_p.srvname AS publisher,
            a.publisher_db,
            a.publication,
            srv_s.srvname AS subscriber,
            s.subscriber_db,
            s.subscription_type
        FROM MSdistribution_agents a
        JOIN MSSubscriptions s ON a.id = s.agent_id
        JOIN MSreplservers srv_p ON a.publisher_id = srv_p.srvid
        JOIN MSreplservers srv_s ON s.subscriber_id = srv_s.srvid
        WHERE s.subscriber_db <> 'virtual';
"@

        $subscriptions = Invoke-Sqlcmd -ServerInstance $instance -Database $db -Credential $Credential -TrustServerCertificate -Query $sql_get_subscriptions -ErrorAction Stop

        if ($subscriptions) {
            # 2. 如果存在订阅,在 PowerShell 中一条一条动态拼接并执行
            foreach ($sub in $subscriptions) {
                
                # 动态拼接当前的 SQL 命令
                $current_cmd = "EXEC sp_replmonitorsubscriptionpendingcmds @publisher='{0}', @publisher_db='{1}', @publication='{2}', @subscriber='{3}', @subscriber_db='{4}', @subscription_type={5};" -f `
                    $sub.publisher, $sub.publisher_db, $sub.publication, $sub.subscriber, $sub.subscriber_db, $sub.subscription_type

                # 【控制台显示】实时输出当前正在执行的命令,方便观察进度
                #Write-Host " -> 执行命令: $current_cmd" -ForegroundColor Gray

                try {
                    # 执行该条订阅的积压检查
                    $res = Invoke-Sqlcmd -ServerInstance $instance -Database $db -Credential $Credential -TrustServerCertificate -Query $current_cmd -ErrorAction Stop

                    if ($res) {
                        # 3. 如果有返回结果,将当前实例、数据库和【完整的 SQL 命令】绑定给它
                        $res | ForEach-Object {
                            $_ | Add-Member -NotePropertyMembers @{
                                DistributorInstance = $instance
                                DistributionDB      = $db
                                ExecutedCommand     = $current_cmd  # 绑定完整命令文本
                            } -ErrorAction SilentlyContinue
                            
                            $all_pending_cmds_results += $_
                        }
                    }
                }
                catch {
                    Write-Error "    执行单个订阅命令失败: $($_.Exception.Message)"
                }
            }
        }
    }
    catch {
        Write-Error "连接 $instance ($db) 失败: $($_.Exception.Message)"
    }
}

#Write-Host "`n--- 所有发布订阅的未同步命令积压结果 ---" -ForegroundColor Green

# ?? 提示:由于 ExecutedCommand 命令很长,使用 -Wrap 可以防止尾部被三个点 (...) 截断
$filtered_results =$all_pending_cmds_results | Where-Object { $_.pendingcmdcount -gt 10  } | Format-Table DistributorInstance, DistributionDB, pendingcmdcount, estimated_time, ExecutedCommand -AutoSize -Wrap

if ($filtered_results) {
	$body = $filtered_results| Format-Table DistributorInstance, DistributionDB, pendingcmdcount, estimated_time, ExecutedCommand -AutoSize | Out-String
	if ($body) {
		Send-MailMessage -To $mail_to -Bcc $mail_bcc -From $mail_from  -Subject $mail_subject -Body $body  -SmtpServer $mail_smtpserver -Encoding utf8
	}
}

if (Test-Path $outfile_error) {
	$body_error = get-content -Path $outfile_error -Raw
	if ($body_error) {
		Send-MailMessage -To $mail_to -From $mail_from  -Subject $mail_subject -Body $body_error  -SmtpServer $mail_smtpserver -Encoding utf8
	}
}
相关推荐
数据库小学妹15 小时前
SQL Server数据迁移怎么做?一次事故复盘:备份还原、bcp、CDC、KDTS全拆解
sqlserver·备份还原·数据库迁移·信创迁移·sqlserver数据迁移
xuefuhe19 小时前
SQL Server exec vs sp_executesql
sqlserver
zengjuan10052 天前
[特殊字符]️ 松鼠备份 | 数据库备份方案即将重磅上线!三大模式组合拳,精准守护SQL Server每一笔数据
数据库·sqlserver·数据库备份·全量备份·增量备份·差异备份·日志和事务备份
识途老码2 天前
docker运行sqlserver
docker·容器·sqlserver
熊文豪11 天前
SQLServer数据迁移之后,那张报表还能不能秒出
数据库·sqlserver·电科金仓
Alex Gram12 天前
数据库同步工具PanguSync图文教程
java·mysql·postgresql·sqlserver·c#·数据库同步软件·数据库同步工具
哥本哈士奇13 天前
dbt+SQLServer构建数据仓库(10):macro 以及 data vault的应用实例
大数据·数据仓库·sqlserver
哥本哈士奇(aspnetx)15 天前
dbt+SQLServer构建数据仓库(10):macro 以及 data vault的应用实例
sqlserver
哥本哈士奇16 天前
dbt+SQLServer构建数据仓库(8):Vibe Coding用dbt构建data vault数仓
数据仓库·sqlserver
哥本哈士奇(aspnetx)17 天前
dbt+SQLServer构建数据仓库(9):用Vibe Coding创建一个DBT UI
sqlserver