如何在多线程环境中生成 PreparedStatements?
Posted
技术标签:
【中文标题】如何在多线程环境中生成 PreparedStatements?【英文标题】:How to generate PreparedStatements in a multi-thread-environment? 【发布时间】:2011-10-21 13:11:35 【问题描述】:我有一个多线程代码的工作版本,但是我对我的 PreparedStatement-wrapper 类是非线程安全的感到不满意。所以我决定在ThreadLocal
中生成 PreparedStatements,以使包装器线程安全。
SQLExceptions 立即开始向我招手。潜在的 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
【问题讨论】:
【参考方案1】:有人可以确认或否认这一发现吗?
我没有听说过类似的东西,如果它确实存在,它可能纯粹是一个实现细节。您可以发布您的堆栈跟踪(当然是通过剥离个人信息)吗?
另外,您为什么要尝试使PreparedStatement
线程安全而不是依赖于准备好的语句池/缓存?或者更具体地说,什么样的分析促使你实现ThreadLocal
PreparedStatement
?
【讨论】:
我有一个场景,其中包含一组固定的 n 个数据库访问器,所有这些访问器都有非常个人的 PreparedStatement 来访问数据库。我理解,理论上数据源应该负责池化。问题似乎是,同时生成 n 个 PreparedStatements 会导致数据库死锁。我不想让语句线程安全。【参考方案2】:一个语句属于一个连接,一个连接不能真正并发使用。一个线程通常应该首先“拥有”一个连接,然后再对其执行语句。所以就按照成语来吧
1 check out connection
2 prepare statement
3 execute query
4 return connection
你不能避免[1]和[4],它们是必要的;如果合并的话,反正也不会太贵。
你想要缓存 [2],这也不是必须的,驱动程序可能已经做了缓存。
【讨论】:
我不以多线程方式访问连接。代码是(或多或少)run() datasource.getConnection().prepareStatement(sql); do_some_stuff()
。数据源是线程安全的,但我相信数据库可能不是“线程安全的”,尽管 jdbc 在其之上做了任何事情。以上是关于如何在多线程环境中生成 PreparedStatements?的主要内容,如果未能解决你的问题,请参考以下文章