1

我正在尝试调试 Glassfish(EJB 应用程序)下的 Derby 死锁问题。我想在各个点查看锁表,所以我编写了以下代码。问题是在我调用它的每个地方,锁表总是以空的形式返回。我错过了什么?

private void dumpLockTable()
{
    try ( Connection connection = dataSource.getConnection() )
    {
        PreparedStatement ps = connection.prepareStatement( "SELECT * FROM SYSCS_DIAG.LOCK_TABLE" );
        ResultSet rs = ps.executeQuery();
        ResultSetMetaData rsmd = rs.getMetaData();
        int columns = rsmd.getColumnCount();            
        StringBuilder sb = new StringBuilder();
        sb.append( "Lock Table\n" );
        while( rs.next() )
        {
            for ( int col = 1; col <= columns; col++ )
            {
                sb.append( rs.getString( col ) );
                sb.append( "\t|" );
            }
            sb.append( "\n" );
        }
        logger.info( sb.toString() );
    }

    catch ( SQLException sqle )
    {
        logger.throwing( LOG_CLASS_NAME, "dumpLockTable", sqle );
    }
}

这是 Glassfish 3.1.2.1 下的 Derby 10.8。我正在通过以下方式获取数据源:

@Resource(mappedName="jdbc/myderbyjndi")
private DataSource dataSource;

所有其他 Derby 活动都是通过实体 bean 和实体管理器进行的。

4

2 回答 2

2

你的代码对我来说看起来不错;我不确定它有什么问题。

但也许当你运行它时,那时根本没有任何锁被持有。

您可以通过使用“ij”工具和两个“ij”会话来开始诊断过程:

  1. 在第一个会话中,连接到数据库并使用 LOCK TABLE 语句锁定一些表
  2. 在第二个会话中,连接到数据库并运行 SELECT * FROM SYSCS_DIAG.LOCK_TABLE

看看能不能在这样的场景下看到 LOCK_TABLE 诊断表的内容。一旦可以,您就可以使用相同的技术(在运行代码时在 ij 会话中人为地持有锁)来进一步调试您的子例程代码。

在wikidocs中有一些关于诊断 Derby 锁定行为的好建议。

您可能想为这个 Derby 增强请求投票。

于 2013-02-03T17:36:12.747 回答
1

我从 Derby 邮件列表中得到了一个答案,我认为我应该添加它以确保完整性。显然,实体管理器实际上并没有立即将命令发送到数据库(我认为这听起来很熟悉,但我已经忘记了),所以这可以解释为什么锁表没有显示任何锁。如果我在执行锁表转储之前添加一个 entityManager.flush(),我会得到一个很好的锁列表。现在我可以调试导致死锁的序列。

于 2013-02-06T01:03:35.713 回答