即使数据来自 Ehcache,c3p0 也总是调用提交

c3p0 is always calling commit even if data is coming from Ehcache

我有一个 Web 服务,它进行只读调用(一堆 select 查询)以从数据库获取数据。但它只是第一次调用数据库,之后所有涉及的实体都使用Ehcache缓存在hibernate二级缓存中。问题是即使我的请求没有进行任何数据库调用来获取数据,应用程序总是对数据库进行提交调用,这会影响我的 Web 服务响应时间。

我的 Web 服务响应时间是 90 毫秒,其中提交调用始终占 35 毫秒 (40%)。数据源配置为 spring bean with data source class com.mchange.v2.c3p0.ComboPooledDataSource 如下所示。

每次调用 web 服务时,它都会对数据库进行提交调用,我可以在从 appdynamics 获取的调用图中看到它。请求中涉及的所有条目的缓存命中率为 100%。

<bean id="catalogReadDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
    <!-- jdbc properties -->
    <property name="jdbcUrl"
        value="XXXXXXXXXXXX" />
    <property name="user" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />

    <!-- c3P0 properties -->
    <property name="acquireIncrement" value="${c3p0.acquireIncrement}" />
    <property name="minPoolSize" value="${c3p0.minPoolSize}" />
    <property name="maxPoolSize" value="${c3p0.maxPoolSize}" />
    <property name="maxStatements" value="${c3p0.maxStatements}" />
    <property name="maxIdleTime" value="${c3p0.maxIdleTime}" />
    <property name="preferredTestQuery" value="${c3p0.preferredTestQuery}" />
    <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}" />
    <property name="testConnectionOnCheckin" value="${c3p0.testConnectionOnCheckin}" />
    <property name="unreturnedConnectionTimeout" value="${c3p0.unreturnedConnectionTimeout}" />
    <property name="checkoutTimeout" value="${c3p0.checkoutTimeout}" />

    <!-- The below property is not set because we have feeds which require 
        a lot of connections. Resetting the connectionPool size to minPoolSize might 
        not be ideal. Instead we'd use maxIdleTime and maxConnectionAge return unused 
        connections. -->
    <!-- <property name="maxIdleTimeExcessConnections" value="${c3p0.maxIdleTimeExcessConnections}" 
        /> -->

    <!-- The below parameters can be set to prevent connection leaks. Ideally, 
        the application should close all connections, in which case they'll be returned 
        to the pool. -->
    <!-- <property name="unreturnedConnectionTimeout" value="unreturnedConnectionTimeout" 
        /> -->
    <!-- <property name="debugUnreturnedConnectionStackTraces" value="debugUnreturnedConnectionStackTraces" 
        /> -->
</bean>

这听起来像是您打开一个事务并始终只有在检查缓存内容后才获得数据库连接。

但是由于您打开了事务上下文,它将关闭,发出提交,因为没有发生异常。

您很可能需要将缓存检查移到事务上下文之外。

当然,这个要看你的应用代码没有包含在问题中。

Connection 上的事务划分相关调用仍然会发生。您可以使用 Spring 的 LazyConnectionDataSourceProxy(已记录 here)之类的内容来避免在不需要时发送这些内容。