preferredTestQuery 从不与 c3p0 0.9.5.2 和 Tomcat 7 一起使用

preferredTestQuery never use with c3p0 0.9.5.2 and Tomcat 7

我将 tomcat7 与 c3p0-0.9.5.2 和 postgresql-9.3-1102-jdbc41 一起使用,preferredTestQuery (select 1) 从不使用,仅在产品中使用。

相同的配置在测试环境中工作正常(检查更新查询)。

在产品中有很多对 getTable postgresql 查询的调用。 (> 1000cpm - New Relic 数据)。

 <Resource name="jdbc/database_read_only"
          auth="Container"
          type="com.mchange.v2.c3p0.ComboPooledDataSource"
          description="Ma description"
          jdbcUrl="jdbc:postgresql://hostname:5432/mabase"
          driverClass="org.postgresql.Driver"
          user="monuser"
          password="monpassword"
          initialPoolSize="10"
          minPoolSize="10"
          maxPoolSize="100"
          acquireIncrement="10"
          maxIdleTime="300"
          maxConnectionAge="1800"
          connectionTesterClassName="com.mchange.v2.c3p0.impl.DefaultConnectionTester"
          preferredTestQuery="select 2"
          testConnectionOnCheckout="true"
          testConnectionOnCheckin="false"
          idleConnectionTestPeriod="300"
          maxIdleTimeExcessConnections="60"
          unreturnedConnectionTimeout="10"
          factory="org.apache.naming.factory.BeanFactory"/>

日志看起来不错:

 2016-12-23 15:26:10,138 : Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 10, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> ddsdsdsqd, debugUnreturnedConnectionStackTraces -> false, description -> ma description, driverClass -> org.postgresql.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> mytoken, idleConnectionTestPeriod -> 300, initialPoolSize -> 10, jdbcUrl -> jdbc:postgresql://hostname:5432/monapp, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 1800, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 60, maxPoolSize -> 100, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 10, numHelperThreads -> 3, preferredTestQuery -> select 1, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> true, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]

为什么 c3p0 使用复杂请求而不是 "select 1"?

复杂请求示例:

SELECT * FROM (SELECT n.nspname,c.relname,a.attname,a.atttypid,a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) AS attnotnull,a.atttypmod,a.attlen,row_number() OVER (PARTITION BY a.attrelid ORDER BY a.attnum) AS attnum, pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS adsrc,dsc.description,t.typbasetype,t.typtype FROM pg_catalog.pg_namespace

SELECT NULL AS TABLE_CAT, n.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME,  CASE n.nspname ~ '^pg_' OR n.nspname = 'information_schema'  WHEN true THEN CASE  WHEN n.nspname = 'pg_catalog' OR n.nspname = 'information_schema' THEN CASE c.relkind   WHEN 'r' THEN 'SYSTEM TABLE'   WHEN 'v' THEN 'SYSTEM VIEW'   WHEN 'i' THEN 'SYSTEM INDEX'   ELSE NULL   END  WHEN n.nspname = 'pg_toast' THEN CASE c.relkind   WHEN 'r' THEN 'SYSTEM TOAST TABLE'   WHEN 'i' THEN 'SYSTEM TOAST INDEX'   ELSE NULL   END  ELSE CASE c.relkind   WHEN 'r' THEN 'TEMPORARY TABLE'   WHEN 'i' THEN 'TEMPORARY INDEX'   WHEN 'S' THEN 'TEMPORARY SEQUENCE'   WHEN 'v' THEN 'TEMPORARY VIEW'   ELSE NULL   END  END  WHEN false THEN CASE c.relkind  WHEN 'r' THEN 'TABLE'  WHEN 'i' THEN 'INDEX'  WHEN 'S' THEN 'SEQUENCE'  WHEN 'v' THEN 'VIEW'  WHEN 'c' THEN 'TYPE'  WHEN 'f' THEN 'FOREIGN TABLE'  WHEN 'm' THEN 'MATERIALIZED VIEW'  ELSE NULL  END  ELSE NULL  END  AS TABLE_TYPE, d.description AS REMARKS  FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c  LEFT JOIN pg_catalog.pg_description d ON (c.oid = d.objoid AND d.objsubid = 0)  LEFT JOIN pg_catalog.pg_class dc ON (d.classoid=dc.oid AND dc.relname='pg_class')  LEFT JOIN pg_catalog.pg_namespace dn ON (dn.oid=dc.relnamespace AND dn.nspname='pg_catalog')  WHERE c.relnamespace = n.oid  AND c.relname LIKE 'availability_table' ORDER BY TABLE_TYPE,TABLE_SCHEM,TABLE_NAME 

我采纳所有想法。

谢谢

我不认为你正在使用你认为你正在使用的东西。

c3p0-0.9.5.2 运行 针对 Postgres 的 JDBC 4.1 驱动程序永远不会使用旧的默认 table 名称查询。如果未设置 preferredTestQuery,它将使用 Connection.isValid(...) 方法。我怀疑您在应用程序的 CLASSPATH.

某处有旧版本的 c3p0 and/or Postgres JDBC

请注意,您应该尝试追查您发布的内容中的怪异之处。你实际配置的preferredTestQuery是"select 2",而你日志中DataSource的preferredTestQuery是"select 1"。同样,您将 unreturnedConnectionTimeout 配置为 10,但在记录的配置中未设置 (0)。您正在记录一个与您正在配置的数据源相似但不同的数据源。

我怀疑生产环境中事情变得奇怪的原因是因为在您的生产环境中而不是您的测试环境中,您有较旧的库(c3p0 and/or postgres 驱动程序)和其他 DataSources 设置对于较旧的应用程序。

请注意,c3p0 的语义非常 stable。如果您在任何地方升级到 0.9.5.2,它不太可能损害您的旧应用程序。 (一定要包括它的依赖项 mchange-commons-java 0.2.11 或更高版本。)

最后,

我更改请求:select 1;通过一个简单的 "select value from singleRowTable"
=> 请求 "select value from singleRowTable" 被 Newrelic 记录了几次, => 首选查询工作。

在详细查看请求和 link 堆栈跟踪后,她来自 org.springframework.jdbc.core.simple.SimpleJdbcInsert。

事实上,SimpleJdbcInsert 就像每个插入的原型一样使用。我将其更改为实例 dao 变量,元数据仅按实例请求。