`
Willam2004
  • 浏览: 87877 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java.sql.SQLException: 违反协议异常的一种解释

    博客分类:
  • Java
阅读更多
一次做应用升级出现了一个问题,描述如下:
   升级分为两块,一块是数据库结构变更(表结构增加新字段);一块是应用程序的升级。
   应用环境为:jboss4.0.5 + ibatis + spring 数据源在jboss的oracle-ds.xml文件中进行配置,通过spring的jndi方式进行查找 。
   我先将数据库进行升级,更改表结构(增加字段),因为应用中的ibatis的查询采用的是ResultMap返回方式,返回定义的表结构字段,即使数据库发生变更,也不会产生影响。于是我大胆的进行脚本的执行。结果当我下午16:00数据库变更之后,几乎在同时就有人反应应用的一些查询功能无法使用,立刻查看出错日志:
   Caused by: com.alibaba.generalorm.dao.DataAccessException: Data query error!   
--- The error occurred in sqlmap/CiaDissension.xml.  
--- The error occurred while applying a parameter map.  
--- Check the QUERY_ALL_DISSENSION_CATEGORY-InlineParameterMap.  
--- Check the statement (query failed).  
--- Cause: java.sql.SQLException: OALL8 处于不一致状态
	at com.alibaba.ibatis.BasicIBatisDao.query(BasicIBatisDao.java:315)
	at com.alibaba.china.rcc.riskdc.dao.DissensionCategoryDAO.getAll(DissensionCategoryDAO.java:40)
	at com.alibaba.china.rcc.riskdc.service.impl.DissensionServiceImpl.getCategoryMap(DissensionServiceImpl.java:495)
	at com.alibaba.china.rcc.riskdc.service.impl.DissensionServiceImpl.getCategory(DissensionServiceImpl.java:188)
	at com.alibaba.china.rcc.riskdc.web.action.DissensionAction.getCategory(DissensionAction.java:263)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.alibaba.webx.action.invoker.AbstractModuleMethodInvoker.executeNoArgMethod(AbstractModuleMethodInvoker.java:401)
	... 33 more

   Caused by: com.alibaba.generalorm.dao.DataAccessException: Data query error!   
--- The error occurred in sqlmap/CiaDissension.xml.  
--- The error occurred while applying a parameter map.  
--- Check the QUERY_ALL_DISSENSION_BUSINESS-InlineParameterMap.  
--- Check the statement (query failed).  
--- Cause: java.sql.SQLException: 违反协议
	at com.alibaba.ibatis.BasicIBatisDao.query(BasicIBatisDao.java:315)
	at com.alibaba.china.rcc.riskdc.dao.DissensionBusinessDAO.getAll(DissensionBusinessDAO.java:19)
	at com.alibaba.china.rcc.riskdc.service.impl.DissensionServiceImpl.getBusiness(DissensionServiceImpl.java:178)
	at com.alibaba.china.rcc.riskdc.web.action.DissensionAction.getBusiness(DissensionAction.java:249)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.alibaba.webx.action.invoker.AbstractModuleMethodInvoker.executeNoArgMethod(AbstractModuleMethodInvoker.java:401)
	... 33 more

为什么会出现违反协议的问题?马上google一下,有些人说是因为数据库的字段类型与java中使用的类型不一致导致,但查看了ibtais的map文件,老的应用代码根本还没有使用新的的字段!后来找pla共同排查,也没有发现应用程序哪里会出现问题,便打电话给DBA让他查下数据库,DBA咨询了一位资格较老的DBA,他说以前也出现过这种情况,只要将应用重启下,就好了。马上重启,果然问题解决了,违反协议的错误没有再报。

查找原因:
在做升级前,我自己在开发环境也做过模拟,并没有出现如果应用不重启,数据库变更而报“违反协议”的错误。而我看了下发布环境与开发环境差异,唯一的差异是开发环境没有采用jboss+jndi的方式获取数据源,而采用了tomcat+c3p0的方式获取数据源。

于是我开始实验。
Tomcat+C3P0启动方式:
1.准备好更改数据库脚本。
2.在开发环境用tomcat启动应用,并访问到涉及表结构变更的页面。
3.执行数据库脚本,确保表结构发生了变更。
4.刷新在步骤2的页面,查看后台输出和前台页面输出。
5.一切正常,没有抛出违反协议或处于不一致状态的错误日志。
JBoss4.0.5+JNDI启动方式
1.准备好更改数据库脚本。
2.在开发环境用jboss启动应用,并访问到涉及表结构变更的页面。
3.执行数据库脚本,确保表结构发生了变更。
4.刷新在步骤2的页面,查看后台输出和前台页面输出。
5.出现了违反协议和处于不一致状态的问题。

总结:

由此可以看出,出现这个问题与ibatis没有关系,而与数据源的获取方式有关,一种是通过Spring+c3p0直接注入DataSource;一种是在oracle-ds.xml文件中配置,然后在spring中通过jndi的方式进行查找,获取数据源。第二种在数据库变更的情况下,就必须进行应用重启,否则就会抛出违反协议或处于不一致的状态。

但根本原因到底是什么呢?我还在寻找。
===================================================
咨询了大少,并不是因为数据源配置模式没有关系,用c3p0或者jndi等,而是与数据源的配置方式有关:

在oracle-ds的配置如下:
   <local-tx-datasource>
        <jndi-name>rccBopsDataSource</jndi-name>
        <use-java-context>false</use-java-context>
        <connection-url>jdbc:oracle:thin:@xx.xx.xx.xx:1521:xx</connection-url>
        <connection-property name="SetBigStringTryClob">true</connection-property>
        <connection-property name="defaultRowPrefetch">50</connection-property>
        <connection-property name="clientEncoding">GBK</connection-property>
        <connection-property name="serverEncoding">ISO-8859-1</connection-property>
        <driver-class>com.alibaba.china.jdbc.SimpleDriver</driver-class>
        <min-pool-size>1</min-pool-size>
        <max-pool-size>14</max-pool-size>
        <prepared-statement-cache-size>20</prepared-statement-cache-size>
        <metadata>
            <type-mapping>Oracle9i</type-mapping>
        </metadata>
        <idle-timeout-minutes>15</idle-timeout-minutes>
        <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
        <user-name>xx</user-name>
        <password>xx</password>
    </local-tx-datasource>


其中prepared-statement-cache-size参数解释为:
<prepared-statement-cache-size> - the number of prepared statements per connection to be kept open and reused in subsequent requests. They are stored in a LRU cache. The default is 0 (zero), meaning no cache.
为每个打开的数据库连接缓存了一定数量的prepared statement.他们是存在LRU cache中,如果设值为0,那么将不缓冲。这里我们设值了每个连接缓存20条prepared statment。

而在c3p0的配置中:
   <bean id="testDataSource"
		class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
		<property name="staticMethod">
			<value>com.mchange.v2.c3p0.DataSources.pooledDataSource</value>
		</property>
		<property name="arguments">
			<list>
				<ref local="unpooledDataSource" />
				<props>
					<prop key="acquireIncrement">1</prop>
					<prop key="initialPoolSize">1</prop>
					<prop key="minPoolSize">1</prop>
					<prop key="maxPoolSize">5</prop>
					<prop key="maxIdleTime">1800</prop>					
					<prop key="maxIdleTimeExcessConnections">1000</prop>
					<!-- 自动收缩连接用的,单位秒 -->
					<!-- 自动重连需要的三个参数 -->
					<prop key="acquireRetryAttempts">30</prop>
					<prop key="acquireRetryDelay">1000</prop>
					<prop key="breakAfterAcquireFailure">false</prop>
					<!-- 获取一个connection需要的时间,单位毫秒 -->
					<prop key="checkoutTimeout">5000</prop>
				</props>
			</list>
		</property>
	</bean>

上网查了下,影响到preparedStatment cache的参数有两个:maxStatements和maxStatementsPerConnection 如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭,默认为0。

继续实验:

1、将c3p0配置增加maxStatements和maxStatementsPerConnection并都设值20。
修改数据库表结构,刷新访问页面。
后台抛出违反协议和处于不一致状态的错误提示。

2.将oracle-ds.xml文件配置更改prepared-statement-cache-size为0。
修改数据库表结构,刷新访问页面。
后台没有抛出违反协议和处于不一致状态的错误提示。

附参考文章:

http://community.jboss.org/wiki/configdatasources   讲解jboss中关于datasource的参数
http://msq.iteye.com/blog/60387   讲解c3p0的详细参数


分享到:
评论
9 楼 Java_KAbanban 2011-06-14  
恩,很不错的文章,受益不少!!
8 楼 zk7019311 2011-06-13  
学习了不少知识。。。
7 楼 daringwalker 2011-06-13  
<p>我想应该可以清除<span style="font-family: arial; font-size: 13px;">Statement Pool ,不过没仔细研究过连接池的接口,楼主研究过么?</span></p>
6 楼 mvpwar 2011-02-16  
研究得太深了吧,不错!
5 楼 agapple 2011-02-14  
stone2083 写道
研究得够深入的。不错。
记得很早之前,就遇到过这样的问题。
ps cached确实存在一定的使用风险。
并且,我还有一个疑问,在我们这样杂和的应用中,ps cached,真的有性能提升吗?
楼上上次有做过对应测试吗?


从profile分析上看,理论上有20%的性能提升,也在一个应用上实施过

但在其他的几个应用实施时,会有莫名的close statement cache的错误。网上也有相应的bug报告

查了几天没查到原因,线下做过比较多的稳定性测试也没能重现线上的问题,比较诡异,后来没时间弄了就放弃了。

总之一句话,慎用ps cache!

4 楼 Willam2004 2011-02-10  
biocy 写道
stone2083 写道
研究得够深入的。不错。
记得很早之前,就遇到过这样的问题。
ps cached确实存在一定的使用风险。
并且,我还有一个疑问,在我们这样杂和的应用中,ps cached,真的有性能提升吗?
楼上上次有做过对应测试吗?


同问,我公司的项目还算较小,如果数据库的压力过大的时候,都是做业务的切割,数据库分表。ps cache 是否对性能有提升,我们没做过实验,请楼主给予指点


我没有做过性能上的测试,有时间我会去做下。
3 楼 biocy 2011-02-10  
stone2083 写道
研究得够深入的。不错。
记得很早之前,就遇到过这样的问题。
ps cached确实存在一定的使用风险。
并且,我还有一个疑问,在我们这样杂和的应用中,ps cached,真的有性能提升吗?
楼上上次有做过对应测试吗?


同问,我公司的项目还算较小,如果数据库的压力过大的时候,都是做业务的切割,数据库分表。ps cache 是否对性能有提升,我们没做过实验,请楼主给予指点
2 楼 stone2083 2011-02-10  
研究得够深入的。不错。
记得很早之前,就遇到过这样的问题。
ps cached确实存在一定的使用风险。
并且,我还有一个疑问,在我们这样杂和的应用中,ps cached,真的有性能提升吗?
楼上上次有做过对应测试吗?
1 楼 agapple 2011-02-09  
又是一例使用prepare statement cache的潜在风险,研究的不错

相关推荐

    Caused by: java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row:

    这里提到的问题是关于SQL操作时遇到的一个常见错误:“Caused by: java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row:”,这个异常通常表明试图删除或更新的记录与数据库中...

    Java的异常类

    - **`java.sql.SQLException`**:操作数据库异常。 - **`java.io.IOException`**:输入输出异常。 - **`java.lang.NoSuchMethodException`**:方法未找到异常。 #### 三、总结 异常处理对于编写健壮和可靠的...

    java 异常种类总结【转】.docx

    SQLException 是一种操作数据库异常,指的是在程序中操作数据库时出现的异常,例如连接数据库失败、执行 SQL 语句失败等。 11. 输入输出异常:IOException IOException 是一种输入输出异常,指的是在程序中进行...

    java常见异常总结

    - `java.sql.SQLException`:处理数据库访问时发生的异常。 - `java.lang.NumberFormatException`:解析数字字符串时发生的异常。 - `java.lang.ClassCastException`:当对象实例不能被转换为指定类型时抛出。 对于...

    java所有运行时异常以及错误.

    10. **操作数据库异常:SQLException** - 在进行数据库操作时,如执行SQL语句失败,会抛出此异常。 11. **输入输出异常:IOException** - 处理输入/输出流时,如读写错误、网络中断等,会抛出此异常。 12. **方法未...

    Java常见异常收纳整合

    这种异常通常是由于程序员错误地尝试将一种类型的对象转换为另一种不相关的类型所导致的。 ### 4. 数组负下标异常:`ArrayIndexOutOfBoundsException` 当尝试访问数组中的非法索引时,即索引值小于0或大于等于数组...

    Java开发过程中常见异常

    10. **操作数据库异常:SQLException** - 在进行数据库操作时,如果发生错误,如SQL语法错误、连接问题等,会抛出此异常。 11. **输入输出异常:IOException** - 进行输入/输出操作时,如读写文件、网络通信等,...

    总结了java容易出错的信息 以及错误信息类型

    10. **操作数据库异常:SQLException** - 在进行数据库操作时,如果发生错误,如SQL语法错误、连接问题等,会抛出此异常。 11. **输入输出异常:IOException** - 与输入/输出相关的错误,如读写文件、网络通信等...

    179海关联调服务

    {“code”:“20006”,“message”:“上传失败,入库失败 java.sql.SQLException: ORA-00001: 违反唯一约束条件 (sessionID重复)”,“total”:0,“serviceTime”:1500000000000} 得到这个消息,恭喜你,测试基本成功了...

    SQLException

    `SQLException`是一种专门用于处理SQL执行时发生的错误的异常类。它包含了错误代码、SQL状态码和错误消息等信息,帮助开发者快速定位问题所在。 #### 三、常见SQLException及解决方法 下面我们将针对部分常见的`...

    java 异常总结

    - **定义**:当一个应用试图访问、修改某个类的域(Field)或者调用其方法,但是又违反域或方法的可见性声明,则抛出该异常。 - **示例**:尝试访问私有成员。 ##### 8. **不兼容的类变化错误**:`...

    2021-2022计算机二级等级考试试题及答案No.4760.docx

    12. JDBC异常:在JDBC编程中,通常会遇到`SQLException`,这是处理数据库连接和操作时可能出现的异常。 13. 删除文件恢复:使用Shift键删除的文件可以直接恢复,除非清空了回收站。 14. 快捷方式与程序文件:删除...

    常用java异常大全

    ### 常用Java异常详解 #### 一、概述 在Java编程中,异常处理是一项重要的功能,它有助于开发者在...对于每种异常类型,都应尽可能地了解其触发条件以及如何避免或妥善处理,这对于编写高质量的Java程序至关重要。

    很好的jabc学习笔记

    在进行JDBC编程时,可能会遇到SQLException及其子类异常,例如CommunicationsException(网络通信异常)、DataIntegrityViolationException(数据完整性违反异常)等。因此,我们需要捕获并适当地处理这些异常,以...

    Java演示常见的数据库异常处理情况.rar

    在Java编程中,数据库操作是不可或缺的一部分,而与数据库交互时常常会遇到各种异常。本压缩包"Java演示常见的数据库异常处理情况.rar"提供了一系列的示例,旨在帮助开发者了解和处理这些异常,确保程序的健壮性。...

    java所有运行时异常以及错误.doc

    Java运行时异常与错误是程序执行过程中可能会遇到的问题,这些异常和错误分为两类:异常(Exception)和错误(Error)。异常是程序设计时可以预见和处理的问题,而错误通常是系统级或者不可预见的问题,通常不建议...

    Java异常详解.txt

    根据给定的部分内容,我们可以了解到Java中异常种类繁多,每一种都有其特定的含义和适用场景。下面将对这些异常进行分类整理,并详细介绍其中的关键概念和用法: ##### 运行时异常 - **`ArithmeticException`**:...

    spring mvc 项目错误,和一些配置

    java.sql.SQLException: No suitable driver - **原因**:表示Java环境未能找到合适的数据库驱动。 - **解决办法**: - 确认数据库驱动已添加至项目中。 - 配置正确的数据库连接字符串。 #### 16. Error ...

    java常见异常

    - **`SQLException`**:执行SQL语句时发生错误时抛出。 - **`IOException`**:输入输出操作中发生错误时抛出。 - **`NoSuchMethodException`**:调用不存在的方法时抛出。 理解并妥善处理这些异常对于编写健壮且...

Global site tag (gtag.js) - Google Analytics