记录关于使用ADO.NET 连接池连接Oracle时Session信息不更新的坑

最近的一个项目中,由于界面查询的数据量比较大,关联的表比较多,有些数据查出来需要临时保存起来供后面的查询使用,于是想到了用oracle的临时表来实现这个需求。大家都知道,oracle的临时表有两种:事务级别临时表和会话级别临时表,我这里使用的是会话级别的临时表。当时把功能时候后就以为万事大吉了,没想到就在这里买下了一个坑。

 坑的浮现:之后在为系统加调试日志时偶然发现了临时表的数据没有像oracle临时表的定义那样“不同会话独享临时表,临时表的数据在会话结束后被自动清空”。首先看第一次查询的日志记录截图,第一次的查询数据量是10017行,红色框圈住的地方使用到临时表:

第二次查询的日志记录截图,第二次查询的数据量比第一次少,15行:

从这前后两次的查询结果来看,得到的结论是:使用到的oracle会话级别临时表没有像它定义那样,在会话结束后没有把临时表的数据清空?不过很明显不是因为这个原因了,最有可能的就是原因应该是,前后两次查询都是同一个Session,所以才导致临时表的数据没有被清空了。有了这个思路,接下来就是找到为什么前后两次的查询会是同一个Session。

 追究坑出现的原因:

首先,系统环境:

1、使用的ADO.NET是默认启用了连接池,连接池配置使用默认的配置;

2、连接oracle数据库的驱动是:

3、每次查询都是新建一个Connection,然后都是在查询完后调用Close()、Dispose();

查找坑出现的思路:

1、启用连接池后,前后两次查询使用的连接都是同一个连接;

2、查询完毕后,Connection调用Close()、Dispose()方法后并没有真正关闭Session;

验证过程:

首先看看oracle官方文档对Connection Pool的解释:

With connection pooling enabled (the default), the Open and Close methods of the OracleConnection object implicitly use the connection pooling service. In the preceding code, the Open call uses the connection pooling service, which is responsible for returning a connection to the application.

Connection pools are created by the connection pooling service using the ConnectionString as a signature to uniquely identify a pool.

If no pool with the exact attribute values in the ConnectionString exists, the connection pooling service creates a new connection pool. If a pool already exists with the requested signature, a connection is returned to the application from that

pool.

When a connection pool is created, the connection-pooling service initially creates the number of connections defined by the Min Pool Size attribute of the ConnectionString. This number of connections is always maintained by the connection pooling service for the connection pool.

At any given time, these connections are available in the pool or used by the application.

The Incr Pool Size attribute of the ConnectionString defines the number of new connections to be created by the connection pooling service when more connections are needed in the connection pool.

When the application closes a connection, the connection pooling service determines whether the connection lifetime has exceeded the Connection Lifetime attribute; if so, the connection pooling service closes the connection; otherwise, the connection goes back to the connection pool. The connection pooling service only enforces the Connection Lifetime when a connection is going back

to the connection pool.

The Max Pool Size attribute of the ConnectionString sets the maximum number of connections for a connection pool. If a new connection is requested, no connections are available, and Max Pool Size has been reached, then the connection pooling service waits for the time defined by Connection Timeout. If the Connection Timeout has been reached and there are still no connections

available in the pool, the connection pooling service raises an exception indicating that the pooled connection request has timed-out.

The connection pooling service closes connections when they are not used; connections are closed every three minutes. The Decr Pool Size attribute of the ConnectionString provides connection pooling service for the maximum number of connections that can be closed in one run.

Connection调用Open()方法时,以下是oracle官方文档描述:

The connection is obtained from the pool if connection pooling is enabled. Otherwise, a new connection is established.

It is possible that the pool does not contain any unused connections when the Open() method is invoked. In this case, a new connection is established.

Connection调用Close()方法时,以下是oracle官方文档描述:

Rolls back any pending transactions.

Places the connection to the connection pool if connection pooling is enabled. Even if connection pooling is enabled, the connection can be closed if it exceeds the connection lifetime specified in the connection string. If connection pooling is disabled, the connection is closed.

Closes the connection to the database.

The connection can be reopened using Open().

从oracle官方文档对于Connection Pool和Connection的Open、Close方法的描述和结合当前系统环境(查询请求只有一个客户端)来看,我们不难可以得到这么一个场景:第一次查询的时候,Connection Pool创建了一个连接返回给Connection对象,查询完后返回给连接池;在第二次查询时,由于跟第一次查询时间间隔小于默认的Connection LifeTime,Connection Pool就返回了第一次查询所用的连接给Connection对象用于查询,结果第一次和第二次用的连接都是同一个。再有,由Close()方法的描述来看,Connection调用Close方法时,并没有把连接的Session信息等数据清除掉(只有在连接真正从连接池移除掉之后,Session才没有)。

目前想到的解决办法有两个(最终决定使用第一个):

1、在每次使用临时表之前先truncate一下临时表;

2、不使用Connection Pool;

第一次发文,主要是今天看了博主农码一生的博文《我们为什么应该坚持写博客》,然后顺便记录一下这个坑,请教园中各位前辈,有没有其他解决方法,或者是说,我解决问题的方向错了。请多多指教~~~

