On data dictionary synchronization errors:show which table is error

本文详细介绍了Dynamics AX中数据字典同步的工作原理、常见失败场景及其解决方法,并提供了一段用于诊断同步错误的x++代码示例。

 

On data dictionary synchronization errors
 
Today, I'll describe some of the more common causes of Data Dictionary Synchronization failures, how to diagnose them and how to fix them. Most of this post should be applicable from Ax 2.5 all the way up to DAX 5.0.
 
Dictionary overview
 
Every object related to the SQL Database (tables, table fields, table indexes) is identified by 'name' in the Database, but identified by a 'unique id' in Dynamics Ax. This unique id is kept in code, in its respective layer file (*.aod). This unique id is a constant; SalesTable for example has had the table id '366' since forever. The object id found in the layer is matched with the Database object name through a table called 'SQLDictionary'. This table maps DAX table ids to SQL table names, and DAX field ids to SQL field names. This means that in theory and practice, a field could have a certain name under DAX, and a different name under the SQL Databse; this happens for example when the object name under the DAX AOT is longer than 30 characters.
 
During synchronization of the dictionnary under the DAX AOT, DAX looks through the SQLDictionary table and verifies that all tables and fields can be found, that they have the proper id and that the corresponding SQL object exists with the proper name and proper type.
 
Possible scenarios at synchronization 
  1. An object (table or field) exists on the SQL Database, exists on a DAX layer and is properly mapped in the SQLDictionary table: DAX is properly aware of this object and nothing will occur at synchronization.
  2. An object (table or field) exists on the SQL Database, but not on any DAX layer nor in the SQLDictionary table: DAX is not aware of this object and nothing will occur at synchronization.
  3. An object (table or field) exists in the AOT and cannot be found in the SQLDictionary table: DAX will attempt to create the object in the SQL Database and insert a corresponding cross-reference record in SQLDictionary. Since DAX is not aware of the Database contents beyond the information contained in SQLDictionary a synchronization error will occur if an object of the same name already exists in the Database.
  4. An object (table or field) exists in the AOT, can be found in the SQLDictionary table, but doesn't exist in the SQL Database: DAX will attempt to create the object in the SQL Database and update the corresponding cross-reference record in SQLDictionary.
  5. A field exists in the AOT (suppose an Int64) and can be found in the SQLDictionary table (as an Int) as well as in the Database: A synchronization error will occur.
  6. An object (table or field) exists in the AOT, can be found in the SQLDictionary table but with a different id, as well as in the Database (happens when a object was moved between layers and restoring a prior database): DAX wil attempt to recreate the object in the Database and will fail with a synchronization error. The original may be dropped.
  7. An index exists in the AOT, but not in the SQL Database: DAX will attempt to introduce this new index to the table in the database. If the index is unique and records are seen as duplicates against it, a synchronization error will occur.

 

Diagnosing synchronization errors
 
Sometimes, DAX will fail to synchronize a table and give you an error message that does not identify the problematic table. This x++ job will help you determine where the cause of the error is:
 
