1

我目前正在调试一个使用Modeshape存储值的应用程序,并且最近出现了一些随机错误。通过广泛的日志记录和使用P6Spy检查内部调用,我发现了一些东西。

对于上下文,Modeshape 有一个基于节点的内部数据模型,但最终它们被保存在数据库中(在我们的例子中,是一个 Oracle DB)。基本上,一个表 MP_CONFIG_CFGMGMT_REPOSITORY 用于此目的,它包含一个 ID 字段、一个修改日期和一个带有节点内容的 BLOB(编码为二进制 JSON)。

在某些时候,Modeshape 需要编辑一个节点,因此更新 MP_CONFIG_CFGMGMT_REPOSITORY 中的相应记录(通过 ID)更改内容字段。此更新在事务中提交。

在那次提交之后,两个线程(其中一个是更新和提交表的同一线程)对同一条记录进行查询。使用 P6Spy,我可以确认,有时,其中一个查询返回一个内容字段,其中包含提交更新之前的值,而另一个查询返回正确的更新值。这会导致代码中进一步出现问题。

阅读 Modeshape 代码,我发现它使用隔离级别创建连接Connection.TRANSACTION_READ_COMMITTED(并且查询被确认在提交更新后发生),因此它不会是脏读的问题。

数据源是在 JBoss(部署我的应用程序的应用程序服务器)中定义的 JNDI 资源,使用以下配置定义:

<datasource jta="false" jndi-name="java:jboss/nameOfDatasource" pool-name="nameOfDatasource" enabled="true" use-java-context="true" statistics-enabled="true">
    <connection-url>jdbc:oracle:thin:@//db-host:6789/DB_NAME</connection-url>
    <driver>oracle</driver>
    <pool>
        <min-pool-size>100</min-pool-size>
        <max-pool-size>100</max-pool-size>
    </pool>
    <security>
        <user-name>${USERNAME}</user-name>
        <password>${PASSWORD}</password>
    </security>
    <validation>
        <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker"/>
        <validate-on-match>false</validate-on-match>
        <background-validation>true</background-validation>
        <background-validation-millis>30000</background-validation-millis>
        <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter"/>
    </validation>
    <statement>
        <prepared-statement-cache-size>25</prepared-statement-cache-size>
    </statement>
</datasource>
...
<drivers>
    ...
    <driver name="oracle" module="org.jdbc.oracle">
        <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
    </driver>
</drivers>

我的问题是:这种行为的可能原因是什么?可能与 Oracle 本身有关?或者可能是 JBoss 在 Oracle 和应用程序之间进行的中间设置?

Oracle 版本:19c 企业版 Release 19.0.0.0.0

我读过 Oracle 有LOB 缓存选项,但建议仅在“如果您很少访问 LOB 或 LOB 非常大”时避免使用它,这里不是这种情况

4

0 回答 0