时间: 2024-09-29 16:56:12

记录关于使用ADO.NET 连接池连接Oracle时Session信息不更新的坑的相关文章

JNDI连接池连接Oracle数据库

今天做了一个评论的小功能,要求用JNDI连接池连接Oracle数据库,以前只是测试了是否连接的上,现在没想到一个JNDI连接池连接Oracle数据库,纠结了好久,原来都是Oracle数据库的问题,这是过失.下面介绍一下JNDI连接池连接Oracle数据库. JNDI介绍 什么是JNDI? JNDI(Java Naming and Directory Interface,Java命名和目录接口) 是一组在Java应用中访问命名和目录服务的API 通过名称将资源与服务进行关联 什么是连接池技术? 连

一次c3p0连接池连接异常错误的排查

最近写了一个数据库采集程序,大概过程是将SQLSERVER数据库的数据定时采集到Oracle数据库.1小时出一次数据,每次数据量在2W左右.环境采用Sping3+hibernate4,数据库连接池采用C3p0 奇怪的时候每隔一段时间都会报:"c3p0 connection is already closed" 我开始的数据库连接池配置如下:oracle数据库开启事务,而采集的sqlserver数据库没有开启事务 jdbc.driverClass=oracle.jdbc.OracleDr

python通过连接池连接redis,操作redis队列

在每次使用redis都进行连接的话会拉低redis的效率,都知道redis是基于内存的数据库,效率贼高,所以每次进行连接比真正使用消耗的资源和时间还多.所以为了节省资源,减少多次连接损耗,连接池的作用相当于缓存了多个客户端与redis服务端的连接,当有新的客户端来进行连接时,此时,只需要去连接池获取一个连接即可,实际上连接池就是把一个连接共享给多个客户端,可以说是广播,要用的话就去接收. #-*-coding:utf-8-*- import redis # 连接池连接使用,节省了每次连接用的时间

springboot---整合druid连接池---连接oracle数据库---整合mybatis---整合thymeleaf---日志配置

目录 在新建的springboot项目pom文件中新添druid连接池的依赖 在application.properties配置文件中添加配置 配置静态文件目录和模板文件目录 @(springboot---整合druid连接池---连接oracle数据库---整合mybatis---整合thymeleaf---日志配置) 在新建的springboot项目pom文件中新添druid连接池的依赖 <!-- druid数据库连接池 --> <dependency> <groupId

Java创建连接池连接不同数据库

在一个应用里面,可能涉及到连接多个不同数据库进行操作,而每次连接写不同的实现会很麻烦.前面已经会了用JDBC连接数据库,那么利用反射和工厂模式,可以实现连接不同的数据库,这样处理起来将会很方便.同时建造数据库连接池,处理多个业务数据处理. 那么具体怎么实现呢,下面一起来看一下: 整体结构如下: 第一步,先处理连接不同数据库 1.首先,将数据库配置信息创建一个公用类:JdbcUrl.java 主数据库可以用默认的构造方法,如果是连接其他库,则通过传递参数的方式来处理. 数据库参数有如下几个: 1

关于c3p0连接池连接mysql数据库需要注意的几点

什么是数据库连接池: 用池来管理Connection,这可以重复使用Connection.有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象. 当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection,而是把Connection"归还"给池.池就可以再利用这个Connection对象了. 导入DBUtils的工具包:commons-dbutils-1.6.jar commons-dbuti

连接池 连接 数据源

数据源--getConnection()JNDI 获取数据源数据源在tomcat容器的conf文件夹 context.xml配置<Resource name="jdbc/news" author="Container" type="javax.sql.DataSource"maxActive="100"连接池的最大数据库连接数.设为0表示无限制.maxIdle="30"最大空闲数,数据库连接的最大空闲

ADO.NET笔记——使用连接池

相关知识: 连接池的意义: 应用程序往往涉及大量的,并发的数据访问操作 数据库服务器能够同时维系的连接数量非常有限.如果某个数据库访问操作不及时关闭连接,就会减少其他调用对数据库访问的机会.因此,一般需要尽可能晚的打开连接,尽可能早的关闭连接 反复的创建和销毁连接对象,或者反复的打开和关闭实际的连接(从应用程序到数据库服务器,可能跨网络),其开销是比较大的,也是不划算的 采用连接池,在池中缓存若干个链接对象.如果有调用需要使用连接,则从池中取出一个:调用完成后,并不销毁连接,而是将连接放回池中,

DBCP、C3P0、Proxool 、 BoneCP开源连接池的比较

 简介   使用评价  项目主页  DBCP DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池.DBCP可以直接的在应用程序用使用 可以设置最大和最小连接,连接等待时间等,基本功能都有,此连接池的持续运行的稳定性还是可以,不过速度稍慢,在大并发量的压力下稳定性有所下降,此外不提供连接池监控 http://homepages.nildram. co.uk/~slink/java/DBPool/  C3P0  C3P0是一个开放源代码的JDBC连接池,它在lib目录