Mybatis技术内幕读书笔记(三)Mybatis的连接池原理(PooledDataSource)

前言:

  了解JDBC 编程的读者知道,数据库连接的创建过程是非常耗时的,数据库能够建立的连接数也非常有限,所以在绝大多数系统中,数据库连接是非常珍贵的资源,使用数据库连接池就显得尤为必要。使用数据库连接池会带来很多好处,例如,可以实现数据库连接的重用、提高响应速度、防止数据库连接过多造成数据库假死、避免数据库连接泄露等。数据库连接池在初始化时, 一般会创建一定数量的数据库连接并添加到连接池中备用。当程序需要使用数据库连接时, 从池中请求连接;当程序不再使用该连接时,会将其返回到池中缓存,等待下次使用,而不是直接关闭。

  当然,数据库连接池会控制连接总数的上限以及空闲连接数的上限,如果连接池创建的总连接数己达到上限,且都己被占用,则后续请求连接的线程会进入阻塞队列等待,直到有钱程释放出可用的连接。如果连接池中空闲连接数较多,达到其上限, 则后续返回的空闲连接不会放入池中,而是直接关闭,这样可以减少系统维护多余数据库连接的开销。如果将总连接数的上限设置得过大,可能因连接数过多而导致数据库僵死,系统整体性能下降;如果总连接数上限过小,则无法完全发挥数据库的性能,浪费数据库资源。如果将空闲连接的上限设置得过大,则会浪费系统资源来维护这些空闲连接:如果空闲连接上限过小,当出现瞬间的峰值请求时,系统的快速响应能力就比较弱。所以在设置数据库连接池的这两个值时,需要进行性能测试、权衡以及一些经验。PooledDataSource 实现了简易数据库连接池的功能,其中需要注意的是, PooledDataSource 创建新数据库连接的功能是依赖其中封装的UnpooledDataSource对象实现的。

  PooledDataSource 并不会直接管理Connection 对象,而是管理PooledConnection 对象。在PooledConnection 中封装了真正的数据库连接对象( java.sql.Connection )以及其代理对象,这里的代理对象是通过JDK 动态代理产生的。

核心变量如下:

PooledConnection 中提供了上述字段的getter/setter 方法,代码比较简单。这里重点关注PooledConnection. invoke() 方法的实现,该方法是proxyConnection 这个连接代理对象的真正代理逻辑,它会对close()方法的调用进行代理,并且在调用真正数据库连接的方法之前进行检测。
代码如下:

PoolState 是用于管理PooledConnect ion 对象状态的组件,它通过两个ArrayList< Pooled Connection>集合分别管理空闲状态的连接和活跃状态的连接,定义如下:

PoolState 中还定义了一系列用于统计的字段,定义如下:

PooledDataSource中管理的真正的数据库连接对象是由PooledDataSource 中封装的UnpooledDataSource 对象创建的,并由PoolState 管理所有连接的状态。PooledDataSource 中核心字段的含义和功能如下:

//通过PoolState 管理连接池的状态并记录统计信息
private final PoolState state= new PoolState(this);
//记录Unpoo ledData Source 对象,用于生成真实的数据库连接对象,构造函数中会初始化该字段
private final UnpooledDataSource datasource;
protected int poolMaximumActiveConnections = 10; //最大活跃连接数
protected int poolMaximumidleConnections = 5 ; // 最大空闲连接数
protected int poolMaximumCheckoutTime = 20000 ;// 最大checkout 时长
protected int poolTimeToWait = 20000 ; // 在无法获取连接时,线#呈需妥等待的时间
//在检测一个数据库连接是否可用时,会给数据库发送一个测试SQL 语句
protected String poolPingQuery = ” NO PING QUERY SET ” 
protected boolean poolPingEnabled ; //是否允许发送测试SQL语句
//当连接超过poolPingConnectionsNotUsedFor毫秒未使用时,会发送一次测试SQL语句,检测连接是否正常
protected int poolPingConnectionsNotUsedFor;
//根据数据库的URL 、用户名和密码生成的一个hash 佳,该哈希值用于标志着当前的连接池,在构造函数中
初始化
private int expectedConnectionTypeCode ;

猜你喜欢

转载自blog.csdn.net/qq_36642340/article/details/81507112