2011-10-21 6 views
2

私はマルチスレッドコードの作業バージョンを持っていましたが、私はPreparedStatement-wrapperクラスがスレッドセーフでないことに満足できませんでした。だから、私は、PreparedStatementsをThreadLocalに生成して、ラッパーをスレッドセーフにすることに決めました。マルチスレッド環境でPreparedStatementsを生成するには?

すぐにSQLExceptionsスタートアップが私を呼び起こします。基本的なOracleエラーはORA-00060 deadlock detectedです。インターネットによれば、書き込みシナリオでのみ発生します。私のステートメントはすべて読み取り専用です。それは、私が意識して聞いたりアクセスしたりしていない、あいまいなACLパッケージで発生します。

Connectionオブジェクトを生成し、DataSourceオブジェクトからのそのオブジェクトからのステートメントを準備することは、データベースのアクセス制御が同時に行われてはならないという仮説を準備し、テストしました「threadsafe」ではないかもしれません(althoug DataSourceが最も確実です)。誰かがその発見を確認したり否定することはできますか?

これが本当に当てはまる場合、マルチスレッドアプリケーションでPreparedStatementが同時に生成されないようにするにはベストプラクティスがありますか?

EDIT:としては、例外のテキストを尋ねた:

Caused by: java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1 
ORA-00060: deadlock detected while waiting for resource 
ORA-06512: at "XXX.PKG_ACL", line 129 
ORA-06512: at "XXX.PKG_ACL", line 459 
ORA-06512: at "XXX.PKG_UTILS", line 1933 
ORA-06512: at line 6 

答えて

2

誰かがその発見を確認または拒否することはできますか?

私はこれらの行には何も聞いていません。存在していれば純粋に実装の詳細かもしれません。スタックトレースを投稿できますか?もちろん、個人情報を取り除くことはできますか?

また、PreparedStatementを準備済みのプール/キャッシュに頼るのではなく、スレッドセーフにしようとする理由は何ですか?具体的には、どのような種類の分析を実装するにはThreadLocalPreparedStatement

+0

私はDBにアクセスするための非常に個人的なPreparedStatementを持つn db-accessorsの固定セットを使用したシナリオを持っています。私は理論的には、データソースがプールを処理する必要があることを理解しています。問題は、n PreparedStatementsを同時に生成すると、データベースにデッドロックが発生することになります。ステートメントをスレッドセーフにするつもりはありません。 – Jonathan

2

文は接続に属し、接続は実際には同時に使用できません。スレッドは、通常、ステートメントを実行する前に、接続を最初に「所有」する必要があります。だからちょうどイディオムに従います。

1 check out connection 
2 prepare statement 
3 execute query 
4 return connection 

あなたは[1]と[4]を避けることはできません。とにかくプールされればあまりにも高価ではない。

あなたは[2]をキャッシュしたいと思いますが、これは必ずしも必要ではありません。ドライバはおそらくすでにキャッシュしています。

+0

私はマルチスレッドの方法で接続にアクセスしません。コードは(多かれ少なかれ) 'run(){datasource.getConnection()。prepareStatement(sql);です。 do_some_stuff()} '。データソースはスレッドセーフですが、データベースの上にjdbcがあるにもかかわらず、「スレッドセーフ」ではない可能性があります。 – Jonathan

関連する問題