Skip to main content
Delphix

Troubleshoot MASKING_GENERATED_IDENTITY_TMP (KBA8902)

 

 

KBA

KBA# 8902

At a Glance 

Description:  This page describes what MASKING_GENERATED_IDENTITY_TMP is, when it is used, possible issues, how to troubleshoot, and how to resolve issues.

This feature replaces DMS_ROW_ID from version 6.0.10.0.
What is MGIT: MASKING_GENERATED_IDENTITY_TMP (MGIT) is an indexed IDENTITY column created by the Engine to assist In-Place Jobs. The column is created if a masked table doesn't have a:
 1. IDENTITY column.
 2. Primary Key, or
 3. Logical Key. 

The index created is called i_MASKING_GENERATED_IDENTITY_TMP.

If there is an IDENTITY column in a masked table but no index, the engine will create only the index in order to increase Update performance.

Process: The IDENTITY column is created before masking starts in the following step:
CREATE IDENTITY TRANSFORMATION
 1. If not exist, create MGIT
 2. If not exist, create i_MGIT


The following step removes the IDENTITY column after masking;
DROP IDENTITY TRANSFORMATION
 1. If exist, drop i_MGIT
 2. If exist, drop MGIT


If the job is killed or canceled, the MGIT and i_MGIT will be left on the table (and reused).
Possible Issues and Solutions:  Brief summary of issues that can surface related to the MGIT are:
  • Creation of the IDENTITY column MGIT and its index i_MGIT:
    • This can take time and will require resources on the database.
    • Appropriate permissions are required to alter the table and create/drop indexes.
       
  • When a job fails, it can leave the MGIT and/or i_MGIT on the table.
    • Resolve the possible job failure.
    • When resolved, restart the job - the IDENTITY column will be reused.
       
  • Failure adding MGIT to the Rule Set: 
    • It is not possible to add MGIT to the Rule Set or Inventory.
    • If Custom SQL is needed, use FILTER instead.
    • If a value needs to be cast - the IDENTITY column needs to be manually created.
       
  • Rule Set Refresh is failing:
    • If MGIT is defined on the table, the Rule Set cannot be refreshed.
    • Please manually remove MGIT and i_MGIT from the tables.
       
  • Masking Primary Key or Logical Key:
    • Please see below for referenced KBAs.
Dms_row_id: MASKING_GENERATED_IDENTITY_TMP is enhanced and replacing DMS_ROW_ID.
Applies to: The MASKING_GENERATED_IDENTITY_TMP was introduced in 6.0.10.0 and is currently only supported on:
  • MS SQL Server
  • SAP ASE (Sybase)
  • PostgreSQL
  • MySQL

Notes:

  • Oracle has the same feature but will automatically use ROWID (no need to create MGIT).
  • For PostgreSQL, it is possible to bypass MGIT by using ctid as a Logical Key. 
Notes:  Never manually create or remove MASKING_GENERATED_IDENTITY_TMP or its index. This will result in an error. 

MASKING_GENERATED_IDENTITY_TMP is a reserved word on the Engine and cannot appear in the Rule Set or Inventory.
Related info: Related Masking Documentation and Knowledge:

What is MASKING_GENERATED_IDENTITY_TMP? 

The MASKING_GENERATED_IDENTITY_TMP is a temporary IDENTITY column created on the database by the Engine if there is no Unique Row Identifier (URI) on a table on an In-Place job.

In order to Mask or Tokenize a table using In-Place (IP) the table needs a column that uniquely identifies each row - a Unique Row Identifier (URI). This URI is the Key in the Update statement. If a URI is missing, the Engine will create DMS_ROW_ID (as an Identity column) and create an index called i_DMS_ROW_ID.

When the masking job has finished, the Engine will remove the index and the column.

Why is it created? 

The column MASKING_GENERATED_IDENTITY_TMP is created if a masked table doesn't have a:

  1. IDENTITY column on the table.
  2. Primary Key (PK) on the table, or
  3. Logical Key (LK) defined in the Rule Set. 

 

The creation and application of the MASKING_GENERATED_IDENTITY_TMP in the job are automatic and no actions are normally required. 

 

There are some instances where the creation of the IDENTITY column is not possible. Two examples are detailed below:

  • Masking Primary Key - see KBA1776.
  • Masking IDENTITY column - see KBA7266.

When is it created?

The MASKING_GENERATED_IDENTITY_TMP is not created when a Primary Key or an Identity column is present or a Logical Key has been specified in the Rule Set. 

The MGIT and the index is created in the following step - and has the following rules:

CREATE IDENTITY TRANSFORMATION
 1. If not exist, create MGIT
 2. If not exist, create i_MGIT

Order of events

The order of these transformations differs between the type of database.

