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

#数据库连接池 ##建立连接 通过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方式会启动十个数据库连接。 而如果使用数据库连接池,限制数据库连接数,则只有两个数据库连接。

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

转载于:https://my.oschina.net/hava/blog/750428

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值