达梦数据库报“网络通信异常”分析解决
前言:
达梦数据库在通过程序插入具有BLOB字段的记录时(非通过SQL直接插入),报“通信异常”,通过更换达梦库驱动包解决。
问题:
在一个项目现场,在进行数据导入时,总时报“网络通信异常”:
19:08:56 ERROR - Application exception overridden by rollback exception org.springframework.dao.DataAccessResourceFailureException: PreparedStatementCallback; SQL [INSERT INTO SCHEMA1.A(ID,REV,NAME,DEPLOYMENT_ID,BYTES,GENERATED) VALUES (?,?,?,?,?,?)]; 网络通信异常; nested exception is java.sql.SQLException: 网络通信异常 at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:105) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:649) at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:870) at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:894) ...
分析解决:
1、试验一:参照网上针对“通信异常”的处理,未能解决问题
网上针对“通信异常”的处理,较多的解决方案是在数据源的配置中增加连接探测参数,但经过测试,发现并不管用:
testOnBorrow: true #是否打开获取连接前探测连接是否可用 validationQuery: select 1 from dual #测试连接的sql testWhileIdle: true
而且该问题能稳定重现,考虑倒是不是网络或数据库的问题,但该机器上同时部署有其他的应用,且都连接的同一数据库,其他应用工作正常。怀疑数据库是不是有什么问题,在一定条件下触发了“通信异常”,决定让现场替换数据库再试。
2、试验二:通过替换数据库,发现问题消除
将达梦7换为达梦6,问题消除。 说明数据库层面可能存在问题,一个数据库有问题,一个没有问题。于是决定寻找数据库层面的差异,考虑到是插入某个表时报异常,决定重点比较2个库中的同一名称的表是否有不同。
--DM6 CREATE TABLE "A_DB"."SCHEMA1"."A"( "ID" VARCHAR(64), "REV" INTEGER, "NAME" VARCHAR(255), "DEPLOYMENT_ID" VARCHAR(64), "BYTES" BLOB(2147483647), "GENERATED" NUMBER(20,0), PRIMARY KEY("ID"), CONSTRAINT "A_DEPL" FOREIGN KEY("DEPLOYMENT_ID") REFERENCES "B"("ID")) STORAGE( INITIAL 1 , NEXT 1 , MINEXTENTS 1 , on "PRIMARY", FILLFACTOR 0 ) ; --DM7 CREATE TABLE "SCHEMA1"."A" ( "ID" VARCHAR2(64), "REV" INTEGER, "NAME" VARCHAR2(255), "DEPLOYMENT_ID" VARCHAR2(64), "BYTES" BLOB, "GENERATED" NUMBER, CONSTRAINT "A_DEPL" FOREIGN KEY("ID") REFERENCES "SCHEMA1"."B"("ID")) STORAGE(ON "SCHEMA1", CLUSTERBTR) ; COMMENT ON COLUMN "SCHEMA1"."A"."BYTES" IS 字节流; COMMENT ON COLUMN "SCHEMA1"."A"."DEPLOYMENT_ID" IS 流程部署ID; COMMENT ON COLUMN "SCHEMA1"."A"."GENERATED" IS 是否引擎生成; COMMENT ON COLUMN "SCHEMA1"."A"."ID" IS 唯一标识; COMMENT ON COLUMN "SCHEMA1"."PT_WF_GE_BYTEARRAY"."NAME" IS 名称; COMMENT ON COLUMN "SCHEMA1"."PT_WF_GE_BYTEARRAY"."REV" IS 版本修订;
通过比较2个表的SQL,发现一个库中的表错误地使用主键ID字段作为外键,与另一表进行关联,那么A表的插入必然依赖于B表,若B表无此ID,则A表插入将因违反约束而失败。
但修改后问题依旧。
3、试验三:使用单独的SQL插入数据库
INSERT INTO SCHEMA1.A(ID,REV,NAME,DEPLOYMENT_ID,BYTES,GENERATED) VALUES (TEST001,1,测试,dep001,0x0000FFFF0A000110,0);
可以成功。
4、试验四:更换数据库驱动包
将应用包中达梦的数据库驱动包更换为最新版本,问题解决。推测,现有的驱动包可能存在什么缺陷,在处理含BLOB字段记录的插入时可能存在处理不足。有点遗憾的是,因为JDBC包较为复杂,没有足够的时间去找到真正的问题点。