精华内容
下载资源
问答
  • 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个; 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接...

    一、什么是连接池?

    数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;

    释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。

    ———以上参考《百度百科》

    二、为什么使用数据连接池

    建立一个数据库连接是一件非常耗时(消耗时间)耗力(消耗资源)的事情。之所以会这样,是因为连接到数据库服务器需要经历几个漫长的过程:建立物理通道(例如套接字或命名管道),与服务器进行初次握手,分析连接字符串信息,由服务器对连接进行身份验证,运行检查以便在当前事务中登记等等。

    连接池就是这样一个容器:它存放了一定数量的与数据库服务器的物理连接。因此,当我们需要连接数据库服务器的时候,只需去池(容器)中取出一条空闲的连接,而不是新建一条连接。这样的话,我们就可以大大减少连接数据库的开销,从而提高了应用程序的性能。

    三、数据库连接池的工作原理

    连接池的工作原理主要由三部分组成,分别为

    • 连接池的建立
    • 连接池中连接的使用管理
    • 连接池的关闭

    第一、连接池的建立。
      一般在系统初始化时,连接池会根据系统配置建立,并在池中创建了几个连接对象,以便使用时能从连接池中获取。连接池中的连接不能随意创建和关闭,这样避免了连接随意建立和关闭造成的系统开销。

    Java中提供了很多容器类可以方便的构建连接池,例如Vector、Stack等。

    第二、连接池的管理。
      连接池管理策略是连接池机制的核心,连接池内连接的分配和释放对系统的性能有很大的影响。其管理策略是:

    当客户请求数据库连接时,

    • 1)如果池中有空闲连接可用,返回该连接。
    • 2)如果没有空闲连接,池中连接都已用完,创建一个新连接添加到池中。
    • 3)如果池中连接已达到最大连接数,请求按设定的最大等待时间进入等待队列直到有空闲连接可用。
    • 4)如果超出最大等待时间,则抛出异常给客户。

    当客户释放数据库连接时,先判断该连接的引用次数是否超过了规定值,如果超过就从连接池中删除该连接,否则保留为其他客户服务。

    该策略保证了数据库连接的有效复用,避免频繁的建立、释放连接所带来的系统资源开销。

    如果连接长时间空闲,或检测到与服务器的连接已断开,连接池管理器也会将该连接从池中移除。

    第三、连接池的关闭。
    当应用程序退出时,关闭连接池中所有的连接,释放连接池相关的资源,该过程正好与创建相反。

    四、连接池需要注意的点

    1、并发问题

    为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题。

    这个问题相对比较好解决,因为各个语言自身提供了对并发管理的支持像java,c#等等,使用synchronized(java)lock(C#)关键字即可确保线程是同步的。

    2、事务处理

    我们知道,事务具有原子性,此时要求对数据库的操作符合“ALL-OR-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。

    我们知道当2个线程共用一个连接Connection对象,而且各自都有自己的事务要处理时候,对于连接池是一个很头疼的问题,因为即使Connection类提供了相应的事务支持,可是我们仍然不能确定那个数据库操作是对应那个事务的,这是由于我们有2个线程都在进行事务操作而引起的。

    为此我们可以使用每一个事务独占一个连接来实现,虽然这种方法有点浪费连接池资源但是可以大大降低事务管理的复杂性。

    3、连接池的分配与释放

    连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。

    对于连接的管理可使用一个List。即把已经创建的连接都放入List中去统一管理。每当用户请求一个连接时,系统检查这个List中有没有可以分配的连接。如果有就把那个最合适的连接分配给他,如果没有就抛出一个异常给用户。

    4、连接池的配置与维护

    连接池中到底应该放置多少连接,才能使系统的性能最佳?

    系统可采取设置**最小连接数(minConnection)最大连接数(maxConnection)**等参数来控制连接池中的连接。

    比方说,最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。

    最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过软件需求上得到。

    如何确保连接池中的最小连接数呢?

    有动态和静态两种策略。
    动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。

    展开全文
  • 数据库连接

    千次阅读 多人点赞 2019-10-22 19:54:01
    1、什么是数据库连接池? 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个; 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放...

    1、什么是数据库连接池?

    数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;

    释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。

    这项技术能明显提高对数据库操作的性能

    2、连接池解决的问题???

          不断的创建、销毁链接,会导致访问数据库服务器的压力,而且对于内存来说,不断的开辟与销毁,内存的使用率极低。使用数据库连接池可以明显提高对数据库操作的性能!

          数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并将这些连接组成一个连接池(简单说:在一个“池”里放了好多半成品的数据库连接对象),由应用程序动态地对池中的连接进行申请、使用和释放。对于多于连接池中连接数的并发请求,应该在请求队列中排队等待并且应用程序可以根据池中连接的使用率,动态增加或减少池中的连接数

    3、数据库连接池的工作原理???

      1、三步骤     连接池的建立,连接池中连接的使用管理,连接池的关闭

    一、连接池的建立:创建几个连接对象,以便使用的时候能从连接池中获取

    二、客户请求数据库连接时,首先查看连接池中是否有空闲连接,若存在,将连接分配给用户使用;如果没有空闲连接,则查看当前所开的连接数是否已经达到最大的连接数,如果没有达到,就重新创建一个连接给请求的客户,如果达到就按照设定的最大等待时间进行等待,超出的最大等待的时间,就抛出异常给用户,当用户释放数据连接的时候,先判断该连接的引用次数是否超过了规定的值,如果超过就删除,如果没有的话,就保留为其他客户服务。保证了数据库连接的有效复用,避免频繁的建立、释放连接所带来的系统资源的资源开销。

    三、连接池的关闭,当应用程序退出的时候i,关闭所有的连接,释放相关的资源,正好与创建相反

    4、数据库连接配置时的参数(可选,有默认值)

    最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费.

    最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作

    最大空闲时间:连接池对象最长的闲置时间,如果长时间没有被使用,那么此连接对象就会被销毁。

    获取连接超时时间:池子中总共有50条连接,当这50条连接都处于工作状态时,第51个连接请求到达,让其加入到等待队列中,等待时间如果超过了设置的超时时间,则抛出异常

    初始化连接数:当数据库连接池创建时,初始化的连接数量

    5、主流的数据库连接池技术

    创建QueryRunner时,可以传递一个数据源DataSource,我们可以将这个数据源理解为数据库连接池,那么我们现在使用不同的数据库连接池技术,目的就只有一个,得到数据源对象

    6、DBCP

    介绍:DBCP(DataBase Connection Pool)属于Apache顶级项目Commons中的核心子项目(最早在Jakarta Commons里就有),它内部依赖于Commons中的另一个子项目Pool,连接池最核心的“池”,就是由Pool组件提供的,因此,DBCP的性能实际上就是Pool的性能

    步骤:

    导包 build path

    书写dbcp.properties属性文件,文件目录在src下

    书写dbcp工具类,来提供数据源

    测试数据源是否可用

    7、封装一个工具类,专门用于向外界提供dbcp的数据源。

    /**
     * 此类的作用就是生成并且提供dbcp的数据源
     * @author Administrator
     *
     */
    public class DBCPUtils {
    	private static DataSource dataSource = null;
    	
    	//完成对数据源的赋值,赋值只需要走一次,所以在静态代码块中完成赋值
    	static {
    		Properties properties = new Properties();
    		FileInputStream fStream = null;
    		try {
    			//创建输入流对象,来读取配置文件dbcp.properties
    			fStream = new FileInputStream("src/dbcp.properties");
    			//将流中读取到的内容加载属性文件对象中
    			properties.load(fStream);
    			//将加载完毕内容的属性文件对象传递到dbcp创建数据源的方法中,生成数据源
    			dataSource = BasicDataSourceFactory.createDataSource(properties);
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    	
    	//返回数据源的方法
    	public static DataSource getDataSource() {
    		return dataSource;
    	}
    }

    测试代码的书写:

    public static void main(String[] args) throws SQLException {
    		/*
    		 	使用dbcp数据源来操作数据库
    		 	方式1:在创建QueryRunner对象,给定数据源,此时不需要书写连接获取的代码,会自动从给定的数据源中获取连接
    		 	使用完毕,不需要执行关闭资源的方法,连接对象会自动归还池子
    		 	
    		 	方式2:我们可以通过数据源的getConnection()获取到由池子管理的数据库连接对象
    		 	使用完毕后,执行关闭资源的方法,并不是将连接对象销毁,而是将连接对象归还池子
    		 */
    		/*
    		QueryRunner qRunner = new QueryRunner(DBCPUtils.getDataSource());
    		List<User> users = qRunner.query("select * from user", 
    				new BeanListHandler<User>(User.class));
    		for (User user : users) {
    			System.out.println(user);
    		}*/
    		
    		DataSource dataSource = DBCPUtils.getDataSource();
    		Connection connection = dataSource.getConnection();
    		QueryRunner qRunner = new QueryRunner();
    		List<User> users = qRunner.query(connection, "select * from user", 
    				new BeanListHandler<User>(User.class));
    		for (User user : users) {
    			System.out.println(user);
    		}
    		DbUtils.close(connection);
    	}

    写一个参数文件dbcp.properties:

    //创建输入流对象,来读取配置文件dbcp.properties

    7、druid的使用

    介绍:它除了提供性能卓越的连接池功能外,还集成了SQL监控,黑名单拦截等功能,用它自己的话说,Druid是“为监控而生”。借助于阿里这个平台的号召力,产品一经发布就赢得了大批用户的拥趸,从用户使用的反馈来看,Druid也确实没让用户失望。

    使用步骤:

    导包   

    书写配置文件druid.properties    

    书写druid工具类,来生成并提供druid的数据源   

    /**
     * 此类专门用于生成druid数据源
     * @author Administrator
     *
     */
    public class DruidUtils {
    	//声明数据源
    	private static DataSource dataSource = null;
    	
    	//为数据源赋值
    	static {
    		Properties properties = new Properties();
    		FileInputStream fStream = null;
    		try {
    			fStream = new FileInputStream("src/druid.properties");
    			properties.load(fStream);
    			dataSource = DruidDataSourceFactory.createDataSource(properties);
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} finally {
    			try {
    				if (fStream != null) {
    					fStream.close();
    				}
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	//返回获取数据源的方法
    	public static DataSource getDataSource() {
    		return dataSource;
    	}
    }

    书写测试代码

    public static void main(String[] args) {
    		//使用druid+dbutils完成添加操作
    		QueryRunner qRunner = new QueryRunner(DruidUtils.getDataSource());
    		try {
    			int row = qRunner.update("insert into user values (null, ?, ?, ?)", 
    								"小阔爱", "666", "男");
    			System.out.println(row > 0 ? "添加成功" : "添加失败");
    		} catch (SQLException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}

    8、c3p0的使用

    介绍:C3P0是我使用的第一款数据库连接池,在很长一段时间内,它一直是Java领域内数据库连接池的代名词,当年盛极一时的Hibernate都将其作为内置的数据库连接池,可以业内对它的稳定性还是认可的。C3P0功能简单易用,稳定性好这是它的优点,但是性能上的缺点却让它彻底被打入冷宫。C3P0的性能很差,差到即便是同时代的产品相比它也是垫底的,更不用和Druid、HikariCP等相比了。正常来讲,有问题很正常,改就是了,但c3p0最致命的问题就是架构设计过于复杂,让重构变成了一项不可能完成的任务。随着国内互联网大潮的涌起,性能有硬伤的c3p0彻底的退出了历史舞台。

    使用步骤:

    导包   

    书写c3p0.properties文件,一定要放在src下   

    如果c3p0的配置文件名称叫c3p0.properties,并且放在了src下,那么就会自动读取配置文件!

    测试代码  

    测试代码:
    public class C3P0Demo {
    	private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
    	
    	public static void main(String[] args) {
    		QueryRunner qRunner = new QueryRunner(dataSource);
    		try {
    			User user = qRunner.query("select * from user where uid = ?",
    					new BeanHandler<User>(User.class), 2);
    			System.out.println(user);
    		} catch (SQLException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();

    五,duid,dbcp,c3p0 的区别。

     

     

     

     

     

     

     

    展开全文
  • 阿里巴巴数据库连接池完整demo

    热门讨论 2014-08-13 13:11:13
    阿里巴巴数据库连接池应该是目前最好的数据库连接池:大并发稳定,操作数据库效率高。此demo不仅有和spring整合的例子,还有单独配置的实例,供大家学习掌握
  • JDBC与数据库连接

    万次阅读 多人点赞 2018-10-24 23:58:23
    JDBC简介,driver类型,JDBC连接,使用技巧; 连接,短连接,长连接连接池; 池化思想; 配置,基本配置,关键配置,性能配置; 连接池工具; druid; HikariCP; flexy-pool;

    JDBC

    简介

    JDBC 是Java应用程序用来连接关系型数据库的标准API,为多种关系型数据库提供一个统一的访问接口。Sun公司一共定义4种 JDBC 驱动类型,一般使用第4种,该类型的Driver完全由Java代码实现,通过使用socket与数据库进行通信。

    1. JDBC-ODBC Bridge driver (bridge driver),JDBC-ODBC桥驱动程序;
    2. Native-API/partly Java driver (native driver),JDBC本地API;
    3. All Java/Net-protocol driver (middleware driver),JDBC-Net纯Java;
    4. All Java/Native-protocol driver (Pure java driver),100%纯Java。

    常规数据库连接一般由以下六个步骤构成:

    • 装载数据库驱动程序;
    • 建立数据库连接;
    • 创建数据库操作对象;
    • 访问数据库,执行sql语句;
    • 处理返回结果集;
    • 断开数据库连接。

    此处省略常规 JDBC 获取连接、执行SQL、获取结果集代码,一般严格遵守上面的流程,网上一大堆;

    连接角度看 JDBC

    在这里插入图片描述
    上图大致画出以访问MySQL为例,执行一条 SQL 命令,不使用连接池的情况下,需要经过哪些流程。

    1. TCP建立连接的三次握手;
    2. MySQL认证的三次握手;
    3. 真正的SQL执行;
    4. MySQL的关闭;
    5. TCP的四次握手关闭;

    为了执行一条SQL,有很多网络交互。
    优点:实现简单。
    缺点:

    1. 网络IO较多;
    2. 数据库的负载较高;
    3. 响应时间较长及QPS较低;
    4. 应用频繁的创建连接和关闭连接,导致临时对象较多,GC频繁;
    5. 在关闭连接后,会出现大量TIME_WAIT 的TCP状态(在2个MSL之后关闭)。

    JDBC技巧

    1. 使用PrearedStatement,可以通过预编译的方式避免在拼接SQL时造成SQL注入。
    2. 使用ConnectionPool
    3. 禁用自动提交
      这个最佳实践在我们使用JDBC的批量提交的时候显得非常有用,将自动提交禁用后,你可以将一组数据库操作放在一个事务中,而自动提交模式每次执行SQL语句都将执行自己的事务,并且在执行结束提交。
    4. 使用Batch Update:批量更新/删除,比单个更新/删除,能显著减少数据传输的往返次数,提高性能。
    5. 使用列名获取ResultSet中的数据,从而避免invalidColumIndexError
      JDBC中的查询结果封装在ResultSet中,我们可以通过列名和列序号两种方式获取查询的数据,当我们传入的列序号不正确的时候,就会抛出invalidColumIndexException,例如你传入了0,就会出错,因为ResultSet中的列序号是从1开始的。另外,如果你更改了数据表中列的顺序,你也不必更改JDBC代码,保持了程序的健壮性。有一些Java程序员可能会说通过序号访问列要比列名访问快一些,确实是这样,但是为了程序的健壮性、可读性,我还是更推荐你使用列名来访问。
    6. 使用变量绑定而不是字符串拼接
      使用PreparedStatment可以防止注入,而使用?或者其他占位符也会提升性能,因为这样数据库就可以使用不同的参数执行相同的查询,提示性能,也防止SQL注入。
    7. 关闭Connection 等资源,确保资源被释放;
    8. 选择合适的JDBC驱动,参考前文,选择第四种;
    9. 尽量使用标准的SQL语句,从而在某种程度上避免数据库对SQL支持的差异
      不同的数据库厂商的数据库产品支持的SQL的语法会有一定的出入,为了方便移植,推荐使用标准的ANSI SQL标准写SQL语句。
    10. 使用正确的getXXX()方法
      当从ResultSet中读取数据的时候,虽然JDBC允许你使用getString()和getObject()方法获取任何数据类型,推荐使用正确的getter方法,这样可以避免数据类型转换。

    连接池

    先看看连接的简介。

    连接

    当数据库服务器和客户端位于不同的主机时,就需要建立网络连接来进行通信。客户端必须使用数据库连接来发送命令和接收应答、数据。通过提供给客户端数据库的驱动指定连接字符串后,客户端就可以和数据库建立连接。查阅程序语言手册来获知通过何种方式使用短连接、长连接。

    1. 短连接
      短连接是指程序和数据库通信时需要建立连接,执行操作后,连接关闭。短连接简单来说就是每一次操作数据库,都要打开和关闭数据库连接,基本步骤是:连接 -> 数据传输 -> 关闭连接

    在慢速网络下使用短连接,连接的开销会很大;在生产繁忙的系统中,连接也可能会受到系统端口数的限制,如果要每秒建立几千个连接,那么连接断开后,端口不会被马上回收利用,必须经历一个FIN阶段等待,直到可被回收利用为止,这样就可能会导致端口资源不够用。在Linux上,可以通过调整/proc/sys/net/ipv4/ip_local_port_range来扩大端口的使用范围;调整/proc/sys/net/ipv4/tcp_fin_timeout来减少回收延期(如果想在应用服务器上调整这个参数,一定要慎重!)。
    另外一个办法是主机使用多个IP地址。端口数的限制其实是基于同一个IP:PORT的,如果主机增加IP,MySQL就可以监听多个IP地址,客户端也可以选择连接某个IP:PORT,这样就增加端口资源。

    1. 长连接
      长连接是指程序之间的连接在建立之后,就一直打开,被后续程序重用。使用长连接的初衷是减少连接的开销。当收到一个永久连接的请求时,检查是否已经存在一个相同的永久连接。存在则复用;不存在则重新建立一个新的连接。所谓相同的连接是指基本连接信息,即用户名、密码、主机及端口都相同。

    从客户端的角度来说,使用长连接有一个好处,可以不用每次创建新连接,若客户端对MySQL服务器的连接请求很频繁,永久连接将更加高效。对于高并发业务,如果可能会碰到连接的冲击,推荐使用长连接或连接池。

    从服务器的角度来看,它可以节省创建连接的开销,但维持连接也是需要内存的。如果滥用长连接的话,可能会使用过多的MySQL服务器连接。现代的操作系统可以拥有几千个MySQL连接,但很有可能绝大部分都是睡眠状态的,这样的工作方式不够高效,而且连接占据内存,也会导致内存的浪费。

    对于扩展性好的站点来说,其实大部分的访问并不需要连接数据库。如果用户需要频繁访问数据库,那么可能会在流量增大的时候产生性能问题,此时长短连接都是无法解决问题的,所以应该进行合理的设计和优化来避免性能问题。

    如果客户端和MySQL数据库之间有连接池或Proxy代理,一般在客户端推荐使用短连接。对于长连接的使用一定要慎重,不可滥用。如果没有每秒几百、上千的新连接请求,就不一定需要长连接,也无法从长连接中得到太多好处。在Java语言中,由于有连接池,如果控制得当,则不会对数据库有较大的冲击,但PHP的长连接可能导致数据库的连接数超过限制,或者占用过多的内存。

    1. 连接池
      数据库连接池是一些网络代理服务或应用服务器实现的特性,实现一个持久连接的“池”,允许其他程序、客户端来连接,这个连接池将被所有连接的客户端共享使用,连接池可以加速连接,也可以减少数据库连接,降低数据库服务器的负载。

    2. 持久连接和连接池的区别
      长连接是一些驱动、驱动框架、ORM工具的特性,由驱动来保持连接句柄的打开,以便后续的数据库操作可以重用连接,从而减少数据库的连接开销。而连接池是应用服务器的组件,它可以通过参数来配置连接数、连接检测、连接的生命周期等。

    如果连接池或长连接使用的连接数很多,有可能会超过数据库实例的限制,那么就需要留意连接相关的设置,比如连接池的最小、最大连接数设置,以及php-fpm的进程个数等,否则程序将不能申请新的连接。

    最小连接数和最大连接数的设置要考虑到以下几个因素:
    最小连接数:连接池一直保持的数据库连接,如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费;
    最大连接数:连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作;
    如果最小连接数与最大连接数相差很大:那么最先连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接。不过这些大于最小连接数的数据库连接在使用完不会马上被释放,将被放到连接池中等待重复使用或是空间超时后被释放。

    池化

    连接池类似于线程池或者对象池,数据库连接池为系统的运行带来以下优势:

    • 昂贵的数据库连接资源得到重用;
    • 减少数据库连接建立和释放的时间开销,提高系统响应速度;
    • 统一的数据库连接管理,避免连接资源的泄露。

    连接池负责:连接建立、连接释放、连接管理、连接分配。

    数据库连接池运行机制:
    系统初始化时创建连接池,程序操作数据库时从连接池中获取空闲连接,程序使用完毕将连接归还到连接池中,系统退出时,断开所有数据库连接并释放内存资源。

    数据库连接池生命周期
    数据库每个读写操作需要一个连接。数据库连接调用流如下图:
    在这里插入图片描述
    调用流程为:

    • 应用数据层向DataSource请求数据库连接
    • DataSource使用数据库Driver打开数据库连接
    • 创建数据库连接,打开TCP socket
    • 应用读/写数据库
    • 如果该连接不再需要就关闭连接
    • 关闭socket

    为什么连接池快很多?
    分析池连接管理的调用流程:
    在这里插入图片描述
    无论何时请求一个连接,池数据源会从可用的连接池获取新连接。仅当没有可用的连接而且未达到最大的连接数时连接池将创建新的连接。close()方法把连接返回到连接池而不是真正地关闭它。
    在这里插入图片描述
    重用数据库连接最明显的原因:

    • 减少应用程序和数据库管理系统创建/销毁TCP连接的OS I/O开销
    • 减少JVM对象垃圾
    • 缓冲安全:连接池是即将到来的连接请求的有界缓冲区。如果出现瞬间流量尖峰,连接池会平缓这一变化,而不是使所有可用数据库资源趋于饱和。
    • 等待步骤和超时机制,可有效防止数据库服务器过载。如果一个应用消耗太多数据库流量,为防止它将数据库服务器压垮,连接池将减少它对数据库的使用。

    配置

    连接池配置大体可以分为基本配置、关键配置、性能配置等主要配置。

    基本配置

    基本配置是指连接池进行数据库连接的四个基本必需配置:传递给JDBC驱动的用于连接数据库的用户名、密码、URL以及驱动类名。
    在Druid连接池的配置中,driverClassName可配可不配,如果不配置会根据url自动识别dbType(数据库类型),然后选择相应的driverClassName。

    关键配置

    为了发挥数据库连接池的作用,在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
    最小连接数:是数据库一直保持的数据库连接数,所以如果应用程序对数据库连接的使用量不大,将有大量的数据库资源被浪费。
    初始化连接数:连接池启动时创建的初始化数据库连接数量。
    最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求被加入到等待队列中。
    最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间,超过时间则抛出异常,可设置参数为0或者负数使得无限等待(根据不同连接池配置)。

    数据库连接池在初始化的时候会创建initialSize个连接,当有数据库操作时,会从池中取出一个连接。如果当前池中正在使用的连接数等于maxActive,则会等待一段时间,等待其他操作释放掉某一个连接,如果这个等待时间超过maxWait,则会报错;如果当前正在使用的连接数没有达到maxActive,则判断当前是否空闲连接,如果有则直接使用空闲连接,如果没有则新建立一个连接。在连接使用完毕后,不是将其物理连接关闭,而是将其放入池中等待其他操作复用。

    性能配置

    预缓存设置:PSCache,对支持游标的数据库性能提升巨大,比如说oracle。JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements属于单个connection而不是整个连接池,所以设置这个参数需要考虑到多方面的因素。
    单个连接拥有的最大缓存数:要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100

    连接有效性检测设置:连接池内部有机制判断,如果当前的总的连接数少于miniIdle,则会建立新的空闲连接,以保证连接数得到miniIdle。如果当前连接池中某个连接在空闲timeBetweenEvictionRunsMillis时间后任然没有使用,则被物理性的关闭掉。有些数据库连接的时候有超时限制(mysql连接在8小时后断开),或者由于网络中断等原因,连接池的连接会出现失效的情况,这时候设置一个testWhileIdle参数为true,可以保证连接池内部定时检测连接的可用性,不可用的连接会被抛弃或者重建,最大情况的保证从连接池中得到的Connection对象是可用的。当然,为了保证绝对的可用性,你也可以使用testOnBorrow为true(即在获取Connection对象时检测其可用性),不过这样会影响性能。

    超时连接关闭设置:removeAbandoned参数,用来检测当前使用的连接是否发生连接泄露,所以在代码内部就假定如果建立连接的时间很长,则将其认定为泄露,继而强制将其关闭掉。

    工具

    • C3P0:开源JDBC连接池,实现数据源和JNDI绑定,包括实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。单线程,性能较差,适用于小型系统,代码600KB左右。
    • BoneCP:开源的快速的 JDBC 连接池。只有四十几K(运行时需要log4j和Google Collections的支持)。另外个人觉得 BoneCP 有个缺点是,JDBC驱动的加载是在连接池之外的,这样在一些应用服务器的配置上就不够灵活。官方说法BoneCP是一个高效、免费、开源的Java数据库连接池实现库。设计初衷就是为了提高数据库连接池性能,完美集成到一些持久化产品如Hibernate和DataNucleus中。特色:高度可扩展,快速;连接状态切换的回调机制;允许直接访问连接;自动化重置能力;JMX支持;懒加载能力;支持XML和属性文件配置方式;较好的Java代码组织。
    • DBCP:Database Connection Pool,一个依赖Jakarta commons-pool对象池机制的数据库连接池,单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar,预先将数据库连接放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完再放回。单线程,并发量低,性能不好,适用于小型系统。
    • Tomcat Jdbc Pool:Tomcat在7.0以前都是使用common-dbcp做为连接池组件,但是dbcp是单线程,为保证线程安全会锁整个连接池,性能较差,dbcp有超过60个类,也相对复杂。Tomcat从7.0开始引入新增连接池模块叫做Tomcat jdbc pool,基于Tomcat JULI,使用Tomcat日志框架,完全兼容dbcp,通过异步方式获取连接,支持高并发应用环境,超简单,核心文件只有8个,支持JMX,支持XA Connection。
    • Druid:下面详细讲解;
    • HikariCP:下面详细讲解;

    本文不会详细介绍前面几种连接池工具,基本上过时;

    Druid

    简介

    阿里出品,淘宝和支付宝专用数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个SQL Parser。支持所有JDBC兼容的数据库。Druid针对Oracle和MySQL特别优化,比如Oracle的PS Cache内存占用优化,MySQL的ping检测优化。Druid提供SQL-92的SQL的完整支持,这是一个手写的高性能SQL Parser,支持Visitor模式,使得分析SQL的抽象语法树很方便。Druid能够提供强大的监控和扩展功能,是一个可用于大数据实时查询和分析的高容错、高性能的开源分布式系统,尤其是当发生代码部署、机器故障以及其他产品系统遇到宕机等情况时,Druid仍能够保持100%正常运行。主要特色:为分析监控设计;快速的交互式查询;高可用;可扩展;
    简单SQL语句用时10微秒以内,复杂SQL用时30微秒。
    通过Druid提供的SQL Parser可以在JDBC层拦截SQL做相应处理,比如说分库分表、审计等。Druid防御SQL注入攻击的WallFilter就是通过Druid的SQL Parser分析语义实现的。

    • Proxool:一个Java SQL Driver驱动程序,完全可配置。

    todo

    spring boot with druid

    以目前也是以后的 Java EE 发展方向的spring boot 为例,说明如何集成druid。其他传统 SSH & SSM应用架构大致类似,但是配置会复杂一些;

    HikariCP

    简介

    新一代数据库连接池,性能相当优异,spring boot 2 默认使用的 dbcp 从之前的 tomcat-pool 换成HikariCP 。
    在 druid 以及 HikariCP 出现之前,BoneCP 可以说是性能最好的 dbcp 之一,https://jolbox.com/index.html?page=https://jolbox.com/benchmarks.html
    官网:http://www.jolbox.com/

    可是现在,BoneCP 的GitHub 的截图。
    在这里插入图片描述
    GitHub

    优势

    Springboot 2.0 默认使用的连接池换成HikariCP,因为其性能格外优异。而其性能来源于HikariCP的在以下几个方面的优化:

    1. 字节码精简 :优化代码,直到编译后的字节码最少,这样CPU缓存可以加载更多的程序代码;
    2. 优化代理和拦截器:减少代码,例如HikariCP的Statement proxy只有100行代码,只有BoneCP的十分之一;
    3. 自定义数组类型(FastStatementList)代替ArrayList:避免每次get()调用都要进行range check,避免调用remove()时的从头到尾的扫描;
    4. 自定义集合类型,使用ConcurrentBag提高并发读写的效率;
    5. 其他针对BoneCP缺陷的优化,比如对于耗时超过一个CPU时间片的方法调用的研究。

    JDBC连接池的实现,主要是对JDBC中几个核心对象Connection、Statement、PreparedStatement、CallableStatement以及ResultSet的封装与动态代理。

    参考:GitHub-HikariCP-wiki

    常用配置项

    • dataSourceClassName
      接收字符串值,默认为空。JDBC driver 提供的 DataSource 类名。不同的 JDBC driver 会有其相对应的类名(不支持 XA data sources)。如果使用了 jdbcUrl 配置项则不需要配置此项。
    • jdbcUrl
      接收字符串值,默认为空。此属性将使 HikariCP 使用“基于驱动管理器”(DriverManager-based)的配置。由于多种原因,我们认为基于数据源(DataSource-based)的配置是更好的选择。但对许多部署实例来讲却也区别不大。当使用此属性来配置“旧”的 JDBC 驱动时,你可能也需要设置 driverClassName 属性,但可以试一试不设置是否能行得通。
    • username / password
      接收字符串值,默认为空。对 DataSource 来讲,username和password仅会在调用 DataSource.getConnection(username, password) 时用到。但在使用基于驱动(Driver-based)配置时,HikariCP 会使用 username 的值去设置调用 DriverManager.getConnection(jdbcUrl, props) 方法时传入的 Properties 中的 user 属性。如果并不是你想要的,你需要避免执行这个方法。
    • autoCommit
      布尔值,默认为 true。控制从连接池中返回的连接的 auto-commit 行为。通常情况下会设置为 false。比如使用Spring 统一管理数据库事务,这时就需要禁用 auot-commit。
    • connectionTimeout
      接收数值,默认为30000(30秒),最小可接收值为250ms。设置客户端获取连接前等待的最大毫秒数,即超时时间。如果超过了这个时间后仍然没有可用的数据库连接返回,SqlException 则会被抛出。
    • idleTimeout
      接收数值,默认为600000(10分),最小可接收值为10000(10秒)。此属性控制一个连接保持空闲状态的最大超时时间。只有当 minimumIdle 小于 maximumPoolSize 时此属性才会生效。一个数据库连接是否退化为空闲状态需要平均15秒+,最多30秒+。设置0表示空闲的连接永远不会从连接池中销毁。
    • maxLifetime
      接收数值,默认为1800000(30分)。此属性为单个连接在连接池中的最长生命周期时间。连接只有在被关闭后才会被移除。强烈建议设置此属性,并且至少应该比任何数据库或组件强制要求的连接时间少30秒。此属性设置为0表示没有最长生命周期时间。
    • connectionTestQuery
      接收字符串值,默认为空。如果数据库驱动支持 JDBC4,则强烈建议不要设置此属性。此属性是为那些不支持 JDBC4 Connection.isValid() API 的老旧数据库准备的。这条查询语句会在连接从连接池返回给客户端之前执行,用以验证返回的数据库连接仍然可用。再次重申,在不设置此属性时尝试启动数据库连接池,如果你的数据库驱动不支持 JDBC4,HikariCP 会记录下错误信息。
      在 c3p0 中,这个属性的名称是 preferredTestQuery;在 tmocat-jdbc 中,这个属性的名称叫做 validationQuery。属性值一般设置为 “Select 1”。
    • minimumIdle
      接收数值,默认和 maximumPoolSize 相同。设置 HikariCP 在连接池中保存的最少空闲连接数。如果空闲连接数少于此属性值,HikariCP 会尽力快速高效的增加连接。不过,为了最高性能和峰值弹性需求,我们建议不要设置此属性,而是让 HikariCP 作为一个固定大小的连接池。
    • maximumPoolSize
      接收数值,默认为10。设置 HikariCP 在连接池中保存的最多连接数,包括空闲的和正在使用的连接。此属性的合理值应该由程序的运行环境决定。当连接池中没有空闲连接,调用 getConnection() 会一直阻塞直到超过 connectionTimeout 设置的超时时间。
    • poolName
      接收字符串值,默认值为自动生成。此属性为连接池设置用户自定义的名称,并会在日志中显示。设置连接池名称主要是为了配合 JMX 在控制台日志中区分不同的连接池和连接池配置。注意,通过我们实践发现,如果需要配合使用 JMX,最好设置自定义的连接池名称。使用默认的自动生成的连接池名称有可能会出现意想不到的问题。
    • prepStmtCacheSize
      接收数值,默认为25。此属性设置 MySQL 驱动在每个连接会缓存的 Prepared Statement 数量。推荐设为250到500之间。
    • prepStmtCacheSqlLimit
      接收数值。此属性为 MySQL 驱动缓存的 Prepared SQL statement 的最大长度。MySQL 默认为256。此默认值远远小于生成的语句长度,推荐将其设置为2048。
    • cachePrepStmts
      布尔值,默认为 false。打开预处理语句缓存。如果为 false,prepStmtCacheSize 和 prepStmtCacheSqlLimit 都不会起作用。
    • useServerPrepStmts
      布尔值。新版的 MySQL 支持服务端预处理语句,这可以极大的提高性能。新版MySQL建议设置为 true。

    spring boot with HikariCP

    initialSize:默认值是 0,连接池创建连接的初始连接数目。
    minIdle : 默认是 0,连接数中最小空闲连接数。
    maxIdle : 默认是 8,连接池中最大空闲连接数。
    maxActive : 默认值是 8, 连接池中同时可以分派的最大活跃连接数。
    maxWait : 默认值是无限大,当连接池中连接已经用完,等待建立一个新连接的最大毫秒数 ( 在抛异常之前 )。
    validationQuery : 一条 sql 语句,用来验证数据库连接是否正常。这条语句必须是一个查询模式,并至少返回一条数据。一般用“ select 1 ”。
    minEvictableIdleTimeMilis : 默认值是 1000 * 60 * 30(30 分钟 ) 单位毫秒,连接池中连接可空闲的时间。
    timeBetweenEvictionRunsMilis : 默认值是 -1 ,每隔一段多少毫秒跑一次回收空闲线程的线程。
    对于minEvictableIdleTimeMilis、timeBetweenEvictionRunsMilis这两个参数,timeBetweenEvictionRunsMilis必须大于1且小于minEvictableIdleTimeMilis,建议是minEvictableIdleTimeMilis的五分之一或十分之一。

    HikariCP v.s. Druid

    不具有可比性,HikariCP 追求性能,Druid 偏向监控;druid 默认开启公平锁导致性能下降,有阿里生产环境大数据验证。
    参考:issue

    其他工具

    flexy-pool

    GitHub
    GitHub-wiki
    tutorials

    FlexyPool adds metrics and fail-over strategies to a given Connection Pool, allowing it to resize on demand.
    大意:增加监控,容错,和自适应调整参数功能。

    从其GitHub源码组织结构,即可得知,根据不同的连接池工具,引用不同的依赖。

    优化

    数据库连接池本质上是一种缓存,它是一种抗高并发的手段。数据库连接池优化主要是对参数进行优化,DBCP连接池的具体参数如下(其他各种连接池的配置参数大同小异,需要区别对待):

    • initialSize:初始连接数,第一次getConnection的,而不是应用启动时。初始值可以设置为并发量的历史平均值;
    • minIdle:最小保留的空闲连接数。DBCP会在后台开启一个回收空闲连接的线程,当该线程进行空闲连接回收的时候,会保留minIdle个连接数。一般设置为5,并发量实在很小可以设置为1.
    • maxIdle:最大保留的空闲连接数,按照业务并发高峰设置。比如并发高峰为20,那么当高峰过去后,这些连接不会马上被回收,如果过一小段时间又来一个高峰,那么连接池就可以复用这些空闲连接而不需要频繁创建和关闭连接。
    • maxActive:最大活跃连接数,按照可以接受的并发极值设置。比如单机并发量可接受的极值是100,那么这个maxActive设置成100后,就只能同时为100个请求服务,多余的请求会在最大等待时间之后被抛弃。这个值必须设置,可以防止恶意的并发攻击,保护数据库。
    • maxWait:获取连接的最大等待时间,建议设置的短一点,比如3s,这样可以让请求快速失败,因为一个请求在等待获取连接的时候,线程是不可以被释放的,而单机的线程并发量是有限的,如果这个时间设置的过长,比如网上建议的60s,那么这个线程在这60s内是无法被释放的,只要这种请求一多,应用的可用线程就少了,服务就变得不可用了。
    • minEvictableIdleTimeMillis:连接保持空闲而不被回收的时间,默认30分钟。
    • validationQuery:检测连接是否有效的sql语句,建议设置;
    • testOnBorrow:申请连接的时候对连接进行检测,不建议开启,严重影响性能;
    • testOnReturn:归还连接的时候对连接进行检测,不建议开启,严重影响性能;
    • testWhileIdle:开启以后,后台清理连接的线程会没隔一段时间对空闲连接进行validateObject,如果连接失效则会进行清除,不影响性能,建议开启;
    • numTestsPerEvictionRun:代表每次检查链接的数量,建议设置和maxActive一样大,这样每次可以有效检查所有的链接;
    • 预热连接池:对于连接池,建议在启动应用的时候进行预热,在还未对外提供访问之前进行简单的sql查询,让连接池充满必要的连接数。

    参考:
    JDBC驱动程序类型
    MySQL之长连接、短连接、连接池
    the-anatomy-of-connection-pooling
    数据库连接池极简教程
    高性能数据库连接池的内幕
    五大理由分析Springboot 2.0为什么选择HikariCP

    展开全文
  • 本篇内容综合广大网友提供内容,笔者经过整理,对数据库连接池原理和实现过程做个很系统的并且通俗易懂的分析讲解,以及手写一个连接池实现过程作为演示。 一、早期通过JDBC方式操作数据库 我们先来看早期使用JDBC...

    本篇内容综合广大网友提供内容,笔者经过整理,对数据库连接池原理和实现过程做个很系统的并且通俗易懂的分析讲解,以及手写一个连接池实现过程作为演示。

    一、早期通过JDBC方式操作数据库

    我们先来看早期使用JDBC的方式操作数据库的过程,这里以mysql数据库为例讲解

    JDBC操作数据库原理:一般来说,java应用程序访问数据库的过程是:

       ①装载数据库驱动程序;

       ②通过jdbc建立数据库连接;

       ③访问数据库,执行sql语句;

       ④断开数据库连接。

    1、具体的代码实现步骤

    创建数据库配置文件db.properties ,配置文件内容如下:

    #连接数据库的url,test表示数据库名,useUnicode=true表示使用Unicode字符集
    url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8; 
    #用户名
    user=root
    #密码
    password=root
    #MySQL数据库加载驱动
    driverClass=com.mysql.jdbc.Driver

    定义一个使用jdbc连接数据库的工具类JdbcUtil.java

    public class JdbcUtil{
        //定义全局变量
        private static String url = null;
        private static String user = null;
        private static String password = null;
        private static driverClass = null;
        //读取配置文件内容,放在静态代码块中就行,因为只需要加载一次就可以了
        static{
            try{
                Properties props = new Properties();
                //使用类路径加载的方式读取配置文件
                //读取的文件路径要以“/”开头,使用"/"开头会直接定位到工程的src路径下
                InputStream in = JdbcUtil.class.getResourceAsStream("/db.properties");
                //加载配置文件
                props.load(in);
                //读取配置文件信息
                url = props.getProperty("url");
                user = props.getProperty("user");
                password = props.getProperty("password");
                driverClass = props.getProperty("driverClass");
                //动态注册mysql驱动程序
                Class.forName(driverClass);
                System.out.println("成功加载MySQL驱动程序");
            }catch(Exception e){
                e.printStackTrace();
                System.out.println("mysql驱动程序注册失败!!!");
            }
        }
    
        //获取连接对象Connection
        public static Connection getConnection(){
            try{
                //要连接数据库,需要向java.sql.DriverManager请求并获得Connection对象
                return DriverManager.getConnection(url,user,password);
            }catch(SQLException e){
                e.printStackTrace();
                //抛出运行时异常
                throw new RuntimeException();
            }
        }
    
        //关闭连接的方法,后打开的先关闭
        public static void close(Connection conn,Statement stmt,ResultSet rs){
            //关闭ResultSet对象
            if(rs != null){
                try{
                    //关闭rs,设置rs=null,因为java会优先回收值为null的变量
                    rs.close();
                    rs = null;
                }catch(SQLException e){
                    e.printStackTrace();
                    throw new RuntimeException();
                }
            }
            //关闭Statement对象,因为PrepareStatement和CallableStatement都是Statement的子接口,所以这里只需要有关闭Statement对象的方法就可以了
            if(stmt != null){
                try{
                    stmt.close();
                    stmt = null;
                }catch(SQLException e){
                    e.printStackTrace();
                    throw new RuntimeException();
                }
            }
            //关闭Connection对象
            if(conn != null){
                try{
                    conn.close();
                    conn = null;
                }catch(SQLException e){
                    e.printStackTrace();
                    throw new RuntimeException();
                }
            }
        }
    }

    到此,这是一个完整的使用JDBC方式操作数据库的过程,下面我们新建一个测试类TestConn.java 测试一下

    package demo;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import utils.JdbcUtil;
    
    public class TestConn {
    
    	public static void main(String[] args) {
    	// TODO Auto-generated method stub
    	Connection conn = JdbcUtil.getConnection();
    	  try {
    		Statement stmt = conn.createStatement();
    		ResultSet rs = stmt.executeQuery("SELECT * FROM user") ;
    		//使用结果集(ResultSet)对象的访问方法获取数据:
    		 while(rs.next()){   
    	         String name = rs.getString("name") ; 
    	         System.out.println(name);
    	         String pass = rs.getString(1);//此方法比较高效,列是从左到右编号的,并且从列1开始 
    	         System.out.println(pass);
    	     } 
    		 //操作完成以后关闭JDBC对象,要把所有使用的JDBC对象全都关闭,以释放JDBC资源,关闭顺序和声明顺序相反: 
    		 //关闭顺序1、关闭记录集,2、关闭声明,3、关闭连接对象
    		 JdbcUtil.close(conn, stmt, rs);
    	  } catch (SQLException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	  }
    	}
    }
    

    2、分析

           程序开发过程中,存在很多问题:首先,每一次web请求都要建立一次数据库连接。建立连接是一个费时的活动,每次都得花费0.05s~1s的时间,而且系统还要分配内存资源。这个时间对于一次或几次数据库操作,或许感觉不出系统有多大的开销。可是对于现在的web应用,尤其是大型电子商务网站,同时有几百人甚至几千人在线是很正常的事。在这种情况下,频繁的进行数据库连接操作势必占用很多的系统资源,网站的响应速度必定下降,严重的甚至会造成服务器的崩溃。不是危言耸听,这就是制约某些电子商务网站发展的技术瓶颈问题。其次,对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将不得不重启数据库。还有,这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。

           上述的用户查询案例,如果同时有1000人访问,就会不断的有数据库连接、断开操作:

    通过上面的分析,我们可以看出来,“数据库连接”是一种稀缺的资源,为了保障网站的正常使用,应该对其进行妥善管理。其实我们查询完数据库后,如果不关闭连接,而是暂时存放起来,当别人使用时,把这个连接给他们使用。就避免了一次建立数据库连接和断开的操作时间消耗。原理如下:

    二、技术演进出来的数据库连接池

           由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理。我们知道,对于共享资源,有一个很著名的设计模式:资源池(resource pool)。该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。

           我们自己尝试开发一个连接池,来为上面的查询业务提供数据库连接服务:

           ①   编写class 实现DataSource 接口

           ②   在class构造器一次性创建10个连接,将连接保存LinkedList中

           ③   实现getConnection  从 LinkedList中返回一个连接

           ④   提供将连接放回连接池中方法

    1、实现mysql数据库连接池代码 

    public class MyDataSource implements DataSource {
        //链表实现栈结构
        privateLinkedList<Connection> dataSources = new LinkedList<Connection>();
        //无参构造器,初始化连接数量
        public MyDataSource() {
             //一次性创建10个连接
             for(int i = 0; i < 10; i++) {
                try {
                  //1、获取数据库连接对象
                  Connection conn = JdbcUtil.getConnection();
                  //2、将连接加入连接池中
                  dataSources.add(con);
                } catch (Exception e) {
                  e.printStackTrace();
              }
           }
         }
     
         @Override
         public Connection getConnection() throws SQLException {
             //取出连接池中一个连接
             final Connection conn = dataSources.removeFirst(); //删除第一个连接返回
             return conn;
         }
     
         //将连接放回连接池
         public void releaseConnection(Connection conn) {
             dataSources.add(conn);
         }
    }
    

    这就是数据库连接池的原理,它大大提供了数据库连接的利用率,减小了内存吞吐的开销。我们在开发过程中,我们只关注我们的业务代码的开发,就不需要再关心数据库连接的问题,自然有数据库连接池帮助我们处理。但连接池需要考虑的问题不仅仅如此,还有更多问题需要考虑,在下一节内容中具体分享。

    欢迎广大开发者朋友交流,学习,笔者电话(微信):18629374628

    展开全文
  • JAVA之JDBC数据库连接池(超详细介绍)

    千次阅读 多人点赞 2020-07-09 16:34:50
    JDBC数据库连接池一、JDBC数据库连接池的必要性二、数据库连接池技术三、多种开源的数据库连接池3.1 C3P0数据库连接池3.2 DBCP数据库连接池3.3 Druid(德鲁伊)数据库连接池 一、JDBC数据库连接池的必要性 1、在使用...
  • 几种常用数据库连接池的使用

    万次阅读 多人点赞 2019-02-14 12:38:38
    一、应用程序直接获取数据库连接的缺点  用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的...
  • 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。 为什么要使用连接池  数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用...
  • 数据库连接池大小到底多少合适?

    万次阅读 2020-06-09 11:59:22
    基本上来说,大部分项目都需要跟数据库做交互,那么,数据库连接池的大小设置成多大合适呢? 一些开发老鸟可能还会告诉你:没关系,尽量设置的大些,比如设置成 200,这样数据库性能会高些,吞吐量也会大些! 你也许...
  • 1.SpringBoot的数据库连接池的相关默认 springBoot之前的版本默认使用的是Tomcat的数据库连接池 较新的版本2点多(具体多少我看看)默认使用的是Hikari(我使用的是2.2.1) 默认支持数据库连接池: Tomcat ...
  • Druid数据库连接

    万次阅读 多人点赞 2019-04-02 23:00:32
    什么是数据库连接池: 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库连接池...
  • MySql数据库连接

    万次阅读 2018-03-10 16:17:13
    官方:数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对连接池中的连接进行申请,使用,释放。 理解:创建数据库连接池是一个很耗时的操作,也...
  • java中几个主流的数据库连接

    万次阅读 多人点赞 2018-08-12 19:12:03
    这里所说的池是一种广义上的池,比如数据库连接池、线程池、内存池、对象池等。其中,对象池可以看成保存对象的容器,在进程初始化时创建一定数量的对象。需要时直接从池中取出一个空闲对象,用完后并不直接释放掉...
  • 数据库连接池 1、什么是数据库连接池? 数据库连接池(Database Connection Pooling)在程序初始化时创建一定数量的数据库连接对象并将其保存在一块内存区中,它允许应用程序重复使用一个现有的数据库连接,而...
  • Springboot+druid数据库连接池使用

    万次阅读 多人点赞 2018-06-08 17:23:10
    1. 为什么要使用数据库连接池 使用数据库连接池主要考虑到程序与数据库建立连接的性能。创建一个新的数据库是一个很耗时的过程,在使用完之后,可能还需要不断的释放建立的连接,对资源的损耗大。 而采用数据库...
  • Python 数据库连接

    千次阅读 2018-09-11 22:21:05
    python编程中可以使用pymysql进行数据库连接及增删改查操作,但每次连接mysql请求时,都是独立的去请求访问,比较浪费资源,而且访问数量达到一定数量时,对mysql的性能会产生较大的影响。因此实际使用中,通常会...
  • JDBC是Java数据连接技术(Java Database Connection)的简称,提供连接各种常用数据库的能力。 •JDBC驱动由数据库厂商提供 –在个人开发与测试中,可以使用JDBC-ODBC桥连方式 –在生产型开发中,推荐使用纯Java...
  • 【mysql调优】数据库连接池配置优化

    千次阅读 2020-03-27 23:02:23
    在性能调优过程中,通过监控数据经常发现接口花费大量时间在获取数据库连接中,那如何通过优化数据库连接池的配置来优化服务的性能呢? 什么是数据库连接池 创建数据库连接是一个很耗时的操作,也容易对数据库造成...
  • 数据库连接JDBC与数据库连接池c3p0、dhcp的关系

    千次阅读 多人点赞 2018-05-13 20:50:07
    数据库连接JDBC在Java中,数据库存取技术可分为如下几类:JDBC直接访问数据库JDO技术第三方O/R工具,如Hibernate, ibatis 等JDBC是java访问数据库的基石,JDO, Hibernate等只是更好的封装了JDBC。JDBC(Java Database...
  • 数据库连接超时问题

    千次阅读 2019-06-19 17:02:48
    数据库连接强行断开,但是web应用不知道数据库已经断开(或者理解为连接池子不知道数据库已经断开),还是通过连接池子连接数据库与数据库的交互,这样会导致如上错误。 解决方案: 1.查询mysql数据库的非交互...
  • 我们在学习工作中可能常使用Hibernate、Mybatis、jpa等等框架,这些框架都对数据库连接池有很好的封装,可能忽略了数据库底层的实现,今天我们就一起来看看如何手写一个简易的数据库连接池,在此之前我们先回忆一下...
  • 数据库连接失败的原因及解决方法

    千次阅读 2020-09-05 13:20:20
    数据库连接失败的原因及解决方法
  • Java数据库连接池实现原理

    万次阅读 多人点赞 2016-05-29 16:33:02
     ②通过jdbc建立数据库连接;  ③访问数据库,执行sql语句;  ④断开数据库连接。 public class DBConnection { private Connection con; //定义数据库连接类对象 private PreparedStatement pstm; pr
  • 代码实现数据库连接

    千次阅读 2017-02-09 21:47:47
    数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放。 大家可以想一下,如果项目中没有数据库连接池会是一个什么样...
  • Mybatis深入之数据库连接池原理

    万次阅读 多人点赞 2015-06-23 22:34:43
    Mybatis深入之数据库连接池原理简介主要记录Mybatis数据库连接池实现原理、如何使用连接池来管理数据库连接的、连接池如何向外提供数据库连接、当外部调用使用完成之后是如何将数据库连接放回数据库连接池的。
  • 真实环境prod中的系统,我们该如何设置数据库连接池的大小呢? 一些所谓的开发老鸟可能会肯定的告诉你:没关系,尽量设置的大些,比如设置成200,这样数据库性能会高些,吞吐量也会大些! 对于菜鸟的你,也许认为好像...
  • 今天主要介绍几款常见的数据库连接池 并且对它们的使用做一个总结,本篇文章是以SpringBoot 项目为例,一起随着小编看一下吧! 在文章的开始,提出一个问题: 一.为什么要使用数据库连接池? 影响一个系统使用...
  • es数据库连接

    千次阅读 2020-01-07 13:27:35
    使用linux连接es数据库: 登陆linux(安装es的linux); 查询所有索引: curl -XGET ‘http://192.168.146.106:9200/_cat/indices?v’ 删除某个索引: curl -XDELETE ‘http://192.168.146.106:9200/索引名称?...
  • Hive数据库连接-连接池实现

    千次阅读 2018-11-15 16:36:36
    Hive数据库连接-连接池实现 通过HiveJDBC获取Hive的连接Connection,下面我们简单介绍HiveJDBC数据库连接实现 HiveJDBC配置文件 连接池配置文件hive-jdbc.properties # 初始化连接池数 db.jdbcPoolInitSize=5 ...
  • 常用的三种数据库连接

    千次阅读 2017-12-28 16:11:55
    1.数据库连接池的概念 数据库连接池概述:  数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个 应用程序的伸缩性和健壮性,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,147,287
精华内容 858,914
关键字:

数据库的连接