ITPub博客

首页 > Linux操作系统 > Linux操作系统 > java.sql.SQLException: OALL8 处于不一致状态

java.sql.SQLException: OALL8 处于不一致状态

原创 Linux操作系统 作者:zhanglei_itput 时间:2011-07-29 15:56:57 0 删除 编辑
转载:http://13594135.iteye.com/blog/904913

一次做应用升级出现了一个问题,描述如下:
   升级分为两块,一块是数据库结构变更(表结构增加新字段);一块是应用程序的升级。
   应用环境为:jboss4.0.5 + ibatis + spring 数据源在jboss的oracle-ds.xml文件中进行配置,通过spring的jndi方式进行查找 。
   我先将数据库进行升级,更改表结构(增加字段),因为应用中的ibatis的查询采用的是ResultMap返回方式,返回定义的表结构字段,即使数据库发生变更,也不会产生影响。于是我大胆的进行脚本的执行。结果当我下午16:00数据库变更之后,几乎在同时就有人反应应用的一些查询功能无法使用,立刻查看出错日志:
Java代码

   1.    Caused by: com.alibaba.generalorm.dao.DataAccessException: Data query error!    
   2. --- The error occurred in sqlmap/CiaDissension.xml.   
   3. --- The error occurred while applying a parameter map.   
   4. --- Check the QUERY_ALL_DISSENSION_CATEGORY-InlineParameterMap.   
   5. --- Check the statement (query failed).   
   6. --- Cause: java.sql.SQLException: OALL8 处于不一致状态 
   7.     at com.alibaba.ibatis.BasicIBatisDao.query(BasicIBatisDao.java:315) 
   8.     at com.alibaba.china.rcc.riskdc.dao.DissensionCategoryDAO.getAll(DissensionCategoryDAO.java:40) 
   9.     at com.alibaba.china.rcc.riskdc.service.impl.DissensionServiceImpl.getCategoryMap(DissensionServiceImpl.java:495) 
  10.     at com.alibaba.china.rcc.riskdc.service.impl.DissensionServiceImpl.getCategory(DissensionServiceImpl.java:188) 
  11.     at com.alibaba.china.rcc.riskdc.web.action.DissensionAction.getCategory(DissensionAction.java:263) 
  12.     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
  13.     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
  14.     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
  15.     at java.lang.reflect.Method.invoke(Method.java:597) 
  16.     at com.alibaba.webx.action.invoker.AbstractModuleMethodInvoker.executeNoArgMethod(AbstractModuleMethodInvoker.java:401) 
  17.     ... 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_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


Java代码

   1.    Caused by: com.alibaba.generalorm.dao.DataAccessException: Data query error!    
   2. --- The error occurred in sqlmap/CiaDissension.xml.   
   3. --- The error occurred while applying a parameter map.   
   4. --- Check the QUERY_ALL_DISSENSION_BUSINESS-InlineParameterMap.   
   5. --- Check the statement (query failed).   
   6. --- Cause: java.sql.SQLException: 违反协议 
   7.     at com.alibaba.ibatis.BasicIBatisDao.query(BasicIBatisDao.java:315) 
   8.     at com.alibaba.china.rcc.riskdc.dao.DissensionBusinessDAO.getAll(DissensionBusinessDAO.java:19) 
   9.     at com.alibaba.china.rcc.riskdc.service.impl.DissensionServiceImpl.getBusiness(DissensionServiceImpl.java:178) 
  10.     at com.alibaba.china.rcc.riskdc.web.action.DissensionAction.getBusiness(DissensionAction.java:249) 
  11.     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
  12.     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
  13.     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
  14.     at java.lang.reflect.Method.invoke(Method.java:597) 
  15.     at com.alibaba.webx.action.invoker.AbstractModuleMethodInvoker.executeNoArgMethod(AbstractModuleMethodInvoker.java:401) 
  16.     ... 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的配置如下:
Java代码

   1.  
   2.      rccBopsDataSource 
   3.      false 
   4.      jdbc:oracle:thin:@xx.xx.xx.xx:1521:xx 
   5.      true 
   6.      50 
   7.      GBK 
   8.      ISO-8859-1 
   9.      com.alibaba.china.jdbc.SimpleDriver 
  10.      1 
  11.      14 
  12.      20 
  13.       
  14.          Oracle9i 
  15.     
 
  16.      15 
  17.      org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter 
  18.      xx 
  19.      xx 
  20. 
 

  
        rccBopsDataSource
        false
        jdbc:oracle:thin:@xx.xx.xx.xx:1521:xx
        true
        50
        GBK
        ISO-8859-1
        com.alibaba.china.jdbc.SimpleDriver
        1
        14
        20
       
            Oracle9i
       

        15
        org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter
        xx
        xx
   




其中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的配置中:
Xml代码

   1.     2. class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
   3.  
   4.     com.mchange.v2.c3p0.DataSources.pooledDataSource 
   5.
 
   6.  
   7.      
   8.          
   9.          
  10.             1 
  11.             1 
  12.             1 
  13.             5 
  14.             1800                  
  15.             1000 
  16.             <!-- 自动收缩连接用的,单位秒 --> 
  17.             <!-- 自动重连需要的三个参数 --> 
  18.             30 
  19.             1000 
  20.             false 
  21.             <!-- 获取一个connection需要的时间,单位毫秒 --> 
  22.             5000 
  23.        
 
  24.    
 
  25.
 
  26. lt;/bean> 

   class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

com.mchange.v2.c3p0.DataSources.pooledDataSource





1
1
1
5
1800
1000
<!-- 自动收缩连接用的,单位秒 -->
<!-- 自动重连需要的三个参数 -->
30
1000
false
<!-- 获取一个connection需要的时间,单位毫秒 -->
5000






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

继续实验:

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

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

附参考文章:

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

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9252210/viewspace-703562/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2009-02-10

  • 博文量
    400
  • 访问量
    1150821