超时更新DB2表

时间:2013-05-13 20:51:03

标签: java sql db2

我正在对这样的DB2表进行更新(java代码):

// Some code  ripped out for brevity...
sql.append("UPDATE " + TABLE_THREADS + " ");
sql.append("SET STATUS = ? ");
sql.append("WHERE ID = ?");

conn = getConn();
pstmt = conn.prepareStatement(sql.toString());
int idx1 = 0;
pstmt.setInt(++idx1, status);
pstmt.setInt(++idx1, id);
int rowsUpdated = pstmt.executeUpdate();
return rowsUpdated;

很长一段时间后,我收到了回滚和错误消息:

UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C9008E, TYPE OF RESOURCE 00000302, AND RESOURCE NAME SOME.THING.X'000002'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.57.82

documentation for error -913说这个原因代码意味着超时。资源类型00000302是一个表空间页面,我根本无法识别资源名称。

当我自己运行SQL时,它运行正常:

UPDATE MY.THREADS
SET STATUS = 1
WHERE ID = 156

我可以SELECT并查看状态已更新。 (虽然当我在超时之前的漫长等待期间运行此SQL时,我遇到了同样的问题。这需要永远,我只是取消它。)

交易中发生了一些事情,我没有看到对此表或记录的任何其他更新。表上有创建/删除触发器,但没有更新触发器。我没有看到任何选择游标,或奇怪的隔离级别更改。我没有在交易中看到太多其他因素。

为什么我收到此错误?我还应该在交易中寻找什么呢?


编辑:

我从代码的开头逐步完成了代码“卡住”。似乎有2个DAO,它们都创建了一个事务。我认为这可能是问题所在。

2 个答案:

答案 0 :(得分:3)

很抱歉回答我自己的问题,但我发现了问题。这是一个有点自制的框架,其中DAO跟踪它自己的连接。

conn = getConn();

这将在显式事务中为每个DAO方法返回相同的连接。

当我逐步完成代码时,我发现我在事务中调用的方法是创建一个新事务,一个新的DAO,因此创建一个新的数据库连接。所以现在我打开了2个交易和2个连接。在这一点上很容易看出,我实际上已经陷入僵局。

这让我有点意外,因为我之前的应用程序允许嵌套事务。 (对两个事务使用相同的DB连接)

答案 1 :(得分:1)

因此,SQL连接将超时,您需要在执行查询之前指定要“连接”的连接,以便在它仍未打开时重新连接。

我只有apache commons DBCP和pooling的代码,但这是我用自己的连接做的。重要的行是connectionPool.setTestOnBorrow(true);并指定验证查询factory.setValidationQuery("select 1");

GenericObjectPool connectionPool = new GenericObjectPool(null);
...
connectionPool.setTestOnBorrow(true); // test the connection before its made
ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(connectURI,username, password);

final String validationQuery = null;
KeyedObjectPoolFactory statementPool = new GenericKeyedObjectPoolFactory(null);
PoolableConnectionFactory factory = new PoolableConnectionFactory(connectionFactory, connectionPool,
        statementPool, validationQuery, defaultReadOnly, defaultAutoCommit);

factory.setValidationQuery("select 1");    // validate the connection with this statement