SQL Server:
<Start Job Action>
1. Optional: Disable Constraints
2. Optional: Drop Indexes
3. Optional: Disable Triggers
4. CREATE IDENTITY TRANSFORMATION
5. Optional: PRESCRIPT TRANSFORMATION
<Start Masking/Tokenization>
Sybase:
PostgreSQL:
MySQL:
<Start Job Action>
1. CREATE IDENTITY TRANSFORMATION
2. Optional: DROP INDEX TRANSFORMATION
3. Optional: PRESCRIPT TRANSFORMATION
     a. Custom PreScript SQL
     b. Disable Triggers
     c. Disable Constraints
<Start Masking/Tokenization>

When is it removed? 

The MASKING_GENERATED_IDENTITY_TMP and the index i_MASKING_GENERATED_IDENTITY_TMP are removed from the database after completion of the job.

The removal is done in the following step - and has the following rules:

DROP IDENTITY TRANSFORMATION
 1. If exist, drop i_MGIT
 2. If exist, drop MGIT

Canceled or terminated jobs

Should the job be canceled (killed) or crashed - the IDENTITY columns and the indexes created will be left on the database.   

Order of events

The order of these transformations differs between the type of database.

SQL Server:
<Start Job Action>
1. Optional: Enable Triggers
2. Optional: Create Indexes
3. Optional: Enable Constraints
4. CREATE IDENTITY TRANSFORMATION
5. Optional: POSTSCRIPT TRANSFORMATION
<Start Masking/Tokenization>
Sybase:
PostgreSQL:
MySQL:
<Start Job Action>
1. Optional: POSTSCRIPT TRANSFORMATION
     a. Custom PostScript SQL
     b. Enable Triggers
     c. Enable Constraints
2. Optional: CREATE INDEX TRANSFORMATION
3. DROP IDENTITY TRANSFORMATION
<Start Masking/Tokenization>

Applicable Delphix Versions

Click here to view the versions of the Delphix engine to which this article applies
Major Release All Sub Releases
6.0 6.0.0.0, 6.0.1.0, 6.0.1.1, 6.0.2.0, 6.0.2.1, 6.0.3.0, 6.0.3.1, 6.0.4.0, 6.0.4.1, 6.0.4.2, 6.0.5.0, 6.0.6.0, 6.0.6.1, 6.0.7.0, 6.0.8.0, 6.0.8.1, 6.0.9.0, 6.0.10.0, 6.0.10.1, 6.0.11.0, 6.0.12.0, 6.0.12.1, 6.0.13.0, 6.0.13.1, 6.0.14.0, 6.0.15.0, 6.0.16.0, 6.0.17.0, 6.0.17.2

5.3

5.3.0.0, 5.3.0.1, 5.3.0.2, 5.3.0.3, 5.3.1.0, 5.3.1.1, 5.3.1.2, 5.3.2.0, 5.3.3.0, 5.3.3.1, 5.3.4.0, 5.3.5.0, 5.3.6.0, 5.3.7.0, 5.3.7.1, 5.3.8.0, 5.3.8.1, 5.3.9.0

5.2

5.2.2.0, 5.2.2.1, 5.2.3.0, 5.2.4.0, 5.2.5.0, 5.2.5.1, 5.2.6.0, 5.2.6.1

5.1

5.1.0.0, 5.1.1.0, 5.1.2.0, 5.1.3.0, 5.1.4.0, 5.1.5.0, 5.1.5.1, 5.1.6.0, 5.1.7.0, 5.1.8.0, 5.1.8.1, 5.1.9.0, 5.1.10.0

5.0

5.0.1.0, 5.0.1.1, 5.0.2.0, 5.0.2.1, 5.0.2.2, 5.0.2.3, 5.0.3.0, 5.0.3.1, 5.0.4.0, 5.0.4.1, 5.0.5.0, 5.0.5.1, 5.0.5.2, 5.0.5.3, 5.0.5.4

Identify MGIT on table

It might be required to identify on what table the MGIT identity column and/or the i_MGIT index were created. For example when a job has been canceled and the Rule Set needs to be modified/refreshed. 

Use the SQL listed below for the appropriate database.

MS SQL Server

The i_MGIT index

SELECT s.name as "Schema", t.name as "Table", c.name as "Column", i.name as "Index"
FROM sys.indexes i, sys.index_columns ic, sys.columns c, sys.tables t, sys.schemas s
WHERE
  i.object_id = ic.object_id AND
  i.index_id = ic.index_id AND
  ic.object_id = c.object_id AND
  ic.column_id = c.column_id AND
  i.object_id = t.object_id AND
  t.schema_id = s.schema_id AND
  i.name = i_MASKING_GENERATED_IDENTITY_TMP;

The MGIT column

SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS  
WHERE 
   COLUMN_NAME = MASKING_GENERATED_IDENTITY_TMP;

Sybase

The i_MGIT index

SELECT su.name as "Schema", so.name as "Table", si.name as "Index"
FROM sysobjects so, sysusers su, sysindexes si
WHERE 
  so.uid  = su.uid AND
  si.id = so.id AND
  si.name = i_MASKING_GENERATED_IDENTITY_TMP

The MGIT column

