问题描述
Agile管理员配置一个Gate SubClass(ID为18401)级别的Page Three属性,ID为2490533,业务操作均无问题。偶然的一次重启服务后出现Node (18387 , 2490533) does not exist in the cache.然而并且2490533并不属于18387。本文从错误提示着手分析,到数据库中数据验证,最后到代码查看,提供了一个完整缜密的分析思路。
分析
分析一个问题必须从错误提示的源头来观察。查看整个异常的trace。
10/11/24 02:48:10 com.agile.admin.client.value.AdminException: Node (18387 , 2490533) does not exist in the cache.
10/11/24 02:48:10 at com.agile.admin.server.ADictionary.getNodeByObjID(ADictionary.java:281)
10/11/24 02:48:10 at com.agile.admin.server.ADTableInfo.addAtt(ADTableInfo.java:30)
10/11/24 02:48:10 at com.agile.admin.server.ADInitLoad.loadTableInfo(ADInitLoad.java:1222)
10/11/24 02:48:10 at com.agile.admin.server.ADInitLoad.startAdmin(ADInitLoad.java:321)
10/11/24 02:48:10 at com.agile.ui.pcm.InitServlet.init(InitServlet.java:61)
10/11/24 02:48:10 at com.evermind.server.http.HttpApplication.loadServlet(HttpApplication.java:2379)
10/11/24 02:48:10 at com.evermind.server.http.HttpApplication.findServlet(HttpApplication.java:4830)
10/11/24 02:48:10 at com.evermind.server.http.HttpApplication.findServlet(HttpApplication.java:4754)
10/11/24 02:48:10 at com.evermind.server.http.HttpApplication.initPreloadServlets(HttpApplication.java:4942)
10/11/24 02:48:10 at com.evermind.server.http.HttpApplication.initDynamic(HttpApplication.java:1144)
10/11/24 02:48:10 at com.evermind.server.http.HttpApplication.(HttpApplication.java:741)
10/11/24 02:48:10 at com.evermind.server.ApplicationStateRunning.getHttpApplication(ApplicationStateRunning.java:431)
10/11/24 02:48:10 at com.evermind.server.Application.getHttpApplication(Application.java:586)
10/11/24 02:48:10 at com.evermind.server.http.HttpSite$HttpApplicationRunTimeReference.createHttp
ApplicationFromReference(HttpSite.java:1987)
10/11/24 02:48:10 at com.evermind.server.http.HttpSite$HttpApplicationRunTimeReference.(HttpSite.java:1906)
10/11/24 02:48:10 at com.evermind.server.http.HttpSite.initApplications(HttpSite.java:643)
10/11/24 02:48:10 at com.evermind.server.http.HttpSite.setConfig(HttpSite.java:290)
10/11/24 02:48:10 at com.evermind.server.http.HttpServer.setSites(HttpServer.java:270)
10/11/24 02:48:10 at com.evermind.server.http.HttpServer.setConfig(HttpServer.java:177)
10/11/24 02:48:10 at com.evermind.server.ApplicationServer.initializeHttp(ApplicationServer.java:2493)
10/11/24 02:48:10 at com.evermind.server.ApplicationServer.setConfig(ApplicationServer.java:1042)
10/11/24 02:48:10 at com.evermind.server.ApplicationServerLauncher.run(ApplicationServerLauncher.java:131)
10/11/24 02:48:10 at java.lang.Thread.run(Thread.java:595)
很明显,Agile在启动之际其中一个过程是要Load整个Agile系统的所有table信息,在解析其中一个attribute的时候,Class-Attr或者Subclass-Attr的对,并不存在,至少在Cache中丢失。因此我们去查看Tableinfo这个表。

注意到2490533的attribute属于18401的class/subclass。至于是class还是subclass这里我们暂时不用去关心。那为什么错误中出现的为(18387 , 2490533)而不是(18401 , 2490533)呢。需要再次去验证2490533的归属。查看Nodetable
在往上一层,由attribute >> attributes >> class/subclass
很明显地可以看出attribute为2490533的从属于class/subclass为18401的一个属性,至于是Page One还是Two还是Three,读者可以根据Inherit的值自行判断。
到目前为止,分析已经很明确,这个错误(18387 , 2490533)有点不可思议,或者说,这个错误本身也是错误的。现在只能从代码着手分析,反编译AdInitLoad.class,找出load tableinfo的SQL (需要指出一点,AdInitLoad处于调用类的外层,却直接当成Dao层去访问SQL,有些不伦不类)
SELECT TABID, TABLEID, CLASSID, ATT, ORDERING, WIDTH, LANGID
FROM TABLEINFO ORDER BY TABID, TABLEID, CLASSID, LANGID;
再找出一段代码。比较这个SQL和下面的代码,相信你能看出问题所在。
//记录集循环开始
if (prevTabID != tabID || prevTableID != tableID) {
tableInfo = new ADTableInfo(tableID, classID);
ADTabNode.addTableInfo(tabID, tableInfo);
prevTabID = tabID;
prevTableID = tableID;
}
tableInfo.addAtt(attID, ordering, width, langID);
//记录集循环结束
SQL排序TABID, TABLEID, CLASSID(忽略LANGID,语言标识在TableInfo中是个冗余字段),但是在Java代码中创建一个新的tableInfo类型的依据是只比较了当前和前一次的tabID和tableID。ClassID被无故丢弃了。因此18387一定是出现在18401之前的一个class/subclass。运行上述SQL查看classID的先后顺序,即可验证。
解决方法
由于这个错误在9.2.2.7版本之前一直存在,直到9.3才被解决,因此暂时没有一个可行的workaround,只能升级。
经验总结
在故障诊断领域,有很多人思想不够开放,碰到一个问题,思路僵化,仅仅停留在错误本身,而没有很好地琢磨错误的深层次来源。更多时候,要对现象提出质疑:这个错误提示会不会本身就是错误的?