Oracle之数据库连接池
连接池出现的背景:
数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。
数据量少的情况:
每一次 web 请求都要建立一次数据库连接。建立连接是一个费时的活动,每次都得花费 0.05s~1s 的时间,而且系统还要分配内存资源。这个时间对于一次或几次数据库操作,或许感觉不出系统有多大的开销。如下面的用户查询案例,如果同时有 1000 人访问,就会不断的有数据库连接、断开操作:
“数据库连接”是一种稀缺的资源,为了保障网站的正常使用,应该对其进行妥善管理。其实我们查询完数据库后,如果不关闭连接,而是暂时存放起来,当别人使用时,把这个连接给他们使用。就避免了一次建立数据库连接和断开的操作时间消耗。原理如下:
我们自己尝试开发一个连接池,来为上面的查询业务提供数据库连接服务:
① 编写 class 实现 DataSource 接口
② 在 class 构造器一次性创建 10 个连接,将连接保存 LinkedList 中
③ 实现 getConnection 从 LinkedList 中返回一个连接
④ 提供将连接放回连接池中方法
1、连接池代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | public class MySelfDataSource implements DataSource { //链表 --- 实现栈结构,链表结构方便插入跟删除操作 private LinkedList<Connection> dataSources = new LinkedList<Connection>(); //初始化连接数量 public MySelfDataSource() { //一次性创建10个连接 for ( int i = 0 ; i < 10 ; i++) { try { //1、装载Oracle驱动对象,作用是:1、装载。将字节码读入内存,并产生一个与之对应的java.lang.Class类对象2、连接。这一步会验证字节码,为static变量分配内存,并赋默认值(0或null),并可选的解析符号引用(这里不理解没关系)3、初始化。为类的static变量赋初始值,假如有static int a = 1;这个将a赋值为1的操作就是这个时候做的。除此之外,还要调用类的static块。(这一步是要点) Class.forName( "oracle.jdbc.OracleDriver" ); // 或者使用DriverManager.registerDriver(new OracleDriver()); //2、通过JDBC建立数据库连接 Connection con =DriverManager.getConnection( "jdbc:oracle:thin:@10.148.3.20:1521:tgtest" , "saa" , "123" ); //3、将连接加入连接池中 dataSources.add(con); } catch (Exception e) { e.printStackTrace(); } } } @Override publicConnection getConnection() throws SQLException { //取出连接池中一个连接 finalConnection conn = dataSources.removeFirst(); // 删除第一个连接返回 return conn; } //将连接放回连接池 publicvoid releaseConnection(Connection conn) { dataSources.add(conn); } } |
2.使用连接池重构我们的用户查询函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //查询所有用户 Public void FindAllUsers(){ //1、使用连接池建立数据库连接 MyDataSource dataSource = new MyDataSource(); Connection conn =dataSource.getConnection(); //2、创建状态 Statement state =con.createStatement(); //3、查询数据库并返回结果 ResultSet result =state.executeQuery( "select * from users" ); //4、输出查询结果 while (result.next()){ System.out.println(result.getString( "email" )); } //5、断开数据库连接 result.close(); state.close(); //6、归还数据库连接给连接池 dataSource.releaseConnection(conn); } |
影响因素:
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数制约。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。数据库连接池的最小连接数和最大连接数的设置要考虑到下列几个因素:
原理:
连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。
作用:它大大提供了数据库连接的利用率,减小了内存吞吐的开销。
Java 连接池:
-
支持多个 pool
-
自动关闭相关联的 JDBC 对象
-
在所设定 time-outs 之后察觉连接泄漏
-
追踪连接使用情况
-
强制启用最近最少用到的连接
-
把 SmartPool“包装”成现存的一个 pool
-
Oracle 的 PS Cache 内存占用优化
-
MySql 的 ping 检测优化