2011-10-21 49 views
2

我已經有一個多線程代碼的工作版本,但我不滿意我的PreparedStatement包裝類非線程安全。所以我決定在ThreadLocal中生成PreparedStatements以使包裝線程安全。如何在多線程環境中生成PreparedStatements?

立即SQLExceptions開始降臨在我身上。底層的Oracle錯誤是ORA-00060 deadlock detected,根據互聯網應該只發生在寫入場景中。我的陳述全部是隻讀的。它出現在一些我從來沒有聽說過,也沒有有意識地訪問的模糊的ACL包中。

我曾與一些時間和精力準備和測試的假設是,生成Connection對象,並從該對象從DataSource對象準備語句不應該在同樣的時間發生,因爲對數據庫的訪問控制可能不是「線程安全」(數據源絕對是數據源)。有人可以確認或否認這一發現?

如果確實如此,是否有一個最佳實踐,以避免在多線程應用程序中同時生成PreparedStatements?

編輯:由於問異常的文本:

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線程安全而不是依賴prepared語句池/緩存的任何原因?或者更具體地說,通過什麼樣的分析來實現ThreadLocalPreparedStatement

+0

我有一套固定的n個db-accessors,所有這些都有他們非常個人的PreparedStatement來訪問數據庫。我理解,理論上來說,數據源應該關注彙集。問題似乎是,同時生成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