文档章节

数据库开发 - 数据库连接池

抢小孩糖吃
 抢小孩糖吃
发布于 2016/09/22 22:08
字数 2728
阅读 102
收藏 6

#数据库连接池 ##建立连接 通过conncetion = DrvierManager.getConnection()获取数据库连接,这段代码通过对应的JDBC驱动,完成了客户端与服务器的大量交互。由于数据库连接经过4次,才能连接成功。则在复杂的网络环境下,建立数据连接的网络开销比较高。 ###MySQL获取数据库连接

  • 1.请求建立连接
    MySQL客户端向MySQL服务器发起请求建立连接
  • 2.发送随机密码种子
    服务器端会随机生成一组密码种子返回给客户端
  • 3.发送加密密码
    客户端利用密码种子和连接数据库的密码,按照约定的加密算法,可以计算得到加密的密码,然后在将这个密码发送到MySQL服务器端进行验证
  • 4.连接建立成功
    MySQL服务器经过对加密密码的验证,连接建立成功

输入图片说明

##多线程数据库访问 在实际业务场景中,多个用户访问Java应用程序,我们会启动线程去处理用户请求,如果要访问数据库,则我们需要创建connection对象,建立到后端数据库的物理连接,在SQL执行结束之后,随着close方法结束,数据库连接被销毁,线程也会被释放。

当用户再次访问时,会重复这个过程,这个过程花费大量的时间建立连接。

##连接复用 由于建立连接需要花费大量时间,我们可以使用数据库连接池对连接进行重复使用。每个线程在使用数据库连接后并不是立即销毁。而是把数据库连接交给下一个需要访问数据库的线程。多个线程共用相同的物理连接。实现连接的复用。
我们以连接池的形式来管理数据库连接,每个需要访问数据库的线程,需要从连接池中租借数据库连接。使用完毕以后,在归还给连接池,这样我们就可以实现连接的重复使用。避免每次访问数据库都要建立数据库连接。
我们从创建数据库连接改变为租借数据库连接!

输入图片说明

##建立连接 连接池存在的第二个重要原因,数据库服务端在处理我们的数据库请求时,都会在服务器端分配一定的资源,比如说内存用来保存数据库查询的结果。在请求处理结束以后,这些资源也会被释放,服务器端的资源总是有限的,不可能无限制的去分配。当同时有多个数据库请求去访问数据库时,服务器端能够处理的连接数是有限制的。当超过最大可分配的资源时,就会出现服务器宕机的问题。为了限制并发访问的连接数。数据库服务器端一般会设置最大连接数。如果超过最大连接数,就会抛出too many connection的异常。

输入图片说明

##限制连接 虽然服务器端做了必要的保护限制,但是对于应用程序,一方面服务器端直接抛SQL服务异常,对Java程序的处理不够友好。Java程序必须要捕获这些异常,进行异常处理。第二点,我们也不应当仅仅依靠服务器的最大连接数限制。我们应当在数据库访问客户端的时候,就实现这种限制。必须被有序可控的被线程使用。一旦发生异常,我们也多了一种保护手段。
所以我们需要在Java客户端程序就实现业务线程排队获取数据库练级。同时获取数据库连接的线程数,起到限流对后端数据库保护的措施。同时连接数过多,对后端数据库的性能造成严重的影响。应为连接数的增多,后端数据库就会存在更多的锁的冲突与检测。加大数据库服务器端资源的消耗。我们应当保证应用程序可控获取数据库连接。

输入图片说明

##连接池 使用连接池两个最重要的原因:

连接池实际上就是一组Java Jar包,介于Java应用程序与JDBC数据库物理连接之间。负责帮助应用程序管理JDBC连接。通过连接池暴露的接口,连接池可以获取数据库连接,使用完毕后,将数据库连接归还给数据库连接池。

连接池对JDBC进行有效的管理。当连接不足时,会自动创建连接。在空闲的连接比较多的时候,会自动的销毁链接。在多个线程同时去获取数据库连接时,连接池还提供排队等待的功能。能够保证应用程序能够有序的获取数据库连接。

输入图片说明

##连接池DBCP

DBCP连接池是Apache开源的Java连接池项目,同时是Tomcat连接池组件。同时在互联网企业中,应用最为广泛。DBCP连接池包括三个Java Jar包。

