重複する CMDB CI Relationshipレコード、または親/子関係から孤立しているか欠落しているレコードを特定して削除する方法Summary<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } 依存関係ビュー (BSM マップ)、CI 関係フォーマッター、識別エンジンエラーなど、CI 関係が関係する問題を調査するための最初のステップは、CI 関係テーブルをクリーンアップすることです。 CI 関係レコード [cmdb_rel_ci] は、いくつかの理由で無効化/破損する可能性があります。 親、子、またはType参照が空。これらのフィールドの 1 つ以上に値がないsys_id 値が入力されているが、CMDB にその sys_id のレコードが存在しないため、親または子の参照が無効Type参照値が無効であり、CI Relationship Type テーブルにないまったく同じ親、子、およびTypeの重複レコードが存在する この記事の目的は、これらのレコードを削除または修正する方法を説明することで、問題の潜在的な原因としてそれらを除外できるようにすることです。また、問題が最初に発生する可能性のある理由のいくつかを特定しようとします。 Release<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } Instructions<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } Table of Contents 1. 親、子、またはType参照が空、これらのフィールドの 1 つ以上に値がない2.sys_id 値が入力されているが CMDB にその sys_id のレコードが存在しないため、親または子の参照が無効3.Type参照値が無効であり、CI Relationship Type テーブルにない4.まったく同じ親、子、およびTypeの重複レコードが存在する 4.1 一度に 1 つのRelationship Type を処理することによるパフォーマンスの問題の回避 次の例では、スクリプトを使用してクリーンアップを実行できます。この種のスクリプトを実行すると、計画よりも多くが削除されるリスクが常にあります。これらを実行した直後にロールバックコンテキストを確認し、スクリプトが想定していたもののみを更新/削除したことを確認してください。 cmdb_rel_ci レコードが削除されると、relation_health_result レコードがカスケード削除されます。これは問題ありません。 1. 親、子、またはType参照が空、これらのフィールドの 1 つ以上に値がない リストから次のレコードを識別できます: https://<instance name>.service-now.com/cmdb_rel_ci_list.do?sysparm_query=parentISEMPTY%5EORchildISEMPTY%5EORtypeISEMPTY Relationship レコードが有効かつ有用であるためには、3 つのフィールドすべてに常に値がなければなりません。そのため、Relationship レコードがないものは無効であり、削除する必要があります。 var relCI = new GlideRecord('cmdb_rel_ci');relCI.addEncodedQuery('parentISEMPTY^ORchildISEMPTY^ORtypeISEMPTY');relCI.query();relCI.deleteMultiple(); 2.sys_id 値が入力されているが CMDB にその sys_id のレコードが存在しないため、親または子の参照が無効 これらのレコードはリストから識別できます。このリストは、値を持つフィールドを検索することで機能しますが、Dot-Walking 機能を使用することはできません。 https://<instance name>.service-now.com/cmdb_rel_ci_list.do?sysparm_query=parentISNOTEMPTY%5Eparent.sys_idISEMPTY%5ENQchildISNOTEMPTY%5Echild.sys_idISEMPTY 有効な CI がない、Relationship レコードも意味がないため、削除する必要があります。 注意:「Data Archiving」プラグインがインストールされている場合、このリストには、関係が作成されてからアーカイブされた CI の参照も表示される場合があります。親 CI または子 CI のいずれかがアーカイブされている場合の正しい解決策は、Relationshipレコードも同時にアーカイブすることです。ただし、この場合、アーカイブルールを実装しようとすると問題が発生します。ルールでは 1 つの参照フィールドのみを考慮することができ、これらのレコードは親と子の両方の CI を参照するためです。詳細については、次を参照してください:親または子 CI がアーカイブされると、Relationshipレコードが不要になり、これらも削除できると判断することもできます。 次のスクリプトはこれらのレコードを削除します。 var relCI = new GlideRecord('cmdb_rel_ci');relCI.addEncodedQuery('parentISNOTEMPTY^parent.sys_idISEMPTY^NQchildISNOTEMPTY^child.sys_idISEMPTY');relCI.query();relCI.deleteMultiple(); 3.Type参照値が無効であり、CI Relationship Type テーブルにない リストから次のレコードを識別できます。 https://<instance name>.service-now.com/cmdb_rel_ci_list.do?sysparm_query=typeISNOTEMPTY%5Etype.sys_idISEMPTY これらの「Type」の壊れた参照は、通常は値の修正が正しい方法であるため、別のセクションにしています。 OOTB Relationship Type のレコードが削除されている場合、Relationshipを削除することはおそらく正しい解決策ではありません。削除後にレコードが作成されていた場合、欠落している cmdb_rel_type レコードを新しいインスタンスからインポートすると、Type参照が再度有効になるため、これらのRelationshipレコードは再び有効になります。不足しているTypeの置換は、クリーンアップを実行する前に、最初に確認して実行する必要があります。削除前に存在するレコードは、そのTypeのカスケード削除の一部としてType値がクリアされた可能性があるため、パート 1/ の空のType のレコードの一部を説明します。 London リリースより前にプロビジョニングされたすべてのインスタンスでは、レコードの作成時にTypeが選択/入力されなかった場合、このフィールド値がデフォルトで「1」に設定されるため、一部のレコードでは [Type] の値が「1」になることがあります。以前はそれを「Depends on::Used by」Relationship Type として解釈するコードがありましたが、そのコードは存在しないため、これは無効なTypeになっています。この状況では、値「1」を「1a9cb166f1571100a92eb60da2bce5c5」に置き換える必要があります。これは、実際の「Depends on::Used by」Relationship Typeレコードの sys_id です。 一部のレコードには、Type の sys_id 値が切り捨てられている場合があります。London リリースまでは、Relationship Editor で [Save and Close] を複数回クリックすることで、この問題が発生する可能性がありました。通常は、値の残りの内容から想定されているTypeを把握できます。 完全な sys_id は存在するが、Relationship Type テーブルにない場合、特に Relationship レコードが標準提供のコードによって作成された場合は、標準提供のRelationship Typeレコードがインスタンスで削除されている可能性があります。復元する必要があります sys_id が標準提供の Relationship Type のいずれでもない場合、互いに同期していないインスタンスが原因である可能性があります。Type がターゲットインスタンスに存在しない場合、別のインスタンスから XML としてインポートされた CI Relationshipレコードでこの問題が発生する可能性があります。 次のスクリプトは、[Type] フィールドの「1」値と切り捨てられた値の両方を修正します。 var relCI = new GlideRecord('cmdb_rel_ci');relCI.addEncodedQuery('typeISNOTEMPTY^type.sys_idISEMPTY');relCI.query();while (relCI.next()) { if (relCI.type.toString() == '1') { relCI.type = '1a9cb166f1571100a92eb60da2bce5c5'; gs.log('Correcting cmdb_ci_rel sys_id:'+ relCI.sys_id + ', Replaced type=1 with type=1a9cb166f1571100a92eb60da2bce5c5','KB0780988'); relCI.setWorkflow(false); relCI.update(); } else if (relCI.type.toString().length < 32) { var typeGr = new GlideRecord('cmdb_rel_type'); typeGr.addEncodedQuery('sys_idENDSWITH' + relCI.type.toString()); typeGr.query(); if (typeGr.next() && typeGr.getRowCount() == 1) { gs.log('Correcting cmdb_ci_rel sys_id:'+ relCI.sys_id + ', Replaced type='+ relCI.type +' with type=' + typeGr.sys_id ,'KB0780988'); relCI.type = typeGr.sys_id; relCI.setWorkflow(false); relCI.update(); } else { gs.log('Unable to correct cmdb_ci_rel sys_id:'+ relCI.sys_id + ', type='+ relCI.type + ' - No matching record for truncated type reference','KB0780988'); } } else { gs.log('Unable to correct cmdb_ci_rel sys_id:'+ relCI.sys_id + ', type='+ relCI.type,'KB0780988'); }} 4.完全に同じ親、子、およびTypeの重複レコードが存在する これはリストビューからは識別できません。追加のレコードを識別して削除し、元のレコードは残しておくためのスクリプトが必要です。次のスクリプトをdry-runモードで実行して確認できます。 次のスクリプトは、GlideAggregate を使用する内部 KB 記事 (KB0744490) に基づき、この状況のためにセットアップされています。これは、インスタンスメモリに過度の負荷がかかるのを避けるために、一度に 5000 件のバッチを実行するため、複数回実行する必要がある場合があります。 削除される関係のいずれかの側の CI がサービスに関与している場合、サービスモデルのレイヤー/環境がRelationshipおよび CI と同期されていることを確認するために、Service Mapping 再計算ジョブが実行されることが想定されます。これは正常です。 // Background script for Deleting duplicate records // *********************************** SETUP **************************************************************************************************************** var dryRun = true; // SET THIS TO false TO ACTUALLY DELETE RECORDS var tableName = 'cmdb_rel_ci'; // TARGET TABLE var encodedQuery = 'parentISNOTEMPTY^typeISNOTEMPTY^childISNOTEMPTY'; // APPLY ANY FILTER CONDITIONS HERE var identifierFields = 'parent,type,child'; //USED TO IDENTIFY THE DUPLICATES var batch = 5000 ; //SETS THE LIMIT FOR HOW MANY RECORDS ARE IN THE GLIDERECORD // ********************************************************************************************************************************************************** var identifiers = identifierFields.split(','); //split up the groupby fields, we'll use this one later var agg = new GlideAggregate(tableName); agg.addQuery(encodedQuery); agg.setLimit(batch); // ADD THE COMBINATION OF UNIQUE IDENTIFIERS HERE for(var i = 0; i < identifiers.length; i++) { agg.groupBy(identifiers[i]); } // DON'T BOTHER READING ANY RECORDS THAT AREN'T DUPLICATE agg.addAggregate('COUNT'); agg.addHaving('COUNT','>','1'); // only where 1 or more duplicates exist agg.query(); // AT THIS POINT WE ONLY HAVE DUPLICATE RECORDSETS (WHERE THERE IS MORE THAN ONE RECORD WITH THE SAME IDENTIFYING FIELDS) // NOW LOOP THROUGH ALL OF THOSE RECORDSETS, KEEPING ONLY THE OLDEST RECORD AND DELETING THE REST var resultString = '\nUnique Set\tRecord to keep\tRecord(s) to delete\n'; // In order to avoid using many gs.print() statements we simply add all the results to a string and display them at the end. var resultCount = 0 //Count the duplicates while(agg.next()) { resultString += getSetDetailsString(agg); //log the set that brought us here var dup = new GlideRecord(tableName); dup.addQuery(encodedQuery); dup.setLimit(batch); //get the records that match the set for(var i = 0; i < identifiers.length; i++) { dup.addQuery(identifiers[i],agg[identifiers[i]]); } // order by date ascending. the first record is the oldest and the one we want to preserve. Change for 'orderByDesc' to preserve the newest record and remove the rest dup.orderBy('sys_created_on'); dup.query(); // skip the first record (original) and log it dup.next(); resultString += (dup.sys_created_on + ' - '+ dup.sys_id + '\t'); // loop through and delete the remaining records for this set. Only deletes if dryRun = false while(dup.next()) { resultString += (dup.sys_created_on + ' - '+ dup.sys_id + ', '); resultCount++; if(!dryRun) { //CAREFUL dup.setWorkflow(false); dup.deleteRecord(); } } resultString += '\n'; } //Display results in TAB SEPARATED FORMAT gs.print('Duplicate count: ' + resultCount); gs.print(resultString); //helper method to dynamically create the SET string for logging function getSetDetailsString(gRecord) { var returnString = '('; for(var i = 0; i < identifiers.length; i++) { returnString += identifiers[i] + ': ' + gRecord[identifiers[i]] + ', '; } returnString += ')\t'; return returnString; } 4.1 一度に 1 つのRelationship Type を処理することによるパフォーマンスの問題の回避 上記のスクリプトは GlideAggregate を実行し、親、子、クラスの 3 つのフィールドと、場合によってはRelationshipテーブル全体に対して groupBy を追加します。これは、インスタンス/データベースのパフォーマンスの点でコストがかかる可能性があります。 groupBy フィールドの数を 2 に減らし、最初に関係する cmdb_rel_ci レコードの数を減らすには、クエリに 1 つのRelationship Type を追加します。すべてのレコードが同じTypeにするため、[type] フィールドで groupBy を実行する必要はありません。 次に、重複を排除する Relationship Type ごとにスクリプトを実行します。 例: Relationship Type "Runs on::Runs":/cmdb_rel_type.do?sys_id=60bc4e22c0a8010e01f074cbe6bd73c3 関係のリストビューから、AND タイプ = Runs on:: Runs を追加できます。そのクエリ文字列を変数にコピーします。また、フィールドのリストからTypeを削除します。 var encodedQuery = 'parentISNOTEMPTY^typeISNOTEMPTY^childISNOTEMPTY^type=60bc4e22c0a8010e01f074cbe6bd73c3'; // 初期クエリーに「runs on」タイプを追加var identifierFields = 'parent,child'; //データには 1 つのタイプしかないため、リストからタイプを削除 通常のスクリプトを使用して実行時間が非常に長いジョブがある場合、または実行時にインスタンスメモリを使用するジョブが多すぎる場合、またはデータベースのパフォーマンスの問題がある場合、これにより、インスタンスへの影響を最小限に抑えてスクリプトを完了することができます。 Related Links<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } これらは既知の原因の一部です。修正済みバージョンへのアップグレードまたはワークアラウンドの適用は、クリーンアップの一環として行う必要があります。 PRB1390309 Under some circumstance Discovery/IRE creates orphaned relationships where the parent/child SYS id is null/empty/invalidPRB1414566 Discovery Table Cleanup does not perform cascade deletion on m2m table leaving orphaned records.Relationship Type レコードの削除や名前の変更を防ぐものはありません。Discovery と Service Mapping は、type 名または sys_id に対してハードコードされているため、Type 参照が壊れているか空のRelationshipレコードを引き続き作成します。KB0852524 / PRB1386982 Relation types that are dependencies of Discovery and Service Mapping Patterns can be renamed or deleted from cmdb_rel_type tableLondon リリースまでの場合、[Type] 値なしで保存された新しいRelationshipレコードは、デフォルトで値「1」に設定されます。これは「Depends on::Used by」Releationship Typeの従来の sys_id でしたが、辞書内のフィールドはこのデフォルト値をずっと保持していました。これは PRB1251706 で新しいインスタンスに対してのみ修正されました。アップグレードする顧客の場合、このフィールドのデフォルト値を辞書から手動でクリアする必要があります。KB0743762: The CI Relationship record's Relationship Type reference field has a bad default value of 1London (+KP8) までは、PRB1273072 は、[Save and Close] ボタンが複数回クリックされることをRelationship Editorが防止しなかったことを意味していました。これにより、relationship typeフィールドの sys_id 値が切り捨てられるという影響がありました。これを防ぐには、1 回クリックしてフォームが閉じるまで待機します。London (+KP5/JP9) までは、PRB1241891 があり、ADM がアプリケーション CI を作成する前に、アプリケーションパターンによってアプリケーション CI との関係が作成されていました。parent または child の値は空のままになります。Relationship Typeのレコードが手動で削除された場合、カスケード削除によってRelationshipレコードも削除されるため、問題は発生しません。ただし、CI とそのRelationshipがカスタムスクリプトまたは XML インポート/インポートセットを介して挿入/インポートされ、Relationship Typeが存在しない場合は、これらの不適切なRelationshipレコードがその方法で作成される可能性があります。CMDB にデータアーカイブが使用されている場合は、CI をアーカイブしてもRelationshipレコードは残る可能性があります。アーカイブルールは、同時にアーカイブされる cmdb_rel_ci テーブルの関連するレコードを使用して設定する必要がありますが、PRB1296280 のため [親] と [子] の両方の参照フィールドを同時に実行することはできません。 これは、単一の「参照要素」の制限を取り除くことを目的としています。KB0695364: It is not possible to archive all cmdb_rel_ci record when CI records are Archived, leading to CompactRelation errors when the CMDB Identification Engine fails to consider that a CI may be Archived and throws an error, causing major syslog table growthRelationship Editorをロードして [Save and Close] ボタンをクリックすると、メイン CI または関連 CI のいずれかの CI が他のユーザーによって削除された可能性があります。いずれにせよ、CI がまだ存在することを確認せずに以前の sys_id 値を使用してRelationshipレコードが追加されます。また、Relationship Editorフォームの URL に無効または空の sys_id がロードされた場合でも、存在しない CI に関係を追加でき、不適切なレコードが発生します。低いですが可能性があります。