2

SQL Server 2008 R2 DB と通信する Java アプリを理解しようとしています。アプリはデータを DB にインポートし、「テスト モード」があります。DB リクエストはトランザクションにラップされ、最後にロールバックされます。

特定のデータセットでは、ツールはトリガーを無効にし、インポート後に再度有効にします。テスト モードでは、最初のパスですべてが期待どおりに機能します。データセットは問題なく「インポート」されます。ただし、演​​習を繰り返そうとすると、トリガーを無効にしようとした時点でアプリがハングします。

SQL プロファイラーを見ると、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

Q : どのような問題が考えられますか? または、さらに調査する方法に関する提案はありますか?

更新: もちろん、上記のトレースは sp_prepare のみを示しています。対応する sp_execute ステートメントがあり、RPC:Completed トレース項目がないことは、問題が SQL Server 側にあることを示しています。変更されたトレースは、RPC:Starting エントリ ('exec sp_execute 1') を示していますが、一致する RPC:Completed はありません。

予想どおり、SSMS で sp_prepare & sp_execute を実行できます (set ステートメントを削除した場合)。結局、最初のパスで OK を実行します。

解決策: sp_who2 (以下を参照) を使用すると、最初の接続/spid が 2 番目の接続/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

これには a を使用しないでくださいPreparedStatement。プレーンのみを使用してくださいStatement

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

「ALTER TABLE」ステートメントは DDL (データ定義言語) です。DDL は、すべての DML (データ操作言語) ステートメントが完了するまで待機する必要があります。テーブルまたはそのテーブルのビュー、またはそのテーブルとの結合をクエリしている、または自動コミットをオフにして更新している、クローズされていない ResultSet、Statement、または PreparedStatement がある場合、それは DML が完了していません。

このようにテーブルを変更する前に、開いている可能性のあるすべての結果セットが明示的に閉じられていることを確認し、同様にすべてのステートメントを閉じてください。これにより、すべての DML が完了し、DDL を実行できるようになります。

一般に、Statement よりも PreparedStatements を使用することをお勧めします。PreparedStatement は 1 回コンパイルされます。実行されるたびにステートメント。これは、あなたのようなパラメーター化されていないステートメントには違いがなく、一度パラメーター化されたステートメントには潜在的な利点があることを意味します。

信頼できる JDBC 実装を想定すると、PreparedStatement が機能しないときにステートメントが機能する時間はありません。

この質問も役立つ場合があります。

于 2013-02-15T23:14:38.827 に答える
1

これは、適切に解放されていないロックがあり、DDL の実行をブロックしているように聞こえます。

ステートメントがハングしたら、ストアド プロシージャを実行しますsp_who2

その手順の結果、どのセッションが DDL をブロックしているかがわかるので、適切なアクションを実行できます。

于 2013-02-20T11:51:34.043 に答える