不可共享和可共享连接

应用程序服务器支持不可共享和可共享的连接。 应用程序中其他组件不能共享不可共享连接。 使用此连接的组件全权控制此连接。

访问标记为不可共享的资源意味着组件使用的连接句柄和该句柄所关联的物理连接之间存在着一对一的关系。 此访问意味着对 getConnection 方法的每次调用仅为请求用户返回连接句柄。 通常,如果您对连接执行的操作可能导致另一个共享此连接的应用程序发生意外的行为(例如,意外地更改隔离级别),那么您必须选择“不可共享”。

将资源标记为“可共享”就能有更大的可伸缩性。 只要每个 getConnection 请求都具有相同的连接属性,就能通过多个连接句柄共享物理连接(即,受管连接),而不必每次调用 getConnection() 时都从连接池中检索新的物理连接。 但是,共享连接意味着任何用户都不能对连接执行可能更改其行为及破坏共享合作伙伴的任何操作(例如,更改隔离级别)。 由于是由运行时来决定是否共享特定的连接,因此用户也不能编写假定进行共享的应用程序的代码。

连接属性要求

要允许在同一事务中使用连接共享,以下数据源属性必须相同:
  • Java™ 命名和目录接口 (JNDI) 名称。 实际上它不是连接属性,此要求仅表示您只能共享同一服务器中相同数据源的连接。
  • 资源认证
  • 关系数据库中:
    • 隔离级别(符合应用于 CMP Bean 的访问意向策略)
    • 只读
    • Catalog
    • 类型映射

有关与 CMP Bean 共享连接的更多信息,请参阅“与 CMP Bean 共享连接”主题。

要允许在同一个事务中共享连接,连接工厂的以下属性必须相同:
  • JNDI 名称。 实际上它不是连接属性,此要求仅表示您只能共享同一服务器中相同连接工厂的连接。
  • 资源认证
此外,用来获取连接的 ConnectionSpec 对象也必须相同。
注: 无法与非 JMS 连接共享 Java 消息服务 (JMS) 连接。

无法共享 IBM® MQ JMS 提供程序的 JMS 连接,因为它们是非事务性连接,并且 Java™ EE 连接器体系结构 (JCA) 规范仅允许可共享事务性资源。 如果在 JMS 资源引用中将 res-sharing-scope 设置为可共享,那么将忽略此设置,将使用不可共享的连接。 但是,MQ 的 JMS 会话是事务性的,可以共享。 缺省情况下,JMS 会话可共享,APAR PK59605 能够指定不可共享的会话。

缺省消息传递提供程序的 JMS 连接不同。 借助缺省消息传递提供程序,可以共享连接。 另一方面,会话不是由连接池管理,因此,无法共享或者不可共享。

与 CMP Bean 共享连接

应用程序服务器允许在 CMP Bean、BMP Bean 和 JDBC 应用程序之间共享物理连接,从而减少资源分配或死锁的问题。 有几种方法可用于确保所有这些实体 Bean 能与 JDBC 应用程序共享同一物理连接。
  • 在 CMP Bean 或方法之间共享连接

    当所有 CMP Bean 方法都使用同一访问意向时,它们都共享同一物理连接。 不同的访问意向策略将触发不同的物理连接分配。 例如,CMP Bean 有两种方法;第一种方法与 wsPessimisticUpdate 意向相关联,而第二个具有 wsOptimisticUpdate 访问意向。 这样,第一种方法和第二种方法就不能在事务中共享同一物理连接。 换言之,就是需要在全局事务中运行 XA 数据源。

    当这两种方法都尝试访问同一个表时,会遇到数据库死锁的问题。 因此,共享连接是由 CMP 方法中定义的访问意向确定的。

  • 在 CMP Bean 和 BMP Bean 之间共享连接

    请记住,首先要验证设置相同连接属性的 BMP Bean 和 CMP Bean 的 getConnection 方法。 要与 CMP Bean 资源的认证类型匹配,请将 BMP Bean 资源的认证类型设置为容器管理的 (在部署描述符中指定为 res-auth = Container)。

    此外,使用下列其中一个选项来确保 Bean 类型之间的连接共享:
    • 在 CMP Bean 方法和 BMP Bean 方法上定义相同的访问意向。 由于使用了相同的访问意向,它们就能共享同一物理连接。 使用此选项的优点在于后端对于 BMP Bean 是透明的。 但是,此选项也使 BMP 不可移植,因为它使用 WebSphere® 扩展 API 来处理隔离级别。 有关更多信息,请参阅主题 "示例: 使用 IBM 扩展 API 访问数据以在容器管理的持久性 Bean 和 Bean 管理的持久性 Bean 之间共享连接" 中的代码示例。
    • 确定 CMP Bean 方法上访问意向使用的隔离级别,然后使用对资源引用指定的相应隔离级别来查找数据源和连接。 选择使用此方法时更多采用的是手动处理,且不同数据库的隔离级别可能也不相同。 有关更多信息,请参阅主题“访问意向隔离级别和更新锁定”和主题“隔离级别和资源引用”部分中的隔离级别和访问意向映射表。
  • 在 CMP 和 Servlet 或会话 Bean 使用的 JDBC 应用程序之间共享连接确定访问意向在 CMP Bean 方法上使用的隔离级别,然后使用对资源引用指定的相应隔离级别来查找数据源和连接。 有关更多信息,请参阅主题“访问意向隔离级别”和主题“隔离级别和资源引用”部分。

确定共享的因子

