【问题标题】:Identify agent jobs missing on secondary replicas识别辅助副本上缺少的代理作业
【发布时间】:2019-01-29 22:57:58
【问题描述】:

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

我已经设置了来自 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 列,它不会将它们识别为相同的值。

【问题讨论】:

  • 你能发一个sysjob表内容的例子吗?
  • 这是任何 sysjobs 表的标准输出,所以我不确定您需要什么?该表也有很多列,因此很难在此处放置您可以理解的输出。您想要我的查询而不是标准 sysjobs 表的示例输出吗?
  • 由于您的临时表只有一列,因此您的查询结果不能有两列。
  • @WolfgangKais 什么是“它”?您用于获取作业名称的查询仅选择一列:SELECT name JobName FROM sysjobs
  • @BrianPressler 是的,这就是我的意思。那么查询如何“抛出如下结果集”(包括ServerName在内的2列)?

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


【解决方案1】:

正如 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

【讨论】:

  • 抱歉,我注意到我的脚本的输出非常好。如上所示,它没有输出单个字符串。我需要隐藏服务器名称,所以我得到两个不同的列返回,服务器名称和作业名称。当我运行查询时,它不会忽略服务器名称列,因此将所有结果视为单独的。
  • 好的。因此,您想按 JobName 分组并计算它们,但还想查看这些作业显示的 ServerNames 是什么?
  • 我认为可能让每个人都感到困惑的是它不会将服务器名称和作业名称作为单个字符串返回。它们是两个不同的列,但查询似乎在每个服务器上单独运行结果,而不是将它们视为单个结果集。
【解决方案2】:

所以想要一个返回所有少于 4 个条目的 JobNames 的查询。没有创建临时表的意义,直接查询sysjobs表即可,如:

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

【讨论】:

  • 这不起作用,因为我正在通过 CMS 一次查询四台服务器。由于似乎与查询一起出现的服务器名称,它不会将它们识别为相同的作业名称。如果我运行您的查询,我会得到以下结果: ServerA DBA DatabaseBackup - AG_DATABASES - FULL ServerB DBA DatabaseBackup - AG_DATABASES - FULL ServerC DBA DatabaseBackup - AG_DATABASES - FULL ServerD DBA DatabaseBackup - AG_DATABASES - FULL
  • @Trinity3Sixty ok 那么这意味着我们需要提取name 字段的一部分。您能否用您的sysjobs 表中的一些示例数据更新您的问题,以便我可以更新我的查询?
  • 用示例输出更新了问题,以更好地说明问题。非常感谢您花时间帮助我。
【解决方案3】:

如果您的 CMS 始终插入服务器名称后跟作业名称,作业名称用空格包围的破折号分隔...您可以使用以下内容解析服务器名称:

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

【讨论】:

  • 它没有返回单个分隔行。它返回两列,服务器名称和作业名称。我的查询未请求服务器名称,但在 CMS 查询中默认返回服务器名称。看起来任何查询仍在将来自每个服务器的结果视为单独的实体,并且仅将它们显示为单个结果集。
  • 我不确定您所说的“它”是什么意思,它没有返回单个分隔行。 sysjobsname 字段是一个字段,所以我不清楚您要说什么。
  • “查询”不只返回来自 sysjobs 的名称字段。该查询返回两列,server 和 sysjobs.name,这是典型的 CMS 查询。我遇到的问题是我的查询没有在整个 CMS 查询的结果上运行,而是似乎单独针对每个服务器的结果集运行。因此,它仍然会返回所有行,因为它无法将不同服务器上的相同作业识别为相同的结果。
【解决方案4】:

您可以使用 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

【讨论】:

  • 服务器名称和作业名称作为单独的结果列返回。它不会将它们一起返回到一个字段中。结果似乎被视为单独的结果集,并且仅在执行任何查询后才显示为单个结果集。
【解决方案5】:

我已经设法以另一种方式绕过它。我现在已经在我的 CMS 服务器上设置了一个表,并且我有一个存储过程,它将使用来自 AG 中所有服务器的代理作业的详细信息填充该表。 然后我可以从那里运行以下查询,它就像一个魅力:

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

【讨论】:

    猜你喜欢
    • 2019-06-10
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多