Migrating non-reference fields to reference fields
Summarize
Summary of Migrating non-reference fields to reference fields
This process enables ServiceNow customers to convert non-reference (string) fields into reference fields by manually preserving sysids rather than storing display names as strings. This migration improves data integrity and efficiency when dealing with archived records and their references in archive tables.
Show less
Determining Tables to Migrate
To start the migration, run a background script that identifies and creates migration records for eligible tables. It processes both direct table extensions and related archived records, ensuring only valid archive tables (prefixed with ar) are included. It also handles related records linked via archive rules to encompass all necessary tables for migration.
Copying Archive References
The Archive Reference Copy (RefCopyJob) job updates archived records by locating the sysid of referenced fields and replacing their display values with the correct sysid. This job processes up to 10,000 records per run, using archive timestamps to track progress.
Changing Field Types from String to Reference
After migrating data for all tables associated with an archive rule, the ArchiveRefJob executes to modify the dictionary definitions of the archive tables, converting the field types from string to reference. This finalizes the structural migration.
Handling Node Failures and Job Recovery
- If the RefCopyJob fails, tables may remain in a
migratingstatus. Customers can verify this by checking thesysarchiverefmigrationtable for stuck records and manually update the status back towaitingto resume migration. - If the ArchiveRefJob stops prematurely, some fields may remain string types while others are references. To resolve this, customers can trigger the job again via a background script that reinitializes the job execution and completes the migration.
Practical Benefits for ServiceNow Customers
- Ensures archived data references are preserved accurately by sysid rather than display strings, improving data consistency.
- Automates the detection and migration of all relevant tables and related archives for comprehensive data migration.
- Provides mechanisms to monitor job progress and recover from failures without losing migration state.
- Finalizes migration by updating field definitions, ensuring future data integrity and simplifying reference management.
Manually preserve sys_ids in reference fields instead of storing the display name as a string.
Determining tables to migrate
var tables = GlideDBObjectManager.get().getAllExtensions(current.table);
for (i = 0; i < tables.size(); i++) {
var gr = new GlideRecord('sys_archive_ref_migration');
gr.addQuery('table', 'ar_' + tables.get(i));
gr.query();
if (!gr.next()) {
if (GlideTableDescriptor.isValid('ar_' + tables.get(i))) {
var gr2 = new GlideRecord("sys_archive_ref_migration");
gr2.initialize();
gr2.setValue('rule', current.sys_id);
gr2.setValue('table', 'ar_' + tables.get(i));
gr2.setValue('reference_migration_progress', 'waiting');
gr2.insert();
}
}
}
//Also get insert related records tables as well
var map = new GlideRecord('sys_archive');
map.addQuery('table', current.table);
map.query();
if (map.next()) {
var id = map.getValue('sys_id');
if (!(id === undefined)) {
var related = new GlideRecord('sys_archive_related');
related.addQuery('archive_map', id);
related.addQuery('action', 'archive');
related.query();
while (related.next()) {
if (!GlideTableDescriptor.isValid('ar_' + related.getValue('table'))) {
gs.log('Related Record table: ' + related.getValue('table') + ' not created yet');
continue;
}
var gr3 = new GlideRecord("sys_archive_ref_migration");
gr3.initialize();
gr3.setValue('rule', current.sys_id);
gr3.setValue('table', 'ar_' + related.getValue('table'));
gr3.setValue('reference_migration_progress', 'waiting');
gr3.insert();
}
}
}Copying archive references
For each table that goes through the migration process, the Archive Reference Copy (RefCopyJob) job identifies the sys_id of the reference fields and updates the display value to be the correct sys_id. The job configures 10k records at a time unless there are more than 10k records with the same timestamp. The migration progress relies on the archived timestamp.
Changing field types from string to reference
After the tables associated with an archive rule completely migrate, the ArchiveRefJob job executes. This job changes the sys_dictionary types of the archive table from string to reference.
Fixing node failures for RefCopyJob and ArchiveRefJob
If node failure occurs while these jobs are running, it leaves the status of the data migration in an improper state. If the RefCopyJob fails, it can leave a table in a migrating status. You can verify this condition by checking if rows in the sys_archive_ref_migration are stuck in migrating status for an extraordinary amount of time. Update the specific row status from migrating to waiting and the RefCopyJob continues the data migration on the table when the job runs again.
GlideRecord trigger = new GlideRecord('sys_trigger');
trigger.initialize();
trigger.setValue('state', 0);
trigger.setValue('trigger_type', 0);
trigger.setValue('next_action', new GlideDateTime());
trigger.setValue('job_context', 'fcRuleId=' + ruleId);
trigger.setValue('name', 'Job Reference Migration' + ' Node - ' + new GlideClusterSynchronizer().getSystemID());
trigger.setValue('trigger_class', 'com.glide.db.auxiliary.job.ArchiveRefJob');
trigger.insert();