识别辅助副本上缺少的代理作业

时间:2018-12-06 11:32:10

标签: sql sql-server content-management-system

我正在尝试建立一个过程,该过程将检查可用性组中所有服务器上的代理作业,并报告辅助副本中可能缺少的所有作业。

我对所有AG中的服务器进行了CMS设置,并且可以跨副本对代理作业运行查询,但是我只想返回某些服务器上的作业,但不是所有服务器上的作业。

我编写了一个查询来使用COUNT()获取此信息,但是由于查询结果是按服务器分组的,因此无法正常工作。我还尝试将结果放在临时表中以查看是否有帮助,但这似乎并没有太大的区别。

AG中有四台服务器,以下查询应返回不在所有四台服务器上的所有作业的名称,但是由于它似乎也返回了服务器名称,因此无法将它们识别为同一作业

CREATE TABLE #jobs (
    JobName NVARCHAR(128))

INSERT INTO #jobs
SELECT name JobName
FROM sysjobs 

SELECT * 
FROM #jobs
GROUP BY JobName
HAVING COUNT(*) < 4
ORDER BY JobName

DROP TABLE #jobs

目前的查询会抛出如下结果集:

+------------+------------------------------------------+
| ServerName |                 JobName                  |
+------------+------------------------------------------+
| ServerA    | DBA DatabaseBackup - AG_DATABASES - FULL |
| ServerA    | OutputFile Cleanup                       |
| ServerB    | DBA DatabaseBackup - AG_DATABASES - FULL |
| ServerB    | IndexOptimize - USER_DATABASES           |
| ServerC    | DBA DatabaseBackup - AG_DATABASES - FULL |
| ServerB    | IndexOptimize - USER_DATABASES           |
| ServerD    | DBA DatabaseBackup - AG_DATABASES - FULL |
| ServerD    | Output File Cleanup                      |
+------------+------------------------------------------+

所有四个服务器都存在作业DBA DatabaseBackup-AG_DATABASES-FULL,因此我不希望返回该服务器,但是由于来自CMS连接的隐式servername列无法将它们识别为相同的值。

5 个答案:

答案 0 :(得分:3)

正如GMB所述,您需要提取“名称”字段的一部分。

我建议将字符串分成ServerName和JobName。

假设名称以-分隔,例如在您的示例中,您的代码应如下所示。

CREATE TABLE #jobs (
ServerName NVARCHAR(128)    
,JobName NVARCHAR(128))

INSERT INTO #jobs
SELECT 
LEFT(name,CHARINDEX('-',name)-1) AS ServerName --Takes the Part left of the first -
, RIGHT(name,LEN(name) - CHARINDEX('-',name)) AS JobName --Takes the Part right of the first -
FROM sysjobs 

SELECT JobName 
FROM #jobs
GROUP BY JobName
HAVING COUNT(*) < 4
ORDER BY JobName

DROP TABLE #jobs

答案 1 :(得分:0)

因此,需要一个查询来返回条目少于4个的所有JobName。创建临时表没有意义,只需直接查询sysjobs表即可,例如:

SELECT name  
FROM sysjobs
GROUP BY name
HAVING COUNT(*) < 4
ORDER BY name

答案 2 :(得分:0)

如果您的CMS始终插入服务器名称,然后插入作业名称,并用短划线将其括起来,并用空格括起来,那么您可以使用以下内容解析服务器名称:

INSERT INTO #jobs
SELECT REPLACE(SUBSTRING(name, CHARINDEX(' - ', name),LEN(name)) , ' - ', '') JobName
FROM sysjobs 

答案 3 :(得分:0)

您可以使用STUFF()函数将所有服务器名称放在一列中,而仅计算作业名称。

SELECT JobName, STUFF((
    SELECT ',' + CAST([ServerName] AS VARCHAR(MAX)) 
    FROM sysjobs 
    WHERE results.JobNames = sysjobs.JobNames
    FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
  ,1,1,'') AS ServerNames 
FROM #jobs results
GROUP BY JobName
HAVING COUNT(*) < 4
ORDER BY JobName

答案 4 :(得分:0)

我设法以另一种方式解决它。现在,我在CMS服务器上设置了一个表,并且有一个存储过程,该过程将用AG中所有服务器上的代理作业的详细信息填充该表。 然后,我可以从那里运行以下查询,它就像一个超级按钮一样工作:

SELECT ServerName
       ,JobName
FROM AgentJobs
WHERE JobName IN(
                    SELECT JobName
                    FROM AgentJobs
                    WHERE JobCategory = 'Production'
                    GROUP BY JobName
                    HAVING COUNT(*) < 4)