【问题标题】:How to generate PreparedStatements in a multi-thread-environment?如何在多线程环境中生成 PreparedStatements?
【发布时间】: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

【问题讨论】:

    标签: java multithreading jdbc prepared-statement


    【解决方案1】:

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

    我没有听说过类似的东西,如果它确实存在,它可能纯粹是一个实现细节。您可以发布您的堆栈跟踪(当然是通过剥离个人信息)吗?

    另外,您为什么要尝试使PreparedStatement 线程安全而不是依赖于准备好的语句池/缓存?或者更具体地说,什么样的分析促使你实现ThreadLocalPreparedStatement

    【讨论】:

    • 我有一个场景,其中包含一组固定的 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 在其之上做了任何事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 2022-01-16
    • 2012-05-29
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多