2

我试图掌握一个与 SQL Server 2008 R2 DB 对话的 Java 应用程序。该应用程序将数据导入数据库,并具有“测试模式”;数据库请求被包装在一个事务中,该事务在最后回滚。

对于特定数据集,该工具会禁用触发器,然后在导入后重新启用它。在测试模式下,第一次通过时,一切都按预期工作——“导入”的数据集没有问题。但是,如果我尝试重复该练习,应用程序会在尝试禁用触发器的位置挂起。

查看 SQL Profiler,我可以看到一个 RPC:Completed 跟踪项,这表明 SQL Server 已接收并成功处理了请求。在这一点上,我希望 Java 应用程序能够获得控制权并继续 - 除了它没有,我正在努力思考下一步该往哪里看。

Java代码:

String sql = "ALTER TABLE MyTable DISABLE TRIGGER ALL";
PreparedStatement stmt = mDBConnection.prepareStatement (sql);
stmt.execute();

跟踪文本数据:

declare @p1 int
set @p1=1
exec sp_prepare @p1 output,N'',N'ALTER TABLE MyTable DISABLE TRIGGER ALL',1
select @p1

:知道可能是什么问题吗?或者关于我如何进一步调查的任何建议?

更新:当然,上面的跟踪只显示了 sp_prepare。有相应的 sp_execute 语句 - 并且缺少 RPC:Completed 跟踪项,表明问题出在 SQL Server 端。修改后的跟踪显示 RPC:Starting 条目 ('exec sp_execute 1'),但没有匹配的 RPC:Completed。

正如预期的那样,我可以在 SSMS 中运行 sp_prepare 和 sp_execute (前提是我删除了 set 语句)——毕竟它在第一次通过时就可以执行。

解决方案: 使用 sp_who2(见下文),我可以看到第一个连接/spid 在第二个被阻止;在提交时,数据库连接已关闭,但在回滚时却没有。由于我在测试和回滚模式下运行,这是我问题的症结所在 - 关闭连接解决了问题。

sp_who2:

CREATE TABLE #sp_who2 
(
   SPID INT,  
   Status VARCHAR(1000) NULL,  
   Login SYSNAME NULL,  
   HostName SYSNAME NULL,  
   BlkBy SYSNAME NULL,  
   DBName SYSNAME NULL,  
   Command VARCHAR(1000) NULL,  
   CPUTime INT NULL,  
   DiskIO INT NULL,  
   LastBatch VARCHAR(1000) NULL,  
   ProgramName VARCHAR(1000) NULL,  
   SPID2 INT,
   RequestID int
) 
GO

INSERT INTO #sp_who2 EXEC sp_who2
GO

SELECT spid, status, blkby, command, ProgramName FROM #sp_who2 WHERE DBName = 'rio7_bch_test'
GO

DROP TABLE #sp_who2
GO
4

3 回答 3

1

不要PreparedStatement为此使用 a 。只使用一个普通的Statement.

Statement stmt = mDBConnection.createStatement(sql);
于 2013-02-15T17:49:04.037 回答
1

“ALTER TABLE”语句是 DDL(数据定义语言)。DDL 必须等待所有 DML(数据操作语言)语句完成。如果您有一个未关闭的 ResultSet、Statement 或 PreparedStatement 正在查询该表或该表的视图,或者与该表连接,或者在关闭自动提交的情况下进行更新 - 那么这就是不完整的 DML。

在像这样更改表之前,请确保在其上打开的每个可能的结果集都已显式关闭,类似地任何语句。这将确保所有 DML 都是完整的,并且可以执行 DDL。

一般来说,使用 PreparedStatements 优于 Statements。PreparedStatement 编译一次。每次执行的语句。这意味着像您这样的未参数化语句没有区别,并且任何参数化一次都有潜在的好处。

假设一个受信任的 JDBC 实现,当 PreparedStatement 不起作用时,Statement 没有时间可以工作。

您可能还会发现这个问题很有帮助。

于 2013-02-15T23:14:38.827 回答
1

这听起来很像您的锁未正确释放并阻止您的 DDL 执行。

当您的语句挂起时,运行存储过程sp_who2

在该过程的结果中,您将确定哪个会话正在阻止您的 DDL,然后您可以采取适当的措施。

于 2013-02-20T11:51:34.043 回答