|
开发人员: JDBC
保持你的连接
作者:Kuassi Mensah
利用隐含的连接高速缓存进行透明的高速缓存访问。
Oracle数据库10g中新一代Java数据库连接(JDBC)驱动器使得Java应用程序执行性能会有很大的不同。无论你是使用Java
2标准版应用程序、Servlets、JavaServer Pages、有状态的会话、企业JavaBean容器、一致性引擎,还是使用对象关系型映射框架,最新的Oracle
JDBC驱动程序都可以显著简化Java开发人员的各种数据源连接问题。在以前的一些版本中也提供了JDBC连接高速缓存,但是Oracle数据库10g添加了新水平的高速缓存。一般说来,连接高速缓存是一种在一个池中保持数目较小的物理数据库连接的方式,这个连接池由大量的并行用户共享和重新使用,从而避免在每次需要时建立一个新的物理数据库连接,以及当其被释放时关闭该连接的昂贵的操作。例如,采用这种方式,一个有100个物理数据库连接的池中可以足以供1000个并行用户共同使用。
但是,在当前的JDBC连接高速缓存规范以及以其为基础的实现中存在着一些缺点。尽管在Oracle9i第2版中的JDBC实现了很多当前的JDBC连接高速缓存规范,但这一标准存在一些局限性,这使该连接高速缓存使用起来很困难,并削弱了其优点。在Oracle数据库10g中,JDBC的实现为连接高速缓存带来了以下提高:
- 透明的高速缓存访问
- 高速缓存不同的用户/口令对
- 根据连接属性检索连接
这些改进来自于新Oracle数据库10gJDBC隐含连接高速缓存(Implicit Connection
Cache)的特性。请注意,你可以通过修改默认的设置来启用该隐含连接高速缓存的大多数功能。为了使用该隐含连接高速缓存的功能,要通过显式地设置或改变连接高速缓存的属性或连接属性来定制你的环境。
透明地高速缓存访问 默认情况下,标准OracleDataSource
API中的getConnection()方法创建一个新的数据库会话和一个连接到一个数据库的物理连接--从而损害性能和可扩展性。利用该隐含连接高速缓存功能,当DataSource的属性ConnectionCachingEnabled设置为真时,getConnection()方法为来自连接高速缓存的所有连接申请提供服务。以下命令将DataSource的属性ConnectionCachingEnabled设置为真:
ods.setConnectionCachingEnabled(True);
// optional, set name of cache
ods.setConnectionCacheName("MyCache");
// optional, set cache properties
ods.setConnectionCacheProperties(cp);
ctx.bind("MyDS", ods);
// look up DataSource
ods =(OracleDataSource) ctx.lookup("MyDS");
你可以通过首先调用getConnection()方法隐式地创建一个Oracle 数据库10gJDBC连接高速缓存,也可以通过使用高速缓存管理器API显式地创建该高速缓存。高速缓存管理器API可以由J2EE容器和企业资源计划(ERP)框架使用,后者可以使Java应用程序开发人员不必管理此连接高速缓存。利用API也可以帮助保持应用程序代码的可移植性。
以下命令可创建MyCache高速缓存和连接到MyDS数据源的一个连接:
conn = ods.getConnection();
以下命令也可创建一个MyCache高速缓存和连接到MyDS数据源的连接,但它是由用户SCOTT/TIGER验证的:
conn = ods.getConnection(
"SCOTT","TIGER");
接下来的一些getConnection()调用或者创建一个新的连接(如果先前未初始化该高速缓存的话),或者只是由该高速缓存检索一个已有的连接。一旦检索到该连接,你就可以进行语句的创建。
可以利用以下语法创建一个语句:
Statement stmt = conn.createStatement ();
...
可以利用以下语法关闭一个语句:
stmt.close();
stmt = null;
你可以用以下两种方法之一添充该高速缓存:或者通过高速缓存管理器API对其进行预初始化,或者逐步将连接释放返回到该高速缓存之后随即进行添充。以下语法将一个连接返回至该高速缓存:
conn.close();
conn = null;
高速缓存不同的用户/口令对 尽管数据库不会对多个连接标识施加任何限制,但一个传统的连接高速缓存可能会对用户/口令值施加一个这样的限制。但是,隐含连接高速缓存可以处理任何用户验证的连接。例如,一个sudhakar.krishna连接可以与同一个连接高速缓存中的john.smith连接很好地并存。
根据连接属性检索连接 隐含连接高速缓存的非常出色的新特性之一就是把连接加上条纹的概念。把连接加上条纹(或加上标记)就是将用户定义的属性应用到一个连接,并且在将该连接返回到该高速缓存时,使属性的状态的持久保持。这一加上条纹的办法可加速将来对连接的检索,因为被高速缓存的连接不必在每次被检索时都重新初始化其状态。
通过从数据源中调用getConnection(connAttr)来发出对具有特定属性和值的连接的请求。下面的几个示例显示如何利用连接属性来从高速缓存中检索具有特定属性的连接。
下面的示例根据NLS_LANG属性从高速缓存中检索一个连接:
java.util.Properties connAttr = null;
connAttr.setProperty("NLS_LANG",
"ISO-LATIN-1");
conn = ds.getConnection(connAttr);
...
下面的示例根据隔离级别(TRANSACTION_ISOLATION)和属性值(SERIALIZABLE)从高速缓存中检索一个连接,并将该连接返回到该高速缓存:
java.util.Properties connAttr = null; connAttr.setProperty( "TRANSACTION_ISOLATION",
"SERIALIZABLE" ); // retrieve connection that // matches TRANSACTION_ISOLATION
conn = ds.getConnection(connAttr); ... // preserve attribute settings
for // the connection and return it // to the connection cache conn.close(connAttr);
请注意,在将一个连接返回到该高速缓存中时,应用程序有机会保存当前的连接属性设置以备将来使用。参见下节"将连接属性应用于一个被高速缓存的连接"
,以获得关于使用conn.close(connAttr) 保存属性的信息。
下面的示例根据CONNECTION_TAG属性的值(JOE'S_CONNECTION)从高速缓存中检索一个连接,将该连接返回到高速缓存,并检索该同一连接:
...
java.util.Properties connAttr = null;
connAttr.setProperty("CONNECTION_TAG",
"JOE'S_CONNECTION"
);
// retrieve connection that
// matches JOE'S_CONNECTION
conn = ds.getConnection(connAttr);
// preserve attribute settings for
// the connection and return it
// to the connection cache
conn.close(connAttr);
// retrieve same connection
conn = ds.getConnection(connAttr);
将连接属性应用于一个被高速缓存的连接
可以采用两种方式将连接属性应用于高速缓存中的一个连接:
- 一个方法是对连接对象调用applyConnectionAttributes(java.util.Properties
connAttr)API。这样可以简单地将所提供的属性设置于连接对象。也可以通过使用这个API,逐渐应用各个属性,允许用户通过多个调用来应用连接的各个属性。例如,你可以通过从模块A调用这个API来应用NLS_LANG。然后通过从模块B发出的下一个调用来应用TRANSACTION_ISOLATION
属性,如此等等。
- 第二种方法是对连接对象调用close(java.util.Properties connAttr)API。这一API关闭逻辑连接,然后将所提供的连接属性应用于基础PooledConnection(物理连接)。通过这一close()API该属性集将对利用applyConnectionAttributes()API设置的任何属性集进行重设。
下面的示例显示对连接对象调用close(connAttr)API,它使高速缓存在将连接返回至高速缓存之前对其应用匹配的连接属性。这可以保证在发出具有相同连接属性的后续连接请求时,高速缓存可以找到一个匹配的连接。
// set attributes for connection
java.util.properties connAttr = null;
connAttr.setProperty("NLS_LANG",
"ISO-LATIN-1");
// request connection based on
// NLS_LANG attributes
conn = ds.getConnection(connAttr);
java.util.properties unmatchedAttr =
conn.getUnMatchedConnectionAttributes();
...
// preserve attribute settings for
// the connection and return it
// to the connection cache
conn.close(connAttr);
根据属性和权值检索连接 可以根据连接属性和属性权值有选择性地从连接高速缓存中检索连接。通过一次操作可将各个权值赋给一个连接属性中的每个关键字,此操作也可以改变高速缓存属性。高速缓存属性CacheAttributeWeights是java.util.Properties之一,它允许设置属性权值。各个权值是一个整数,它定义一个特定的关键字消耗资源的程度。一旦在高速缓存中权值被指定,就可以通过调用getConnection(connAttr)发出对数据源的连接请求。connAttr参量引用该关键字及其相关的值。从高速缓存中检索连接包括搜索一个满足以下条件组合的连接:
- 一个关键字/数值匹配高速缓存中的一个连接
- 匹配该连接的各个连接属性的所有关键字的最大总权值
让我们看一下代码清单1中的示例,其中使用CacheAttributeWeights配置了一个高速缓存,并发出了一个连接请求。
代码清单1中的getConnection()请求力求从MyCache
高速缓存中检索一个连接。在进行连接匹配和从高速缓存中进行检索该连接的过程中,可能发生以下两种情况之一:
- 找到一个完全匹配的连接。如代码清单1中的示例所示,一个完全匹配的连接是一个符合以下条件的连接:它具有由属性值NLS_LANG、SecurityGroup和Application所定义的全部已定义的关键字和相同的属性值。
- 未找到一个完全匹配的连接。在此情况下,可使用一个在属性关键字/值及其相关权值方面最接近匹配的连接(但是仅当设置ClosestConnectionMatch属性时如此)。例如,最接近匹配的连接可能是与NLS_LANG及Application属性匹配,但与SecurityGroup属性不匹配的一个连接。也有可能找到一些连接,它们与相同数目的不同关键字匹配,但具有不同的组合权值。例如,连接1可能具有SecurityGroup的匹配属性,其相关权值为8,Application的权值为4,总权值为12,而连接2可能具有
NLS_LANG (10)和 Application (4)的属性匹配,其组合权值为14。在此情况下,返回连接2。换言之,相对于连接1而言,连接2是最接近的匹配,而且(从调用者的角度来说)其重建成本更昂贵。在没有任何匹配的连接属性时,返回一个新的连接。利用数据源中设置的用户和口令创建一个新连接。
一旦返回该连接,用户可以对连接对象调用getUnMatchedConnectionAttributes()API,以返回一组与该标准不匹配的属性(java.util.Properties)。然后,调用者(或者应用程序)在使用此连接之前可以使用非匹配属性表先重新初始化这些数值。
结论 Oracle 数据库 10g JDBC隐含连接高速缓存极大地简化了Java/JDBC应用程序和J2EE组件的JDBC连接高速缓存。除了提供透明的缓冲访问之外,隐含连接高速缓存还提供了用于通过利用属性和权值来标记和检索连接以加速连接重用的系统。
Kuassi Mensah(kuassi.mensah@oracle.com)是Oracle公司服务器技术部的产品经理。 |