SELECT su.name "Schema", so.name "Table", sc.name "Column"
FROM sysobjects so, sysusers su, syscolumns sc
WHERE
  so.uid  = su.uid AND
  sc.id = so.id AND
  sc.name = MASKING_GENERATED_IDENTITY_TMP

PostgreSQL

The i_MGIT index

Note: The i_MGIT index has the table name concatenated to the end of the index name.

SELECT n.nspname "Schema", c.relname "Index_Table"
FROM PG_CLASS C JOIN PG_NAMESPACE N ON N.OID = C.RELNAMESPACE
WHERE C.RELNAME ~ i_MASKING_GENERATED_IDENTITY_TMP;

The MGIT column

SELECT table_catalog, table_schema, table_name, column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME=MASKING_GENERATED_IDENTITY_TMP;

JOB XML Example

SQL Statements

Create IDENTITY (MS SQL Server)

The create statement is defined in the following Job XML file:

KETTLE_CREATE_IDENTITY_TRANSFORMATION_[job_id].xml

The create statement looks like this (example):

IF NOT EXISTS (
  SELECT 1 
  FROM INFORMATION_SCHEMA.COLUMNS  
  WHERE 
    TABLE_SCHEMA = 'dbo' AND 
    TABLE_NAME = 'tbl_mask' AND 
    COLUMN_NAME = MASKING_GENERATED_IDENTITY_TMP)
BEGIN
   ALTER TABLE [Test].[dbo].[tbl_mask] ADD &quot;MASKING_GENERATED_IDENTITY_TMP&quot; INT IDENTITY(1,1)
END;


IF NOT EXISTS (
  SELECT 1 
  FROM sys.indexes i, sys.index_columns ic, sys.columns c, sys.tables t, sys.schemas s
  WHERE
    i.object_id = ic.object_id AND
    i.index_id = ic.index_id AND
    ic.object_id = c.object_id AND
    ic.column_id = c.column_id AND
    i.object_id = t.object_id AND
    t.schema_id = s.schema_id AND
    s.name = 'dbo' AND
    t.name = 'tbl_mask' AND
    c.name = MASKING_GENERATED_IDENTITY_TMP  AND
    i.name = i_MASKING_GENERATED_IDENTITY_TMP)
BEGIN
   CREATE INDEX i_MASKING_GENERATED_IDENTITY_TMP ON [Test].[dbo].[tbl_mask] (&quot;MASKING_GENERATED_IDENTITY_TMP&quot;)
END;

Drop IDENTITY (MS SQL Server)

The drop statement is defined in the following Job XML file:

KETTLE_DROP_IDENTITY_TRANSFORMATION_[job_id].xml

The create statement looks like this (example):

IF EXISTS (
  SELECT 1 
  FROM sys.indexes i, sys.index_columns ic, sys.columns c, sys.tables t, sys.schemas s
  WHERE
    i.object_id = ic.object_id AND
    i.index_id = ic.index_id AND
    ic.object_id = c.object_id AND
    ic.column_id = c.column_id AND
    i.object_id = t.object_id AND
    t.schema_id = s.schema_id AND
    s.name = 'dbo' AND
    t.name = 'tbl_mask' AND
    c.name = MASKING_GENERATED_IDENTITY_TMP  AND
    i.name = i_MASKING_GENERATED_IDENTITY_TMP)
BEGIN
    DROP INDEX i_MASKING_GENERATED_IDENTITY_TMP on  [Test].[dbo].[tbl_mask]
END;


IF EXISTS (
  SELECT 1 
  FROM INFORMATION_SCHEMA.COLUMNS  
  WHERE 
    TABLE_SCHEMA = 'dbo' AND 
    TABLE_NAME = 'tbl_mask' AND 
    COLUMN_NAME = MASKING_GENERATED_IDENTITY_TMP)
BEGIN
   ALTER TABLE [Test].[dbo].[tbl_mask] DROP COLUMN  [MASKING_GENERATED_IDENTITY_TMP]
END;

Troubleshooting

To troubleshoot issues with MGIT and its index i_MGIT please use this knowledge article.

 

If there is an error there should also be an error from the database detailing to root cause.

 

Examples of self-help commands are listed below:

Linux/Unix

Finding errors in INFO.log for specific JOB 

This limits the search for errors to a specific job and execution (change xx and yy to the job and execution as required). 

grep -E "E=1|Caused by|Job with execution.*submitted|Unable to load the job|Couldn't execute|Failed|updating batch|for job|Masking Engine|MASKING_GENERATED" info.log | grep "JOB_ID_xx_yy"

Windows PowerShell 

Finding errors in INFO.log for specific JOB 

This limits the search for errors to a specific job and execution (change xx and yy to the job and execution as required). 

Select-String "E=1|ORA-|Caused by|Job with execution.*submitted|Unable to load the job|Couldn't execute|Failed|updating batch|for job|Masking Engine|MASKING_GENERATED" info.log | Select-String "JOB_ID_xx_yy"

 

 

Related Articles

The following articles may provide more information or related information to this article: