SCOM のデータベース領域が想定以上に増加してしまった場合の調査方法について

こんにちは。日本マイクロソフトの佐々木です。

SCOM を利用している中でデータ量が想定以上に増加してしまった場合の調査方法について、TIPSをご紹介します。

一般に SCOM が収集するデータ量は監視対象の状況や台数、導入している管理パックによって様々に変化します。このため、個々の環境でどれくらいのデータ量が妥当かを正確に見積もることは非常に困難です (※見積もり方法については参考内の記事をご参照ください)。ある日を境に当初の見積もりを超えてデータ量が異常に多くなり、最終的にはデータベース領域が圧迫されるなんてことも、残念ながら結構起きます。

このような問題のよくある原因としては、特定のルールやモニタ等の監視定義から大量のデータが生成されていることが考えられます。
例えば、作成したルールに絞り込み条件が抜けている等の問題があり、想定以上のデータを収集してしまっているといった場合です。
このような場合には、データベースの圧迫を引き起こしているルールを特定して対処を行う必要があります。
こんな時には、以下に紹介するステップを参照してみてください。SCOM 2007、  SC 2012 OM のいずれのバージョンでも共通で利用することができます。

※ご注意を頂きたい点※
これらの方法は主にトラブルシュートを目的としたものです。また結果は環境毎に異なります。
それらの定義に対してどのような変更 (ルールの無効化や設定の変更等) を行うかはユーザー自身で判断する必要があります。

- 手順の概要
初めにSCOMが利用するOperationsManagerテーブルサイズの一覧(「A.) テーブルサイズの一覧」) を確認します。例えば、イベントデータやパフォーマンスデータのサイズが多いことが確認できた場合には、それらのデータを生成しているルールやモニタに問題があることが判ります。その後、後述のクエリ(「B.) データを多く報告している具体的な監視定義の確認方法」)の実施により、データを多く生成している具体的な監視の定義を確認します。最後に、必要に応じて定義の変更 (無効化あるいは監視内容の変更等) による対処を実施します。

A.) テーブルサイズの一覧
==================================

以下のクエリを実行します。
------------------------------------------------------
use OperationsManager
CREATE TABLE temp (
TABLE_NAME sysname,
rows sysname,
reserved sysname,
DATA varchar(32),
index_size varchar(254),
unused varchar(100)
)
INSERT INTO temp EXEC sp_MSforeachtable @command1 = "sp_spaceused '?'"
SELECT * FROM temp order by table_name
drop table temp
------------------------------------------------------

データ増加の要因となる可能性が高い以下のテーブルには、特に注目してください。

StateChangeEvent   --> 状態変更のデータに該当します。
Event_** --> イベントのデータに該当します。

B.) データを多く報告している具体的な監視定義の確認方法
==================================

a. 状態変更イベントの発生元モニタの確認
状態変更イベントは、モニタの状態が遷移したことを示す情報です。特定の監視対象が頻繁に状態変更を繰り返している場合、その監視対象を監視するモニタにより状態変更イベントが多く記録されるケースがあります。

---------------------------------------
use OperationsManager

CREATE TABLE temp_SCMC (
StateChangeMonitorCount [int] NOT NULL,  MonitorId [uniqueidentifier] NOT NULL
)

insert into temp_SCMC select count(*) AS StateChangeMonitorCount , MonitorId
from statechangeeventview group by MonitorId

select M.MonitorName, SCMC.StateChangeMonitorCount
from temp_SCMC SCMC
inner join Monitor M on M.MonitorId = SCMC.MonitorId
order by SCMC.StateChangeMonitorCount DESC

drop table temp_SCMC
---------------------------------------

b. イベントデータを報告しているルールの確認
---------------------------------------
use OperationsManager

CREATE TABLE temp_ERC (
EventRuleCount [int] NOT NULL,
RuleId [uniqueidentifier] NOT NULL
)

insert into temp_ERC select count(*) As EventRuleCount, RuleId
from EventAllView
Group By RuleId

select RS.RuleName, ERC.EventRuleCount
from temp_ERC ERC
inner join Rules RS on RS.RuleId = ERC.RuleId
order by ERC.EventRuleCount DESC

drop table temp_ERC
---------------------------------------

c. パフォーマンスデータを報告しているルールの確認
---------------------------------------
use OperationsManager

CREATE TABLE temp_PRC (
PerfRuleCount [int] NOT NULL,
RuleId [uniqueidentifier] NOT NULL
)

insert into temp_PRC
select count(*) AS PerfRuleCount, PS.RuleId
from PerformanceDataAllView PDAV
inner join PerformanceSource PS on PDAV.PerformanceSourceInternalId = PS.PerformanceSourceInternalId group by RuleId

select RS.RuleName, PRC.PerfRuleCount
from temp_PRC PRC
inner join Rules RS on RS.RuleId = PRC.RuleId
order by PRC.PerfRuleCount DESC

drop table temp_PRC
---------------------------------------

