达梦数据库报“网络通信异常”分析解决
前言:
达梦数据库在通过程序插入具有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包较为复杂,没有足够的时间去找到真正的问题点。