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

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

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

输入图片说明

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

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

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

输入图片说明

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

输入图片说明

##限制链接 虽然服务器端作了必要的保护限制,可是对于应用程序,一方面服务器端直接抛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方式会启动十个数据库链接。 而若是使用数据库链接池,限制数据库链接数,则只有两个数据库链接。

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

相关文章
相关标签/搜索