如何在多线程环境中生成预准备语句?

时间:2011-10-21 13:11:36

标签: java multithreading jdbc prepared-statement

我有一个多线程代码的工作版本,但我不满意我的PreparedStatement-wrapperclass是非线程安全的。所以我决定在ThreadLocal中生成PreparedStatements以使包装线程安全。

SQLExceptions startet立即向我致敬。底层Oracle错误是ORA-00060 deadlock detected,根据互联网,它应该只出现在写入场景中。我的陈述都是只读的。它出现在一些模糊的ACL包中,我既没有听说也没有意识到这一点。

我已经花了一些时间和精力准备并测试了一个假设,即生成Connection对象并从DataSource对象中准备来自该对象的语句不应该同时发生因为数据库的访问控制可能不是“线程安全”(尽管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 个答案:

答案 0 :(得分:2)

  

有人可以确认或否认这一发现吗?

我没有听到过这些内容,如果确实存在,那可能只是一个实现细节。你可以发布你的堆栈跟踪(通过剥离个人信息)吗?

此外,您尝试使PreparedStatement线程安全而不是依赖于准备语句池/缓存的任何原因?或者更具体地说,什么样的分析会促使您实施ThreadLocal PreparedStatement

答案 1 :(得分:2)

语句属于连接,并且连接不能真正同时使用。在执行语句之前,线程通常应首先“拥有”连接。所以请按照成语

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

你无法避免[1]和[4],它们是必要的;如果合并的话,不要太昂贵。

你想缓存[2],这也不是必需的,驱动程序可能已经进行了缓存。