1. 报错背景

tomcat + Oracle + Druid连接池后台报错( java.sql.SQLException: 违反协议),很奇怪的是只有某种特殊情况下才报错,项目其他功能都运转正常,报错信息看最后面代码示例。

2. 可能原因(OALL8-jdbc与Oracle驱动版本不一致

1、jdbc配置出错(驱动配置):oracle.jdbc.OracleDriver

2、oracle驱动版本不对

PLSQL中查看:select * from v$version;

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

PL/SQL Release 11.2.0.4.0 - Production

CORE 11.2.0.4.0 Production

TNS for Linux: Version 11.2.0.4.0 - Production

NLSRTL Version 11.2.0.4.0 - Production

3、可能原因OALL8-jdbc与Oracle驱动版本不一致

之前数据库用的版本是PL/SQL Release 10.2.0.5.0 - Production,后来升级到了PL/SQL Release 11.2.0.4.0 - Production,所以需要将jdbc升级对应版本。JDBC下载链接

pom:

<dependency><groupId>ojdbc</groupId><artifactId>ojdbc</artifactId><!-- <version>6</version> --><version>14-10gR3</version>
</dependency><dependency><groupId>com.oracle</groupId><artifactId>ojdbc6</artifactId><version>11.2.0.4.0</version>
</dependency>

2. 可能原因(网上的一种靠谱的解答)

原文链接

2.1 背景

项目中Oracle使用druid数据库连接池,为了提高访问数据库的效率,开启了PreparedStatement Cache。但是随着项目的运行,也出现了一些问题,在项目运行的过程中,给表添加字段后,会一直出现"ORA-17401:违反协议"异常。应用重启后,不再抛出。

问题描述
在应用持续运行中,给生产库中的某张表添加字段,然后涉及该表查询的地方不断抛出"ORA-17401:违反协议"异常,直到重启引用。

异常描述
"ORA-17401:违反协议"是TTC(Two-Task Common)的一个错误。TTC是oracle通信协议里较为靠上的一层,用于处理客户端与数据库服务器通信时的协议差异,比如转换字符集和数据类型。用以确保Oracle的客户端和服务器在不同的网络交互模式(比如TCP/IP、共享内存)下可以透明地交互。

2.2 问题定位

1. 重启应用异常不再抛出,反应出重新建立数据库链接能够修复该错误;

2. 部分项目使用其他连接池没有此问题,而druid与之最大的差异就是开启了PreparedStatement Cache。PreparedStatement实际上避免了相同SQL语句重复解析和建立游标,同时也复用了相同的数据结构。那么当服务器端的表结构即数据结构发生改变时,很有可能TTC就会无法处理这种改变。而使用普通的Statement时,因为不存在数据结构的复用,所以也就不会出现"违反协议异常"。

所以,根据以上两点,关闭了PreparedStatement Cache后,重复之前错误的流程,不再抛出该异常。

但是选择druid就是为了其PreparedStatement Cache这个特性,然后只能继续找问题,最后查阅代码,发现之前的mapper.xml中,查询都是直接使用的select *,对部分改为select [字段] 后,发现问题不再出现,但是和其他开发人人员沟通后,认为将目前项目所有的查询修改,工作量较大,风险较高,而且同样的查询在每个项目中都有,也不想进行重构,所以,只能用其他的办法来解决。

2.3 最终解决方案

在和其他人员沟通后,只能将修改后的影响降为最低,所以只能通过如下代码,在每次修改表结构后,主动清除每个应用服务器上每个数据库连接的PreparedStatement Cache,以此来尽量避免由用户行为触发异常的出现。

    @Resource(name = "druidDataSource")private DruidDataSource druidDataSource;public void clearDruidStatementCache() {Log.info("DruidDataSource", "清除Druid的Statement Cache Start......");if (druidDataSource != null) {try {druidDataSource.clearStatementCache();} catch (SQLException e) {Log.error("DruidDataSource", "清除Druid的Statement Cache Error", e);}}Log.info("DruidDataSource", "清除Druid的Statement Cache End......");}

2.4 问题的查找过程

最初用的是druid1.0.25版本,根据http://www.oschina.net/news/79452/druid-1-0-27中的信息,在1.0.27版本中,进行了如下修改

根据其中所说,如果执行出错,可以从PSCache中移除,所以将版本换到了1.0.27,但是问题还是依然存在,只好继续查。

根据http://tomcat.apache.org/tomcat-5.5-doc/jndi-datasource-examples-howto#Oracle_8i,_9i_&_10g,注意如下内容

For Oracle 9i onwards you should use oracle.jdbc.OracleDriver rather than oracle.jdbc.driver.OracleDriver as Oracle have stated that oracle.jdbc.driver.OracleDriver is deprecated and support for this driver class will be discontinued in the next major release.

而我们用的是oracle.jdbc.driver.OracleDriver,并不是oracle.jdbc.OracleDriver,但是并不一定要进行修改。

这是因为根据https://github.com/alibaba/druid/issues/1598中所说,在1.0.29版本中已经兼容了两种写法,不过我还是按要求改成了正确的。

以上基本就是整个问题的查找过程,不过最后因为种种原因,暂时只是采取了一种比较不合理的方法来规避,尽量减少用户来触发从而降低体验。

3. 结合自身项目最终问题原因

tomcat 中context.xml配置的驱动为:oracle.jdbc.OracleDriver,而底层类DBpool.java中open方法中却是oracle.jdbc.driver.OracleDriver

druid的PreparedStatement Cache这个特性导致需要

OALL8-jdbc:下载对应版本的jdbc

<dependency>
              <groupId>com.oracle</groupId>
              <artifactId>ojdbc6</artifactId>
              <version>11.2.0.4.0</version>
        </dependency>

4. 问题报错信息

问题报错信息
三月 06, 2019 1:26:54 下午 com.alibaba.druid.pool.DruidDataSource error
严重: discard connection
java.sql.SQLException: 违反协议: [ 0, ]at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:669)at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:249)at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:566)at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:202)at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:45)at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:933)at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1075)at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1718)at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1678)at oracle.jdbc.driver.OracleStatementWrapper.execute(OracleStatementWrapper.java:332)at com.alibaba.druid.filter.FilterChainImpl.statement_execute(FilterChainImpl.java:2600)at com.alibaba.druid.filter.FilterAdapter.statement_execute(FilterAdapter.java:2473)at com.alibaba.druid.filter.FilterEventAdapter.statement_execute(FilterEventAdapter.java:188)at com.alibaba.druid.filter.FilterChainImpl.statement_execute(FilterChainImpl.java:2598)at com.alibaba.druid.proxy.jdbc.StatementProxyImpl.execute(StatementProxyImpl.java:147)at com.alibaba.druid.pool.DruidPooledStatement.execute(DruidPooledStatement.java:558)at com.sinosoft.sysframework.reference.DBManager.preDeal(DBManager.java:238)at com.sinosoft.sysframework.reference.DBManager.open(DBManager.java:220)at com.sinosoft.sysframework.reference.DBManager.open(DBManager.java:193)at com.sinosoft.sysframework.reference.DBManager.open(DBManager.java:174)at com.sinosoft.sysframework.reference.DBManager.open(DBManager.java:161)at com.sinosoft.utiall.dbsvr.DBPrpDcodeCom.findByConditions(DBPrpDcodeCom.java:365)at com.sinosoft.utiall.blsvr.BLPrpDcodeCom.query(BLPrpDcodeCom.java:143)at com.sinosoft.utiall.blsvr.BLPrpDcodeCom.translateCode(BLPrpDcodeCom.java:267)at com.sinosoft.indiv.ci.interfS.ProposalQueryBusinessDecoder.transProfitFG(ProposalQueryBusinessDecoder.java:1583)