- 実施手順の例
~~~~~~~~~~~~~~~~~~~~~~~~~~
例えばイベントデータを生成しているルールを、データが多い順に確認する方法は以下の通りになります。
「a.) 状態変更イベントの発生元モニタの確認」あるいは「c.) パフォーマンスデータを報告しているルールの確認」についても同様の手順で実施可能です。
最も効果があるシナリオは、独自のイベント収集ルールやパフォーマンス収集ルールを作成しており、それらに起因してデータが増えているケースです。そのような場合には、定義を見直すことで大幅にデータ量が削減されることが見込まれます。

※ご注意を頂きたい点※
これらの方法は主にトラブルシュートを目的としたものです。また結果は環境毎に異なります。
それらの定義に対してどのような変更 (ルールの無効化や設定の変更等) を行うかはユーザーが判断する必要があります

1.) 始めにイベントデータを報告しているルールをデータ量が多い順に確認します。

以下のクエリを実行します。実行結果に極端に多く出力されているルールがある場合には、そのルールに注目します。
※結果はSCOMのワークフロー名 (DB上で管理される内部的な名称) として出力されます。後の手順で SCOM コンソールで示されるルール名 (表示名) に変換します。

---------------------------------------
use OperationsManager

CREATE TABLE temp_ERC (
EventRuleCount [int] NOT NULL,
RuleId [uniqueidentifier] NOT NULL
)

insert into temp_ERC
select count(*) As EventRuleCount, RuleId
from EventAllView Group By RuleId

select RS.RuleName, ERC.EventRuleCount
from temp_ERC ERC
inner join Rules RS on RS.RuleId = ERC.RuleId
order by ERC.EventRuleCount DESC

drop table temp_ERC
---------------------------------------

2.) ワークフロー名から実際のルール名を確認するために以下のクエリを実行します。

SET @ObjectName 以降にワークフロー名を入力します。
以下のクエリは Microsoft.SystemCenter.BatchResponseModule.AlertOnFailedResponses とした場合です。

*本手順は以下のブログの記事にも記載をしておりますのでよろしければご参照ください。
“SCOM2007 / イベントログ内のワークフロー名から、アラートの元となった「ルール」、「モニタ」及び「検出」を特定する方法について”
https://blogs.technet.com/b/systemcenterjp/archive/2009/08/17/scom2007.aspx

-----------------------------------------
Use OperationsManager
DECLARE @ObjectName NVARCHAR(256)
SET @ObjectName = 'Microsoft.SystemCenter.BatchResponseModule.AlertOnFailedResponses'
IF EXISTS (SELECT 1 FROM DiscoveryView WITH (NOLOCK) WHERE Name = @ObjectName)
        SELECT
                'Discovery' As 'Object Type',
                d.DisplayName AS 'Displayname in Console',
                d.Name AS 'Internal Monitor Name',
                d.Id AS 'MonitorId',
                p.Displayname AS 'ManagementPack',
                p.Version AS 'ManagementPack Version',
                p.Name AS 'Management Pack Library Name'
        FROM DiscoveryView d WITH (NOLOCK)
        INNER JOIN ManagementPackView p WITH (NOLOCK) ON d.ManagementPackId = p.Id
        WHERE d.Name = @ObjectName
ELSE IF EXISTS (SELECT 1 FROM MonitorView WITH (NOLOCK) WHERE Name = @ObjectName)
        SELECT
                'Monitor' AS 'Object Type',
                m.DisplayName AS 'Displayname in Console',
                m.Name AS 'Internal Monitor Name',
                m.Id AS 'MonitorId',
                p.Displayname AS 'ManagementPack',
                p.Version AS 'ManagementPack Version',
                p.Name AS 'Management Pack Library Name'
        FROM MonitorView m WITH (NOLOCK)
        INNER JOIN ManagementPackView p WITH (NOLOCK) ON m.ManagementPackId = p.Id
        WHERE m.Name = @ObjectName
ELSE IF EXISTS (SELECT 1 FROM RuleView WITH (NOLOCK) WHERE Name = @ObjectName)
        SELECT
                'Rule' AS 'Object Type',
                r.DisplayName AS 'Displayname in Console',
                r.Name AS 'Internal Rule Name',
                r.Id AS 'RuleId',
                p.Displayname AS 'ManagementPack',
                p.Version AS 'ManagementPack Version',
                p.Name AS 'Management Pack Library Name'
        FROM RuleView r WITH (NOLOCK)
        INNER JOIN ManagementPackView p WITH (NOLOCK) ON r.ManagementPackId = p.Id
        WHERE r.Name = @ObjectName
-----------------------------------------

3.) 出力された結果の内、「 Displayname In Console 」列に注目します。
この列で示されている名称が実際にコンソール上で示される、該当のルールの表示名です。
例えば「 Microsoft.SystemCenter.BatchResponseModule.AlertOnFailedResponses 」の場合は "失敗したバッチ応答に関するアラート" が表示名になります。

4.)  ルールやモニタの定義を変更します。
手順 2.)の出力結果には管理パック名やそのバージョンも出力されます。「作成」ペインよりそれらの情報を元に実際のルールを見つけ、必要に応じて上書きにより定義の変更あるいはルール自体の無効化を実施します。

(参考)
併せてこちらもご参照ください。
“System Center 2012 Operations Manager スペックを見積もるツールのご紹介”
https://blogs.technet.com/b/systemcenterjp/archive/2012/04/23/3493758.aspx