↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

已结束支持的版本: 7.4 / 7.3
历史版本。 PostgreSQL 7.3 已结束支持。 请参阅 当前版本手册.

5.9. 连接池与 DataSource #

5.9.1. JDBC、JDK 版本支持 #

JDBC 2 在一个称为 JDBC 2.0 Optional Package(也称为 JDBC 2.0 Standard Extension)的附加 API 中引入了标准的连接池特性。这些特性后来被包含在核心 JDBC 3 API 中。PostgreSQL JDBC 驱动在配合 JDBC 2.0 Optional Package(JDBC 2)与 JDK 1.3.x 一起使用,或者与 JDK 1.4+(JDBC 3)一起使用时支持这些特性。大多数应用服务器都包含 JDBC 2.0 Optional Package,它也可以从 Sun 的 JDBC 下载站点单独获得。

5.9.2. JDBC 连接池 API #

JDBC API 为连接池提供了一个客户端接口和一个服务器端接口。客户端接口是 javax.sql.DataSource,应用代码通常用它来获取一个池化的数据库连接。服务器端接口是 javax.sql.ConnectionPoolDataSource,大多数应用服务器将通过它与 PostgreSQL JDBC 驱动对接。

在应用服务器环境中,应用服务器的配置通常引用 PostgreSQL 的 ConnectionPoolDataSource 实现,而应用组件代码通常获取由应用服务器(而不是 PostgreSQL)提供的 DataSource 实现。

在没有应用服务器的环境中,PostgreSQL 提供了应用程序可以直接使用的两种 DataSource 实现。一种实现执行连接池化,而另一种只是通过 DataSource 接口提供对数据库连接的访问,不做任何池化。另外,这些实现不应在应用服务器环境中使用,除非应用服务器不支持 ConnectionPoolDataSource 接口。

5.9.3. 应用服务器:ConnectionPoolDataSource #

PostgreSQL 为 JDBC 2 包含一个 ConnectionPoolDataSource 实现,为 JDBC 3 也包含一个:

表 5.1. ConnectionPoolDataSource 实现

JDBC实现类
2org.postgresql.jdbc2.optional.ConnectionPool
3org.postgresql.jdbc3.Jdbc3ConnectionPool

两种实现使用相同的配置方案。JDBC 要求 ConnectionPoolDataSource 通过 JavaBean 属性配置,因此每种属性都有相应的 get 和 set 方法:

表 5.2. ConnectionPoolDataSource 配置属性

属性类型描述
serverNameStringPostgreSQL 数据库服务器的主机名
databaseNameStringPostgreSQL 数据库名
portNumberintPostgreSQL 数据库服务器监听的 TCP/IP 端口(或者用 0 表示使用默认端口)
userString用来建立数据库连接的用户
passwordString用来建立数据库连接的口令
defaultAutoCommitboolean连接被交给调用方时,其 autoCommit 是启用还是禁用。默认值为 false,即禁用 autoCommit。

许多应用服务器使用属性风格的语法来配置这些属性,因此把属性作为一块文本输入并不罕见。

例 5.5. ConnectionPoolDataSource 配置示例

如果应用服务器提供单一区域来输入所有属性,它们可能像这样列出:

serverName=localhost
databaseName=test
user=testuser
password=testpassword

或者,用分号而不是换行符分隔,像这样:

serverName=localhost;databaseName=test;user=testuser;password=testpassword


5.9.4. 应用程序:DataSource #

PostgreSQL 为 JDBC 2 包含两种 DataSource 实现,为 JDBC 3 也包含两种。池化实现在客户端调用 close 方法时实际上并不关闭连接,而是把连接归还到一个可供其他客户端使用的空闲连接池中。这避免了反复打开和关闭连接的任何开销,并允许大量客户端共享少量数据库连接。

