Java JDBC事务死锁:需要解决方案吗?

Java JDBC事务死锁:需要解决方案吗?,java,oracle,jdbc,transactions,deadlock,Java,Oracle,Jdbc,Transactions,Deadlock,我的朋友描述了一个场景,并要求我找到解决方案。他使用的是Oracle数据库和JDBC连接,读取提交作为事务隔离级别。在其中一个事务中,他更新记录,执行select语句并提交事务。当所有事情都发生在一个线程中时,一切都很好。但当处理多个请求时,就会出现死锁 线程A更新记录 线程B更新另一条记录 线程A发出select语句并等待线程B的事务完成提交操作 线程B发出select语句并等待线程A的事务完成提交操作 上述情况会导致死锁。由于它们使用命令模式,基本框架只允许发出一次commit(在所有db操

我的朋友描述了一个场景,并要求我找到解决方案。他使用的是Oracle数据库和JDBC连接,读取提交作为事务隔离级别。在其中一个事务中,他更新记录,执行select语句并提交事务。当所有事情都发生在一个线程中时,一切都很好。但当处理多个请求时,就会出现死锁

  • 线程A更新记录
  • 线程B更新另一条记录
  • 线程A发出select语句并等待线程B的事务完成提交操作
  • 线程B发出select语句并等待线程A的事务完成提交操作 上述情况会导致死锁。由于它们使用命令模式,基本框架只允许发出一次commit(在所有db操作结束时),因此它们无法在select语句之前立即发出commit

    我的论点是:线程A应该选择所有提交的记录,因此不应该发布。但是他说线程A肯定会等到线程B提交记录。这是真的吗

    避免上述问题的所有方法是什么?是否可以更改隔离级别(而不更改底层java框架)

    关于基本框架的信息很少:它类似于Struts操作,每个请求都由一个操作处理,事务在执行前开始,在执行后提交。

    From

    Oracle明确支持读取 提交和可序列化隔离 在中定义的级别 标准然而,这并不能说明问题 整个故事。SQL标准是 正在尝试设置隔离级别 将允许不同程度的 在上执行的查询的一致性 每一级。可重复读取是最重要的 符合SQL标准的隔离级别 索赔将保证 从查询中读取一致的结果。 在SQL标准定义中,阅读 承诺不会给你始终如一的感觉 结果,而READ UNCOMMITTED是 用于获取非阻塞读取的级别

    但是,在Oracle数据库中,读取 COMMITTED具有所有属性 需要实现读一致性 查询。在其他数据库中,读取 提交的查询可以并且将返回 世界上从未有过的答案 数据库此外,Oracle数据库 也支持阅读的精神 未承诺的提供 脏读是为了提供一个非阻塞 读取,从而不会阻止查询 通过,而不是阻止 同样的数据。然而,Oracle数据库 不需要脏读来实现 这一目标,也不支持他们。 脏读是一种实现 必须使用其他数据库来提供 非阻塞读取

    阅读 坚信的阅读已提交 隔离级别声明 事务可以只读 已在数据库中提交。 没有脏读(读取 未提交的数据)。可能有 不可重复读取(即,重新读取 同一行的返回值可能不同 在同一交易中回答)和 幻影读取(即,新插入的 并且提交的行对用户可见 在中之前不可见的查询 反作用)。读承诺是 也许是最常用的 数据库中的隔离级别 应用程序无处不在,它是 Oracle数据库的默认模式。它是 很少看到不同的孤立 Oracle数据库中使用的级别

    在 Oracle数据库,使用 多版本控制和读一致性 查询,我从 账户查询在读取中是相同的 承诺的例子,因为它是在 阅读未提交的示例。神谕 数据库将重建修改后的数据库 查询时显示的数据 他开始回答,回答是 在数据库中进行查询时 开始


    如果选择更新其他线程已更新(但尚未提交)的记录,我相信您的朋友是正确的。如果他们只是选择数据,而JDBC框架没有通过强制选择更新来帮助您,那么您是正确的

    若要避免此问题,请确保仅在确实需要时才选择更新,在这种情况下,请使用“选择”对话框中的NOWAIT选项。如果操作将被阻止,这将导致引发错误


    Oracle将检测死锁并回滚其中一个涉及的事务。

    Oracle中不会出现这种情况,原因很简单,即写入不会阻止该数据库中的读取

    我们可以在以下场景中获得死锁:

  • 会话A更新了一条记录#1234
  • 会话B更新另一条记录#5678
  • 会话A更新记录#5678
  • 会话B更新记录#1234
  • 会话A发出提交
  • 会话B发出提交 Oracle将检测死锁并回滚其中一个会话。在传统的客户机/服务器应用程序中,悲观锁定可以避免这种情况(
    SELECT…FOR UPDATE
    )。在web应用程序中,通过使用“乐观锁列”可以避免这种情况,而“乐观锁列”实际上根本不是锁的形式(这就是为什么它可以避免死锁,尽管会以大量额外读取为代价)

    我不理解“等待…事务完成”的含义,因为在Oracle中,读取提交后,读卡器不会阻止写入程序,写入程序也不会阻止读卡器。