连接池
在 Mybatis 中,数据源 dataSource 共有三类,分别是:
UNPOOLED : 不使用连接池的数据源。采用传统的 javax.sql.DataSource 规范中的连接池,Mybatis 中有针对规范的实现
POOLED : 使用连接池的数据源。采用池的思想
JNDI : 使用 JNDI 实现的数据源,采用服务器提供的 JNDI 技术实现,来获取 DataSource 对象,不同的服务器所能拿到的 DataSource 是不一样的。(如果不是web或者maven的war工程,是不能使用的,tomcat-dbcp连接池:因为需要相应的代码需要在服务器端才能启动,连接池连接的数据源是部署在服务器上的,如tomcat你可以在servlet或者jsp(最终还是会转换成servlet)上进行sqlsession的创建才能在jndi上getConnection到相应的connection,通过浏览器或客户端对服务器的访问调用了服务器上部署的有相应需要连接数据库的方法,才能调用服务器连接的数据库源)
连接池和线程池:
连接池:(降低物理连接损耗)
1、连接池是面向数据库连接的
2、连接池是为了优化数据库连接资源
3、连接池有点类似在客户端做优化数据库连接是一项有限的昂贵资源,一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的性能低下。 数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由应用程序动态地对池中的连接进行申请、使用和释放。对于多于连接池中连接数的并发请求,应该在请求队列中排队等待。并且应用程序可以根据池中连接的使用率,动态增加或减少池中的连接数。
线程池:(降低线程创建销毁损耗)
1.、线程池是面向后台程序的
2、线程池是是为了提高内存和CPU效率
3、线程池有点类似于在服务端做优化线程池是一次性创建一定数量的线程(应该可以配置初始线程数量的),当用请求过来不用去创建新的线程,直接使用已创建的线程,使用后又放回到线程池中。
避免了频繁创建线程,及销毁线程的系统开销,提高是内存和CPU效率。相同点:
都是事先准备好资源,避免频繁创建和销毁的代价。扩展:
对象池:
对象池技术基本原理的核心有两点:缓存和共享,即对于那些被频繁使用的对象,在使用完后,不立即将它们释放,而是将它们缓存起来,以供后续的应用程序重复使用,从而减少创建对象和释放对象的次数,进而改善应用程序的性能。事实上,由于对象池技术将对象限制在一定的数量,也有效地减少了应用程序内存上的开销。对于两者是否有联系:
- 首先,每个连接要启动,都需要依赖于一个线程的调用,否则,即使连接在连接池里,没有断开连接,也无法做出行为
- 当线程使用完时,会将连接与线程解绑交还于连接池
- 一般会是多个连接并发执行,即需要多个线程,因此前面也有线程池的管理
- 每个连接都是线程安全的,用synchronized锁住
while(conn == null) { synchronized(this.state) { PoolState var10000; if (!this.state.idleConnections.isEmpty()) { conn = (PooledConnection)this.state.idleConnections.remove(0); if (log.isDebugEnabled()) { log.debug("Checked out connection " + conn.getRealHashCode() + " from pool."); } } else if (this.state.activeConnections.size() < this.poolMaximumActiveConnections) { conn = new PooledConnection(this.dataSource.getConnection(), this); if (log.isDebugEnabled()) { log.debug("Created connection " + conn.getRealHashCode() + "."); } } else { PooledConnection oldestActiveConnection = (PooledConnection)this.state.activeConnections.get(0); long longestCheckoutTime = oldestActiveConnection.getCheckoutTime(); if (longestCheckoutTime > (long)this.poolMaximumCheckoutTime) { ++this.state.claimedOverdueConnectionCount; var10000 = this.state; var10000.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime; var10000 = this.state; var10000.accumulatedCheckoutTime += longestCheckoutTime; this.state.activeConnections.remove(oldestActiveConnection); if (!oldestActiveConnection.getRealConnection().getAutoCommit()) { try { oldestActiveConnection.getRealConnection().rollback(); } catch (SQLException var16) { log.debug("Bad connection. Could not roll back"); } } conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this); conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp()); conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp()); oldestActiveConnection.invalidate(); if (log.isDebugEnabled()) { log.debug("Claimed overdue connection " + conn.getRealHashCode() + "."); } } else { try { if (!countedWait) { ++this.state.hadToWaitCount; countedWait = true; } if (log.isDebugEnabled()) { log.debug("Waiting as long as " + this.poolTimeToWait + " milliseconds for connection."); } long wt = System.currentTimeMillis(); this.state.wait((long)this.poolTimeToWait); var10000 = this.state; var10000.accumulatedWaitTime += System.currentTimeMillis() - wt; } catch (InterruptedException var17) { break; } } }
- 如果想要修改 Mybatis 使用的数据源,那么就可以在 Mybatis 配置文件中修改:(这里
type
属性的取值就是为POOLED、UNPOOLED、JNDI
。)
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
查看 POOLED
的实现 PooledDataSource
,可以看出获取连接时采用了池的思想,大概流程如下图(只是一个简单介绍,不全面)
查看 UNPOOLED
的实现 UnpooledDataSource
,可以看出每次获取连接时都会注册驱动并创建新连接,大概流程如下图(只是一个简单介绍,不全面)
sqlsession、transaction、connection、sql语句的关系在下一篇文章中
https://www.cnblogs.com/eternal-heathens/p/13366799.html