此处的列表不是详尽的列表。 产品在不同环境下可能共享连接也可能不共享连接。
  • 仅用相同的资源引用 (resource-ref)(它将 res-sharing-scope 指定为“可共享”)获取的连接才有可能进行共享。 res-sharing-scope 和 res-auth 的资源引用属性以及 IBM 扩展 isolationLevel 帮助确定是否可以共享连接。 IBM 扩展 isolationLevel 存储在 IBM 部署描述符扩展文件中; 例如 :ibm-ejb-jar-ext.xmi。
    受支持的配置: 对于 IBM 扩展和绑定文件,根据您是使用Java EE 5 之前的应用程序或模块,还是使用 Java EE 5 或更高版本的应用程序或模块, .xmi.xml 文件扩展名有所不同。 IBM 扩展或绑定文件名为 ibm-*-ext.xmiibm-*-bnd.xmi ,其中 * 是扩展或绑定文件的类型,例如 appapplicationejb-jarweb。 存在下列条件:
    • 对于使用版本 5 之前的 Java EE 版本的应用程序或模块,文件扩展名必须为 .xmi
    • 对于使用 Java EE 5 或更高版本的应用程序或模块,文件扩展名必须为 .xml。 如果应用程序或模块随附 .xmi 文件,那么产品会忽略 .xmi 文件。

    但是, Java EE 5 或更高版本的模块可以存在于包含Java EE 5 之前的文件并使用 .xmi 文件扩展名的应用程序中。

    ibm-webservices-ext.xmiibm-webservices-bnd.xmiibm-webservicesclient-bnd.xmiibm-webservicesclient-ext.xmiibm-portlet-ext.xmi 文件继续使用 .xmi 文件扩展名。

  • 您只能共享使用相同属性请求的连接。
  • 只有不同的组件实例位于同一个事务(容器或用户启动的事务)中时,才能在它们之间共享连接。
  • 仅在共享范围内共享连接。 当前 ® 共享边界包括 事务LocalTransactionContainment (LTC) 边界。
  • LTC 范围中的连接共享规则:
    • 对于可共享的连接,在单个组件实例中仅允许连接复用。 当对连接进行以下操作时发生连接复用:获取、使用、落实/回滚、关闭;获取、使用、落实/回滚、关闭。 注意,如果您使用 ContainerAtBoundary 的 LTC 解析控制,那么由于该操作是由容器处理的,因此无需任何启动/落实。

      第二次获取返回的连接与第一次获取返回的连接相同(如果使用相同的属性)。 因为串行使用连接,所以一次只使用基本物理连接的一个连接句柄,这样并不发生真正的连接共享。 术语“复用”更准确。

      更为重要的是,包含两次获取操作的 LocalTransactionContainment 范围不完整;在 ManagedConnection 对象上未调用 cleanUp() 方法。 因此第二次获取操作继承了在第一次 getConnection() 调用期间设置的所有连接属性。

  • 事务(容器管理的事务 (CMT),Bean 管理的事务 (BMT) 或 LTC 事务)之间的可共享连接遵循以下高速缓存规则:
    • 总之,因为一个连接句柄的用户不可能预期另一个连接句柄用户将做什么更改,因此不允许在可共享的连接上设置属性。 此限制是 Java Platform, Enterprise Edition (Java EE) 标准的一部分。
    • 资源适配器的普通用户可以通过在 ConnectionSpec 中传递连接属性以在连接工厂 getConnection() 调用上设置这些属性。

      然而,在某事务期间设置的连接属性,不能保证在下一事务中使用时还是原样。 因为在共享作用域外共享连接是无效的,事务结束时连接句柄从当前与其相关联的物理连接上移出。 该物理连接返回到空闲连接池。 进入空闲池之前清除连接句柄。 下次使用句柄时,它自动与适当的连接相关联。 连接的适当性基于安全性登录信息、连接属性和扩展资源引用中指定的隔离级别(对于 JDBC API),它们是在返回当前句柄的原始请求中传递的。 连接上设置的任何属性在获取后都将丢失。

    • 对于 JDBC 用户,应用程序服务器提供了一个扩展,该扩展使您能够通过 ConnectionSpec 传递连接属性。

      在局部事务作用域中设置属性和共享连接时必须谨慎。 确保您设置产生的行为是共享此连接的其他组件所期待的。

  • 您无法使用全局事务中的关系资源适配器来为 JDBC API 设置可共享连接的隔离级别。 产品为资源引用提供扩展以使您能指定隔离级别。 如果您的应用程序需要使用多个隔离级别,那么创建多个资源引用,并将它们映射至同一数据源或连接工厂。

最大连接共享

要使应用程序拥有最多的连接共享机会,请确保将每个组件的局部事务包含 (LTC) 解析器属性设置为 ContainerAtBoundary。 此设置指定是组件容器而不是应用程序代码解析 LTC 范围中的所有资源管理器局部事务 (RMLT)。 第一次在 LTC 范围内使用连接时,容器将开始 RMLT,并且会在 LTC 范围末尾自动完成它。

请参阅主题“配置事务部署属性”以获取有关设置事务解析控制和其他属性的指示信息。

连接共享违例

只要操作违反了共享需求,资源适配器就可能发出新的异常,即共享违例异常。 可能的违例包含更改连接属性、安全设置或隔离级别。 针对受管连接执行此类可变操作的情况下,在以下两个条件成立时,可能会发生共享违例异常:
  • 与受管连接相关联的连接句柄数大于一。
  • 受管连接与局部事务或 XA 事务相关联。

根据受管连接变为不可共享连接的时间和方式,组件和 J2C 运行时可能都需要检测此共享违例异常。 如果是由于通过连接句柄进行的操作(例如,更改隔离级别),受管连接才变为不可共享连接,那么该组件需要处理此异常。 如果由于某个组件与连接句柄的交互,受管连接在没有被应用程序服务器认可的情况下变为不可共享连接,那么资源适配器可通过发出共享违例异常来拒绝创建连接句柄。