public static void manualSync(Args _args)
{
    #define.unknown("UNKNOWN")
    #define.tableIdMax(65536)
    int i = 1;
    ;
    while (i < #tableIdMax)
    {
        if (tableid2name(i) != #unknown)
        {
            print(tableid2name(i));
            try
            {
                if (!appl.dbSynchronize(i, false, true))
                    throw Exception::Error;
            }
            catch
            {
                error(tableid2name(i));
            }
        }
        i++;
    }
}
 
When ids don't match...
 
Generally you will have table id and field id mismatches upon re-attaching a database when objects where moved across different layers. The reason for this is that of the 65 536 available tables ids, ids [0, 10 000] are reserved for SYS, ids [20 000, 30 000] are reserved for BUS, ids [40 000, 50 000] are reserved for CUS, etc; with no overlap between the grops of ids (I may be slightly off, this is from memory).
 
While migrating a customer from Ax 2.5 to Ax 4.0, they revised they're customization strategy to bring mods onto the CUS layer, when originally they were on the USR layer. We didn't want to spend hours importing data using the data import-export tool, so I ran jobs to fix the SQLDictionary table (you would also need to fix the data in any RefTableId field). This was the basic idea:
 
( NEVER RUN THIS CODE IN A PRODUCTION ENVIRONMENT)
 
/*
 *  Warning, this code does not work 'as-is', it is only given as example
 *  This will completely destroy an environment if run 'as-is'!
 */
public static void fixSQLDictionary(Args _args)
{
    SQLDictionary sqlDictionary;
    #Define.CUSLAYERSTART(40000)
    #Define.USRLAYEREND  (60000)
    boolean validate()
    {
        if(sqlDictionary.FieldId == 0 && sqlDictionary.Name != tableid2name(sqlDictionary.TabId))
        {
            return false;
        }
        else if(sqlDictionary.FieldId != 0
            && sqlDictionary.Name != fieldid2name(sqlDictionary.TabId, sqlDictionary.FieldId))
        {
            return false;
        }
        return true;
    }
    ;
    try
    {
        ttsbegin;
        //FIX CUSTOM TABLES AND THEIR FIELDS
        while select forupdate sqlDictionary
            where sqlDictionary.TabId >= #CUSLAYERSTART
                && sqlDictionary.TabId < #USRLAYEREND
        {
            sqlDictionary.TabId = tablename2id(sqlDictionary.Name);
            if (sqlDictionary.orig().FieldId != 0)
                sqlDictionary.FieldId = fieldname2id(sqlDictionary.TabId, sqlDictionary.Name);
            if (!validate())
            {
                //TODO: Need to deal with DEL_* objects and objects with names > 30 chars
                continue;
            }
            //TODO: Uncomment
            //sqlDictionary.doUpdate();
        }
        //FIX CUSTOM FIELDS ON STD TABLES
        while select forupdate sqlDictionary
            where (sqlDictionary.FieldId >= #CUSLAYERSTART
                    && sqlDictionary.FieldId < #USRLAYEREND)
                && (sqlDictionary.Tabid < #CUSLAYERSTART)
        {
            sqlDictionary.FieldId = fieldname2id(sqlDictionary.TabId, sqlDictionary.Name);
            if(!validate())
            {
                //TODO: Need to deal with DEL_* objects and objects with names > 30 chars
                continue;
            }
           
            //TODO: Uncomment
            //sqlDictionary.doUpdate();
        }
        ttscommit;
    }
    catch
    {
        throw error("Aborted");
    }
}

 

### Oracle Clusterware 集群服务已经在线但出现警告 [INS-35423] 或 CRS 状态检查异常的处理方法 在 Oracle RAC 安装或集群管理过程中,即使 Oracle Clusterware 服务已经在线,也可能出现类似 `[INS-35423] The installer has detected that Oracle Clusterware is not running on local node` 的警告。这类问题通常与集群状态检测、OCR 设备访问权限、网络配置或安装程序缓存有关。 #### 1. 检查 Oracle Clusterware 是否正常运行 尽管服务看似在线,但安装程序可能因无法访问 OCR 设备或表决磁盘而误判集群状态。可以通过以下命令检查 CRS 状态: ```bash crsctl check crs ``` 输出应显示 CRS、CSS 和 EVM 三个组件均为“active”状态。若其中任意一项为 inactive,需手动启动: ```bash crsctl start crs ``` 如果启动失败并提示 `CRS-0804` 或 `PROC-26: Error while accessing the physical storage Storage layer error [Insufficient quorum to open OCR devices]`,则表明 OCR 设备无法访问或表决磁盘未满足仲裁条件,需检查 ASM 磁盘组状态和 OCR 配置 [^1]。 #### 2. 检查 OCR 设备状态 OCR 是 Oracle Clusterware 的核心配置数据库。即使服务在线,若 OCR 设备无法访问,安装程序仍可能报错。使用以下命令检查 OCR 状态: ```bash ocrcheck ``` 若 OCR 状态为“not healthy”或提示无法访问 OCR 设备,则需检查 ASM 磁盘组是否在线,并确认 OCR 文件所在的磁盘组已正确挂载。若 OCR 文件损坏,可尝试从备份恢复: ```bash ocrconfig -restore <backup_file> ``` 恢复后,重启 Clusterware 服务以确保配置生效 [^1]。 #### 3. 检查集群节点列表是否可访问 在安装 Oracle Database 软件时,若集群列表为空并报 `INS-35423` 错误,可能是由于安装程序无法从 OCR 获取节点信息。此时需确保 OCR 服务正常,并以 root 用户身份运行以下命令重启 Clusterware: ```bash /u01/app/11.2.0/grid/bin/crsctl start crs ``` 重启后重新运行安装程序,应能正常识别集群节点 [^2]。 #### 4. 检查网络配置与节点通信 Oracle Clusterware 依赖于节点间的私有网络通信。若网络配置错误,可能导致安装程序无法识别集群状态。使用以下命令检查网络接口配置: ```bash oifcfg getif ``` 确保所有节点的私有网络接口已正确分配 `cluster_interconnect` 角色,并验证节点间通信是否正常。若使用 `/etc/hosts` 文件进行解析,需确保所有节点的主机名与 IP 地址映射一致;若使用 DNS,需确保解析无误 [^4]。 #### 5. 清理并重新初始化 Clusterware(如必要) 若上述方法无效,可能需要清理 Clusterware 配置并重新初始化。执行以下命令: ```bash crsctl stop crs crsctl deconfig crs -f ``` 然后重新配置 OCR 和表决磁盘,并重新启动 Clusterware 服务。确保在重新安装前,所有节点上的 ASM 磁盘组可用,且 OCR 文件路径正确 [^1]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值