How to bulk update records without changing sys_updated_on or firing business rules

seungchulkim
Tera Contributor

Hi Guys, This is Iron

Do you happen to know that you can achieve this with setWorkflow(false) + autoSysFields(false) + updateMultiple(), and by only touching records whose value is actually different. This keeps audit columns clean and makes the job safe to rerun.

Step 1: Group first, then write once per group

Instead of looping every record, find the distinct combinations that decide the result.

 

var ga = new GlideAggregate('cmdb_software_instance');
ga.addNotNullQuery('u_raw_appname');
ga.groupBy('u_raw_appname');
ga.groupBy('u_raw_fullversion');
ga.addAggregate('COUNT');
ga.query();
// millions of rows -> a few thousand combinations


Step 2: Update only what changed

var gr = new GlideRecord('cmdb_software_instance');
gr.addQuery('u_raw_appname', name);
gr.addQuery('u_raw_fullversion', version);
gr.addEncodedQuery('u_eol_status!=' + status + '^ORu_eol_statusISEMPTY');   // skip rows already correct
gr.setWorkflow(false);       // no business rules, notifications, audit
gr.autoSysFields(false);     // sys_updated_on / sys_updated_by / sys_mod_count stay as they are
gr.setValue('u_eol_status', status);
gr.setValue('u_eol_date', eolDate);
gr.updateMultiple();

 

Step 3: Add a dry-run switch

initialize: function (opt) { opt = opt || {}; this.dry = !!opt.dry; },

run: function () {
    var st = { dry: this.dry, updated: 0 };          // return dry in the result so you can verify it later
    // ... count first ...
    if (this.dry) return st;
    // ... write ...
    return st;
}

 

// Background script
var job = new MyBulkUpdater({ dry: true });
gs.info('dry=' + job.dry);                        // confirm before running
gs.info(JSON.stringify(job.run()));

 

When NOT to use this

 

  • setWorkflow(false) also skips business rules you may need (e.g. CMDB reconciliation). Use it only for fields your own process owns.
  • Leaving out autoSysFields(false) on a cleanup job stamps your user on every touched record. We saw this on ~29K CIs before adding it.

If this helped, please mark it as Helpful 👍




sys_updated_on を変えず、ビジネスルールも動かさずに一括更新する方法

setWorkflow(false) + autoSysFields(false) + updateMultiple() を使い、さらに値が実際に異なるレコードだけを更新することで実現できます。監査用の列が汚れず、ジョブを何度再実行しても安全です。

Step 1: 先にグループ化し、グループごとに 1 回だけ書き込む

全レコードをループするのではなく、結果を決める組み合わせを先に取ります。

 

var ga = new GlideAggregate('cmdb_software_instance');
ga.addNotNullQuery('u_raw_appname');
ga.groupBy('u_raw_appname');
ga.groupBy('u_raw_fullversion');
ga.addAggregate('COUNT');
ga.query();
// 数百万行 -> 数千の組み合わせ

 

Step 2: 変わったものだけ更新する

var gr = new GlideRecord('cmdb_software_instance');
gr.addQuery('u_raw_appname', name);
gr.addQuery('u_raw_fullversion', version);
gr.addEncodedQuery('u_eol_status!=' + status + '^ORu_eol_statusISEMPTY');   // すでに正しい行はスキップ
gr.setWorkflow(false);       // ビジネスルール・通知・監査を動かさない
gr.autoSysFields(false);     // sys_updated_on / sys_updated_by / sys_mod_count を変えない
gr.setValue('u_eol_status', status);
gr.setValue('u_eol_date', eolDate);
gr.updateMultiple();

付ける

initialize: function (opt) { opt = opt || {}; this.dry = !!opt.dry; },

run: function () {
    var st = { dry: this.dry, updated: 0 };          // 後で確認できるよう結果に dry を入れる
    // ... まず件数を数える ...
    if (this.dry) return st;
    // ... 書き込み ...
    return st;
}



// バックグラウンドスクリプト
var job = new MyBulkUpdater({ dry: true });
gs.info('dry=' + job.dry);                        // 実行前に確認
gs.info(JSON.stringify(job.run()));

 

使うべきでない場面

  • setWorkflow(false) は必要なビジネスルール(CMDB の照合など)も止めます。自分の処理が所有するフィールドだけに使ってください。
  • クリーンアップジョブで autoSysFields(false) を忘れると、触った全レコードに自分のユーザー名が残ります。実際に約 2.9 万件の CI で発生しました。

参考になれば Helpful をお願いします 👍

0 REPLIES 0