输入图片说明

##DBCP官网 Apache Commons
DBCP

可以从Apache官方网站下载Java Jar包,也可以在mvnrepo网站下载。注意:DBCP三个Jar都是必须的。

##创建连接池对象 DBCP连接池使用叫做BasicDataSource对象来表示一个连接池。首先我们要创建BasicDataSource对象,由于JDBC连接池只是JDBC连接的管理单位。底层数据库访问依然通过JDBC连接实现。所以我们必须要告诉DBCP必要的信息,才能让DBCP去帮助我们去创建连接,这些信息与我们去创建JDBC连接的信息是一致的。

输入图片说明

##DBCP初始化


    public static BasicDataSource basicDataSource = null;

    public final static String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    public final static String DB_URL = "jdbc:mysql://192.168.1.200/test";
    public final static String USER = "root";
    public final static String PASSWORD = "dVHJtG0T:pf*";

    public void init()
    {
        basicDataSource = new BasicDataSource();
        basicDataSource.setUrl(DB_URL);
        basicDataSource.setDriverClassName(JDBC_DRIVER);
        basicDataSource.setUsername(USER);
        basicDataSource.setPassword(PASSWORD);
    }

##获取数据库连接 输入图片说明
我们可以注意到,这里除了获取连接外,和JDBC代码方式没有任何区别。

Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            connection = basicDataSource.getConnection();

            statement = connection.createStatement();
            resultSet = statement.executeQuery("SELECT * FROM user");

            while(resultSet.next())
            {
                String username = resultSet.getString("UserName");
                System.out.println("[UserName]:" + username);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
        finally {
            try {
                resultSet.close();
                statement.close();
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }

##高级配置 在实际开发过程中,我们还会去设置一些连接数据库的参数,来帮助我们优化连接池,提高数据库访问的性能。

  • setInitialSize()
    当我们应用第一次访问数据库时,会发生很慢的情况。这是由于数据库连接池中没有数据库连接。需要去创建连接,此过程需要花费较多的时间。当连接创建好以后,后续的数据库访问就不会再去创建数据库连接。速度相对较快。InitialSize就是只在数据库连接池创建时,预制一些数据库连接。来保证应用程序第一次访问时,连接池中就有一定数量的数据库连接。第一次访问就不会变的很慢。可以通过InitialSize设置连接池预制的连接数。一般设置成预期业务访问量,是比较合适的。
  • setMaxTotal()
    当连接池中没有空闲的连接,又有线程需要去访问数据库时,连接池此时会创建一个新的数据库连接。但是此时,连接数已经达到了MaxTotal设定的最大值。则连接池就不会为等待线程新建数据库连接。而是强制让该线程进入等待队列。直到有其他线程归还数据库连接,再进行分配。MaxTotal起到限流保护数据库的作用,进入队列的线程不可能无限制的等待。
  • setMaxWaitMillis()
    通过设置MaxWaitMillis来设置队列线程最大的等待时间,如果超过等待时间,则会得到SQLExecption异常。
  • setMaxIdle()
    当应用程序使用完线程连接以后,将连接归还给连接池,如果此时空间连接池超过了MaxIdle的值时,则连接池会自动销毁这个数据库连接。这样减少后端数据库的连接数,减少资源的损耗。

输入图片说明

  • setMinIdle()
    当然如何连接池中的空闲连接低于MinIdle时,则会自动触发和创建数据库连接。来保证连接池有足够的连接被租借。一般来说,我们为了避免数据库连接池频繁的创建和销毁连接。建议吧MinIdleMaxIdle设置为相同的值。

##DBCP定期检查 数据库服务为了释放,空闲等待的资源,默认会关闭超过一定时间阈值的数据库连接。MySQL数据库服务器端默认会关闭时间超过,8个小时的连接。但是这时,数据库连接池端并不知道数据库连接被关闭。当线程向数据库连接池租借数据库连接时,连接池会将失效的数据库连接,租借给应用程序。线程在使用这样的数据库连接,就会抛出SQLException异常。为了防止以上情况发生,尽量保持数据库连接池连接的有效性。则定期对数据库连接池的空闲连接的时间进行检查。在服务器端关闭连接之前,我们保证,会把这个连接销毁掉,在创建新的连接。来保证线程到数据库连接池租借的连接都是有效的。

  • setTestWhileIdle(True)
    开启定期检查空间数据库连接有效性
  • setMinEvictableIdleTimeMillis()
    销毁连接最小空闲时间,当连接的空间时间超过该值时,会被连接池自动的销毁。建议:MinEvictabledleTimeMillis要小于数据库服务器端自动关闭的预制时间,MySQL小于8个小时,我们才能够检测空闲时间超过该值。才能保证主动关闭连接。
  • setTimeBetweenEvictionRunsMillis()
    检查运行时间的间隔

##验证连接池有效 连接池帮助我们起到限流的作用,实现连接的重复使用。对比使用连接池与JDBC的后端连接数。

我们通过MySQLshow processlist来可以看到线程数据库连接的情况。

如果启动十个线程,则JDBC方式会启动十个数据库连接。 而如果使用数据库连接池,限制数据库连接数,则只有两个数据库连接。

##总结 使用数据库连接提高数据库访问的效率。起到对后端数据库进行限流保护的作用。

© 著作权归作者所有

抢小孩糖吃

抢小孩糖吃

粉丝 74
博文 258
码字总数 247185
作品 0
东城
程序员
私信 提问
JDBC--数据库连接池

一、数据库连接池 (1)JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤:   在主程序(如servlet、beans)中建立数据库连接。 进行sql操作 断开数...

大道无名
2016/07/02
271
0
JDBC Item5: 数据库连接池

一、应用程序直接获取数据库连接的缺点   用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需...

_Roger_
2016/01/27
65
0
连接池详解,c3p0与dbcp的区别!

连接池: 连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。这项技术能明显提高对数据库操作的性能。 连接池的好处: (1)对于大多数应用程序,当它们正...

IT_laobai
2018/06/20
0
0
数据库连接池

这两天公司的事情不忙,看了一下ssh的框架,在看spring框架的时候看到数据源这一块。就想知道数据源这一块是怎么实现的,以前也有学习过数据源,但感觉没那么系统。在网上看到一个详细介绍数...

zdatbit
2016/05/12
100
0
数据库连接池应用中数据库服务器断开超时连接的问题

数据库应用开发过程中,我们可能会遇到一个问题:应用使用了数据库连接池,每经过指定时间后,发出到数据库服务器的任何请求都会失败,而且有且仅有一次失败,之后的正常访问都没有问题。尤其...

如风达
2015/09/18
154
0

没有更多内容

加载失败,请刷新页面

加载更多

Echars鼠标点击事件多次触发

本文转载于:专业的前端网站➭Echars鼠标点击事件多次触发 gChart.on('click', function (params) { if (params.componentSubType == "bar" && params.componentType == "serie......

前端老手
16分钟前
3
0
springboot2.0.6(附) 解析META-INF/spring.factories通过系统加载类获取对应的 class 的全限定名称

在 SpringBoot中是通过getSpringFactoriesInstances(Class<T> type)方法获取所有classpath下面的META-INF/spring.factories文件,然后根据type值找到对应的 class 的全限定名称列表。下面我来...

小亮89
18分钟前
4
0
zk工厂方法实现NIOServerCnxnFactory

NIOServerCnxnFactory类 内部类 AbstractSelectThread AcceptThread SelectorThread 属性 ZOOKEEPER_NIO_SESSIONLESS_CNXN_TIMEOUT 10s session过期时间 ZOOKEEPER_NIO_NUM_SELECTOR_THREADS......

writeademo
21分钟前
3
0
天猫精灵业务如何使用机器学习PAI进行模型推理优化

作者:如切,悟双,楚哲,晓祥,旭林 引言 天猫精灵(TmallGenie)是阿里巴巴人工智能实验室(Alibaba A.I.Labs)于2017年7月5日发布的AI智能语音终端设备。天猫精灵目前是全球销量第三、中国...

阿里云官方博客
29分钟前
5
0
BJL技巧之大路馆擦法—《利辰逸》

很多朋友刚玩百佳时间不长,不知道如何看路,今 天我就来简单的讲下看大路的方法。 都是前辈教的,这里我只是简单复述一下。 大路的观察方法有以下几种: 先从庄闲的数量变化说起。 庄闲的强...

那女孩对我说
29分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部