Hibernate应用程序部署在WebSphere AS 上出现记录死锁的分析与解决
有一个项目,是用Hibernate开发的部署在WebSphere Application Server 5.1下,总是会出现数据库记录被死锁的情况,即使是一个简单的更新动作,都有可能造成。
这个问题,困扰我许久,检查过所有代码,事物一定要提交或者回滚,Session及时释放,怀疑过是否是因为是部署在集群环境,但好像那些措施总于事无补,百思不得其解。
就差没有使用容器提供的事物了。
突然间想到去各自的官网,查查有没有人碰到过类似的信息,于是在 http://www.hibernate.org 网站找到了Hibernate in WAS 5.x - fixes possible deadlock problem,其中提到要定制一个 ConnectionProvider,名之为 WSDataSourceConnectionProvider,代码如下:
以上代码中类 WSRRAFactory、JDBCConnectionSpec 用到了 $WAS_HOME/lib/rsaexternal.jar;类WSJdbcConnection、WSJdbcUtil 用到了 $WAS_HOME/lib/rsadapterspi.jar,所以需要在编译时 $WAS_HOME/lib 中两那两个包引用进来。
同时,在 hibernate.cfg.xml 中要有如下配置,记得在 WAS 还需配置相应的连接池 jdbc/unmiDs。
文中又有链接提到 Sharing connections in WebSphere Application Server V5
大致说到的是,在WAS环境中Hibernate应用程序运行时可能一个事物使用的并非是同一个链接,无形中搞出个分布式事物来吧,具体情况和解决办法还有待细究,希望这个就是我想要的结果。
OK,明天再来分析上面那两篇文章吧,期望找到一个治本的解决方案。
好像与现今使用的C3P0连接池也有关系,有建议说换成最近新版的
文中 c3p0 problem 也有提到把 maxStatements 和 maxStatementsPerConnection 设置为零
c3p0.maxStatements=0
c3p0.maxStatementsPerConnection=0 永久链接 https://yanbin.blog/hibernate-was-dead-lock/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
这个问题,困扰我许久,检查过所有代码,事物一定要提交或者回滚,Session及时释放,怀疑过是否是因为是部署在集群环境,但好像那些措施总于事无补,百思不得其解。
就差没有使用容器提供的事物了。
突然间想到去各自的官网,查查有没有人碰到过类似的信息,于是在 http://www.hibernate.org 网站找到了Hibernate in WAS 5.x - fixes possible deadlock problem,其中提到要定制一个 ConnectionProvider,名之为 WSDataSourceConnectionProvider,代码如下:
1package com.unmi.db;
2
3import java.sql.Connection;
4import java.sql.SQLException;
5import java.util.Properties;
6
7import org.apache.log4j.Logger;
8import org.hibernate.HibernateException;
9import org.hibernate.cfg.Environment;
10import org.hibernate.connection.ConnectionProvider;
11import org.hibernate.util.NamingHelper;
12
13import com.ibm.websphere.rsadapter.JDBCConnectionSpec;
14import com.ibm.websphere.rsadapter.WSCallHelper;
15import com.ibm.websphere.rsadapter.WSDataSource;
16import com.ibm.websphere.rsadapter.WSRRAFactory;
17import com.ibm.ws.rsadapter.jdbc.WSJdbcConnection;
18import com.ibm.ws.rsadapter.jdbc.WSJdbcUtil;
19
20/**
21 * ConnectionProvider implementation that implements WSDataSource specific
22 * Transaction Isolation level settings for the connection. Modified from the
23 * original DatasourceConnectionProvider class by Lari Hotari
24 *
25 */
26public class WSDataSourceConnectionProvider implements ConnectionProvider {
27 public boolean supportsAggressiveRelease() {
28 return false;
29 }
30
31 private WSDataSource ds;
32 private String user;
33 private String pass;
34 private Integer isolation;
35
36 private static final Logger log = Logger
37 .getLogger(WSDataSourceConnectionProvider.class);
38
39 public void configure(Properties props) throws HibernateException {
40
41 String jndiName = props.getProperty(Environment.DATASOURCE);
42 if (jndiName == null) {
43 String msg = "datasource JNDI name was not specified by property "
44 + Environment.DATASOURCE;
45 log.fatal(msg);
46 throw new HibernateException(msg);
47 }
48
49 user = props.getProperty(Environment.USER);
50 pass = props.getProperty(Environment.PASS);
51
52 String i = props.getProperty(Environment.ISOLATION);
53 if (i == null) {
54 isolation = null;
55 } else {
56 isolation = new Integer(i);
57 log.info("JDBC isolation level: "
58 + Environment.isolationLevelToString(isolation.intValue()));
59 }
60
61 try {
62 ds = (WSDataSource) NamingHelper.getInitialContext(props).lookup(
63 jndiName);
64 } catch (Exception e) {
65 log.fatal("Could not find datasource: " + jndiName, e);
66 throw new HibernateException("Could not find datasource", e);
67 }
68 if (ds == null)
69 throw new HibernateException("Could not find datasource: "
70 + jndiName);
71 log.info("Using datasource: " + jndiName);
72 }
73
74 public Connection getConnection() throws SQLException {
75 if (log.isDebugEnabled()) {
76 log.debug("getConnection()");
77 }
78 Connection connection = ds.getConnection(createJDBCConnectionSpec());
79
80 if (log.isDebugEnabled()) {
81 if (connection != null) {
82 log.debug("Returning connection, System.identityHashCode="
83 + System.identityHashCode(connection));
84 log.debug("Connection=" + connection);
85 log.debug("Shareable=" + WSCallHelper.isShareable(connection));
86 log.debug("Class=" + connection.getClass());
87 Connection nativeConnection = (Connection) WSJdbcUtil
88 .getNativeConnection((WSJdbcConnection) connection);
89 log.debug("Native connection=" + nativeConnection);
90 log.debug("Native connection, System.identityHashCode="
91 + System.identityHashCode(nativeConnection)
92 + ", class=" + nativeConnection.getClass());
93 } else {
94 log.debug("Returning null");
95 }
96 }
97 return connection;
98 }
99
100 public void closeConnection(Connection conn) throws SQLException {
101 conn.close();
102 }
103
104 public void close() {
105 }
106
107 protected JDBCConnectionSpec createJDBCConnectionSpec() {
108 JDBCConnectionSpec connSpec = WSRRAFactory.createJDBCConnectionSpec();
109
110 // 设置事称隔离级别
111 if (isolation != null) {
112 connSpec.setTransactionIsolation(isolation);
113 }
114
115 if (user != null || pass != null) {
116 connSpec.setUserName(user);
117 connSpec.setPassword(pass);
118 }
119 return connSpec;
120 }
121}以上代码中类 WSRRAFactory、JDBCConnectionSpec 用到了 $WAS_HOME/lib/rsaexternal.jar;类WSJdbcConnection、WSJdbcUtil 用到了 $WAS_HOME/lib/rsadapterspi.jar,所以需要在编译时 $WAS_HOME/lib 中两那两个包引用进来。
同时,在 hibernate.cfg.xml 中要有如下配置,记得在 WAS 还需配置相应的连接池 jdbc/unmiDs。
1<property name="connection.datasource">jdbc/unmiDs</property>
2<property name="dialect">org.hibernate.dialect.OracleDialect</property><br/><br/>
3<property name="hibernate.connection.provider_class">
4 com.unmi.db.WSDataSourceConnectionProvider
5</property><br/><br/>
6<property name="connection.username">user</property>
7<property name="connection.password">password</property>文中又有链接提到 Sharing connections in WebSphere Application Server V5
大致说到的是,在WAS环境中Hibernate应用程序运行时可能一个事物使用的并非是同一个链接,无形中搞出个分布式事物来吧,具体情况和解决办法还有待细究,希望这个就是我想要的结果。
OK,明天再来分析上面那两篇文章吧,期望找到一个治本的解决方案。
好像与现今使用的C3P0连接池也有关系,有建议说换成最近新版的
文中 c3p0 problem 也有提到把 maxStatements 和 maxStatementsPerConnection 设置为零
c3p0.maxStatements=0
c3p0.maxStatementsPerConnection=0 永久链接 https://yanbin.blog/hibernate-was-dead-lock/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。