【问题标题】:How do I prevent JPA inserts from locking a database table?如何防止 JPA 插入锁定数据库表?
【发布时间】:2009-07-30 19:50:56
【问题描述】:

我使用 Hibernate 支持的 JPA 作为我的持久层。我有一个多线程进程,它聚合来自 Soap 调用的数据,然后在数据库中存储一行。该过程通常最终插入大约 700 行,大约需要 1 到 3 个小时,而 Soap 调用是主要瓶颈。

在整个过程中,我插入的表被锁定,不会及时返回 select 语句。

这是 SQL 服务器错误:

错误消息:超过锁定请求超时时间。

如何避免在这个漫长的过程中锁定我的数据库表?

【问题讨论】:

    标签: java database hibernate jpa persistence


    【解决方案1】:

    您可能需要更改隔离级别。

    以下是一些信息: http://www.interview-questions-tips-forum.net/index.php/Your-Questions-on-Java/JDBC-Transaction/Transaction-Isolation-Levels

    它讨论了不同的隔离级别,以及它们可以帮助防范的内容。执行此操作的一般方法是从严格者开始,如果您需要更好的响应时间,然后再降低,同时牢记数据完整性/错误读取的要求。

    编辑

    Spring 事务级别用于在事务管理器中抽象 JDBC(或其他)事务隔离级别。它们在TransactionDefinition 类中定义,并且是静态成员。

    TransactionDefinition.ISOLATION_DEFAULT
    Default isolation
    
    TransactionDefinition.ISOLATION_READ_UNCOMMITTED
    Lowest level of isolation; allows transactions to see uncommitted modifications from other transactions
    
    TransactionDefinition.ISOLATION_READ_COMITTED
    Cannot read uncommitted data
    
    TransactionDefinition.ISOLATION_REPEATABLE_READ
    Ensures repeatable reads
    
    TransactionDefinition.ISOLATION_SERIALIZABLE
    Most reliable; all transactions are executed atomically, and are treated as though they occurred serially.
    

    还有事务传播级别。您可能正在使用事务进行纯读取,这可能是矫枉过正 - 读取不需要事务,写入应该始终围绕它们进行事务。 TransactionDefinition 中的传播级别也是明确的。这些通常在 spring 连接文件中用于定义特定调用的序列化和传播。如果您有接线示例,我可能会提供更多提示/信息。

    【讨论】:

    • 如果你使用的是 Spring 事务管理器,当你设置事务 DAO 时,你可以为每个事务调用设置隔离级别。
    • 真的,你能在此基础上扩展一下吗?或者为我指出一篇在此基础上扩展的文章的方向?
    • 请注意,我从 Rob Harrop 和 Jan Machacek 的参考书“Pro Spring”中获得的所有 Spring 信息。虽然是一本非常枯燥的书,但它是 Spring 的一个很好的参考书,索引非常好。正是这本书终于让我的交易“点击”了——尽管花了一段时间 :)
    【解决方案2】:

    您是否使用 same 事务插入所有 700 行?

    您的交易边界在哪里?如果你可以降低你的事务边界,即只事务实际的插入操作,那么锁就会被短暂地持有。

    如果您需要将整个过程设为原子,则可以将其写入临时表,然后进行批量插入(快速)以将其插入主表。

    【讨论】:

    • 我不确定我的交易边界。我在需要事务的 DAO 方法上有 @transactional,但在使用 DAO 的代码的入口点上也有 @transactional。如果我删除前者,它会给我一个无交易错误。这是我目前正在调查的事情。查看stackoverflow.com/questions/807457
    • 我的@Transactional 太过分了,一旦我删除它,进程就可以正常工作而不会锁定数据库。我仍然有一些奇怪的问题@Transactional,但是对于这个过程,我解决了它只是依靠较小的交易。这个问题也很有帮助stackoverflow.com/questions/1079114
    【解决方案3】:

    您是否尝试在一个 JPA 事务中发出 700 个肥皂请求?不要那样做。 :-)

    【讨论】:

    • 不,程序所做的是通过 SOAP 调用获取结果,然后报告到数据库中。事务由 Spring 处理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-14
    相关资源
    最近更新 更多