声明:本文第二章转载自“雨幕下的稻田”的心得,未经允许请不要以原创名义进行转载,尊重原创。

Druid java.sql.SQLException: 违反协议 / Oracle连接报错生违反协议相关推荐

  1. Druid java.sql.SQLException: connection holder is null

    问题 java.sql.SQLException: connection holder is null 项目使用了Druid,执行过程中出现了这个错误. 解决过程 错误的意思是没有获取到连接,怀疑是同 ...

  2. Oracle Caused by: java.sql.SQLException: sql injection violation, syntax error: syntax error, expect

    参考:https://blog.csdn.net/qq_36326332/article/details/102938147 https://blog.csdn.net/fly_captain/art ...

  3. [转载]“java.sql.SQLException:指定了无效的 Oracle URL”

    原文地址:"java.sql.SQLException:指定了无效的 Oracle URL"作者:康愚 昨天晚上用MyEclipse连接Oracle,出现了" java. ...

  4. Oracle关于java.sql.SQLException常见错误集锦

    最近使用Oracle时老是遇到java.sql.SQLException错误,害得我在网上查得累死累活的,所以一口气查了一下几个常见的,在此列了列.英文是来自官方的,用中文简单翻译了一下,有一些实在不 ...

  5. nslang oracle_解决ojdbc14连接oracle报“java.sql.SQLException: Io 异常: Size Data Unit (SDU) mismatch”异常问题...

    一.前言 通过ojdbc14.jar连接oracle数据库,应用运行期间报出"java.sql.SQLException: Io 异常: Size Data Unit (SDU) misma ...

  6. oracle 异常返回值,oracle - java.sql.SQLException:无效的列类型:调用具有行类型返回值的函数时为1111 - 堆栈内存溢出...

    我在一个名为" MyPackage"的Oracle软件包中有一个函数: FUNCTION MyFunction(name IN VARCHAR2) RETURN MyTable%r ...

  7. java 流已被关闭_mybatis oracle java.sql.SQLException: 流已被关闭问题

    /** * 按照页码取值(从current_page页开始,每页page_size条) * @param key * @param params * @param current_page * @pa ...

  8. oracle插入报错-Caused by: java.sql.SQLException: 无效的列类型: 16

    一.问题截图 如图我们用kettle将SqlServer数据抽取至oracle数据,因两边数据库的字段类型不一致,导致数据同步过去时报Caused by: java.sql.SQLException: ...

  9. ORACLE各种常见java.sql.SQLException归纳

    java.sql.SQLException错误! ORA-00904:     --invalid column name 无效列名 ORA-00942: --table or view does n ...

最新文章

  1. mysqls压力测试怎么用_用 Swagger 测试接口,怎么在请求头中携带 Token?
  2. 前台进程组、后台进程组
  3. CTL_CODE说明
  4. 区分内边距与外边距padding和margin
  5. Java多线程系列--“JUC锁”03之 公平锁(一)
  6. 软件测试为什么需要学习Linux的知识?Linux学到什么程度?-log5
  7. MetaMask发布9.2.0版本 新增支持多个Ledger和Trezor硬件账户
  8. 在linux中,boot与uboot有什么区别?
  9. lua table remove元素的问题
  10. HTML5技术的调研以及贴吧应用总结
  11. 数据的逻辑结构包括那些?
  12. PyTorch 轻松节省显存的小技巧
  13. CTF_EXP01:BugkuCTF 秋名山老司机
  14. Ubuntu16.04配置GPU驱动(GTX1060)+ CUDA9.0 + CUDNN7.0.5
  15. bsearch()快搜函数
  16. Oracle 10g 版本10.2.0.1.0升级到Oracle 10g 10.2.0.3.0过程
  17. 嵌入式软件静态解析工具-CasePlayer2
  18. matlab中frame是什么意思,frame2time结果是什么含义?
  19. C++OO部分知识小结(1)
  20. 并查集的使用,臭虫同性恋问题

热门文章

  1. 免费高清壁纸网站推荐
  2. 天玑9000和高通骁龙870哪个好
  3. 寒江独钓 Windows内核安全编程
  4. SQL 创建、更新、删除表、重命表名
  5. 图片上传(调用微信接口)
  6. iOS 图片捏合放大缩小 点击放大缩小
  7. 【Dubbo】序列化异常—— com.esotericsoftware.kryo.KryoException: Buffer underflow
  8. Oracle RushQL勒索病毒恢复方法
  9. 深信服信锐 技术支持(网络工程师)
  10. 小白新人Python哪些基础知识必学?