这里提供的池化 datasource 实现并不是世界上功能最丰富的。举几个方面:连接直到池本身关闭之前永远不会被关闭;没有办法收缩池。而且,为默认配置用户之外的用户请求的连接不会被池化。许多应用服务器提供更高级的池化特性,并改用 ConnectionPoolDataSource 实现。

表 5.3. DataSource 实现

JDBC是否池化实现类
2否org.postgresql.jdbc2.optional.SimpleDataSource
2是org.postgresql.jdbc2.optional.PoolingDataSource
3否org.postgresql.jdbc3.Jdbc3SimpleDataSource
3是org.postgresql.jdbc3.Jdbc3PoolingDataSource

所有实现都使用相同的配置方案。JDBC 要求 DataSource 通过 JavaBean 属性配置,因此每种属性都有相应的 get 和 set 方法。

表 5.4. DataSource 配置属性

属性类型描述
serverNameStringPostgreSQL 数据库服务器的主机名
databaseNameStringPostgreSQL 数据库名
portNumberintPostgreSQL 数据库服务器监听的 TCP/IP 端口(或者用 0 表示使用默认端口)
userString用来建立数据库连接的用户
passwordString用来建立数据库连接的口令

池化实现需要一些额外的配置属性:

表 5.5. 池化 DataSource 的额外配置属性

属性类型描述
dataSourceNameString每个池化 DataSource 都必须有一个唯一的名称
initialConnectionsint池初始化时要创建的数据库连接数量。
maxConnectionsint允许的打开数据库连接的最大数量。当请求更多连接时,调用方将挂起,直到有连接被归还到池中。

下面是一个使用池化 DataSource 的典型应用代码的例子:

例 5.6. DataSource 代码示例

初始化一个池化 DataSource 的代码可能像这样:

Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource();
source.setDataSourceName("A Data Source");
source.setServerName("localhost");
source.setDatabaseName("test");
source.setUser("testuser");
source.setPassword("testpassword");
source.setMaxConnections(10);

然后使用池中一个连接的代码可能像这样。注意,这些连接最终被关闭是至关重要的,否则池会“泄漏”连接,并最终把所有客户端都锁在门外。

Connection con = null;
try {
    con = source.getConnection();
    // use connection
} catch(SQLException e) {
    // log error
} finally {
    if(con != null) {
        try {con.close();}catch(SQLException e) {}
    }
}


5.9.5. DataSources 和 JNDI #

所有 ConnectionPoolDataSource 和 DataSource 实现都可以存储在 JNDI 中。对于非池化实现,每次从 JNDI 检索该对象时都会创建一个新实例,其设置与被存储的实例相同。对于池化实现,只要它可用(例如,不是从 JNDI 检索该池的另一个不同 JVM),就会检索到同一个实例,否则会用相同的设置创建一个新实例。

在应用服务器环境中,通常存储在 JNDI 中的是应用服务器的 DataSource 实例,而不是 PostgreSQL 的 ConnectionPoolDataSource 实现。

在应用程序环境中,应用程序可以把 DataSource 存储在 JNDI 中,这样它就不必把对 DataSource 的引用提供给它可能需要使用它的所有应用组件:

例 5.7. DataSource JNDI 代码示例

初始化一个池化 DataSource 并把它添加到 JNDI 的应用代码可能像这样:

Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource();
source.setDataSourceName("A Data Source");
source.setServerName("localhost");
source.setDatabaseName("test");
source.setUser("testuser");
source.setPassword("testpassword");
source.setMaxConnections(10);
new InitialContext().rebind("DataSource", source);

然后使用池中一个连接的代码可能像这样:

Connection con = null;
try {
    DataSource source = (DataSource)new InitialContext().lookup("DataSource");
    con = source.getConnection();
    // use connection
} catch(SQLException e) {
    // log error
} catch(NamingException e) {
    // DataSource wasn't found in JNDI
} finally {
    if(con != null) {
        try {con.close();}catch(SQLException e) {}
    }
}


5.9.6. 特定应用服务器的配置 #

针对特定应用服务器的配置示例将收录在这里。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.