c3p0+mysql session资源不释放

问题描述:

程序正常启动后获得正常的连接数,在设定的时间内也正常释放了,但是一旦用户登录后数据库的连接sleep就超过设置的时间不再释放,程序中opensession的地方也已经手动关闭了,请问各位是属于什么问题? hibernate.cfg.xml配置文件如下:
[code="java"]

update

    <property name="hibernate.default_schema">demo_new</property>

    <property name="hibernate.connection.username">root</property>

    <property name="hibernate.connection.password"></property>

    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/demo_new</property>

    <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>

    <!-- 连接池 -->
    <property name="hibernate.connection.provider_class">
        org.hibernate.connection.C3P0ConnectionProvider</property>

    <property name="hibernate.current_session_context_class">thread</property>
    <!-- 间隔多少秒检查空闲的连接,这里为了测试设置为30秒-->
    <property name="hibernate.c3p0.idle_test_period">30</property>

    <!-- hibernate.c3p0.timeout是设置c3p0.maxIdleTime,单位是秒  ,这里为了测试设置为30秒-->
    <property name="hibernate.c3p0.timeout">30</property>

    <!-- 最大连接数-->
    <property name="hibernate.c3p0.max_size">300</property>

    <!-- 保持最小的连接数-->
    <property name="hibernate.c3p0.min_size">15</property>

    <!-- 每次获取连接的数量 -->
    <property name="hibernate.c3p0.acquire_increment">5</property>

    <property name="hibernate.bytecode.use_reflection_optimizer">
        false
    </property>
    <!--
        JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements
        属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
        如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0
    -->
    <property name="hibernate.c3p0.max_statements">50</property>

    <!--Fetch Size 是设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数-->
    <property name="hibernate.jdbc.fetch_size">100</property>

    <!--Batch Size是设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,有点相当于设置Buffer缓冲区大小的意思-->
    <property name="hibernate.jdbc.batch_size">50</property>
    <!--
        + | 在数据插入数据库之后,允许使用JDBC3 PreparedStatement.getGeneratedKeys() |
        来获取数据库生成的key(键)。需要JDBC3+驱动和JRE1.4+, | 如果你的数据库驱动在使用Hibernate的标
        识生成器时遇到问题,请将此值设为false. | 默认情况下将使用连接的元数据来判定驱动的能力. +
    -->
    <property name="hibernate.jdbc.use_get_generated_keys">true</property>
    <!-- 强制Hibernate按照被更新数据的主键,为SQL更新排序。这么做将减少在高并发系统中事务的死锁。 -->
    <property name="hibernate.order_updates">true</property>

    <property name="hibernate.connection.charSet">utf8</property>

    <property name="hibernate.connection.characterEncoding">utf8</property>

    <property name="hibernate.connection.useUnicode">true</property>

    <property name="hibernate.show_sql">false</property>

    <property name="hibernate.format_sql">false</property>

    <property name="hibernate.use_sql_comments">false</property>


    <mapping package="com.pjgw.assetsys.entity" />
            ........

[/code]

[quote]timeout是链接在连接池的生命周期,如果超过这个时间,正好在一定的时间去检查了,那么应该释放数据库的连接才对,[/quote]

[b]conn表示你链接到c3p0 ,
conneciont表示c3p0链接到db[/b]

conn 不是链接数据库的 connection

你getConnection函数,获得的只是conn 不表示你真正获得了数据库的connection

数据库的connection是在c3p0启动的时候,就链接了(这是可选项吧)也是c3p0管理的

timout指阿是conn,而不是connection, 链接池的目的就是复用这些conn

[quote]
如果数据库的连接sleep的时间超过了这个,那么是不是就是因为程序没有主动释放这个链接呢?
[/quote]

只能说c3p0收回了这个链接,回收了conn,而不是c3p0把这个链接与数据库断开了connection

[quote]
之前我也为了解决这个问题,改了mysql的wait_timeout,但是这个也是治标不治本的方法,还是没用,程序跑一段时间就崩溃了,内存一直往上涨;
我先试试看你说的用spring配置的方式,直接管理c3p0 [/quote]

我也是这么想的。

不释放就在数据库那设置timeout
[code="mysql"]
mysql>set interactive_timeout = 60; //60秒
[/code]

你担心你执行sql语句的时候突然链接被咔嚓掉么?别担心
在c3p0里面有

[code="xml"]true[/code]

每次sql语句执行的时候都验证


为什么这么解答你的问题呢?因为链接不释放,是很麻烦的事情
你得记录所有的链接,所有的sql语句,然后根据sql语句来反向推出哪个模块有问题

你给出的配置文件,怎么看都是千锤百炼的

[code="mysql"]mysql> show processlist;[/code]

[quote]我想要看到具体哪个sql语句没有释放
你说的这个命令直接在ide里面就可以看到 [/quote]

这个是不可能的了,这部分的代码你得自己写了。。。。

所以我说
[quote]
为什么这么解答你的问题呢?因为链接不释放,是很麻烦的事情
你得记录所有的链接,所有的sql语句,然后根据sql语句来反向推出哪个模块有问题 [/quote]

其实你在数据库的设置+hibernate的配置就能解决问题。

或者你用spring来管理hiberante + datasource,这样你就用的就不是hiberante的datasource,用原版的datasource

我很奇怪,如果hibernate的用没有问题的话,为啥会存在connection没有关闭的情况。

bean 调用 dao,dao在获得数据后,应该会释放链接的。。

鉴于你是[quote]spring+hibernate+c3p0+mysql[/quote]
我非常强烈的推荐你,换一种spring的配置方式,用spring来管理原生的c3p0,而不是用hiberante的delgate的方式来管理。
spring 来产生sessionFactory,spring 来产生datasource

此外,hibernate.c3p0.timeout

[quote]timeout Must be set in hibernate.cfg.xml (or hibernate.properties), Hibernate default: 0
[color=red]The seconds a Connection can remain pooled[/color] but unused before being discarded. Zero means idle connections never expire.[/quote]

你看到的,这个timeout,是在链接池的生存周期,而不是链接到数据库的timeout

呵呵,你的测试可能不对

[quote]只能说c3p0收回了这个链接,回收了conn,而不是c3p0把这个链接与数据库断开了connection [/quote]

这句话我说的不对

[quote]如果数据库的连接sleep的时间超过了这个,那么是不是就是因为程序没有主动释放这个链接呢? [/quote]
应该是的

[quote]一个一个的action类检查,大概1500多个action。。。。。[/quote]

程序写得不好,还是慢慢改吧。 走捷径,就算可以,对以后的改进也不好。

    <property name="hibernate.c3p0.min_size">15</property>  

有15个链接是不释放的啊