【问题标题】:Oracle dirty readOracle 脏读
【发布时间】:2016-05-27 19:34:38
【问题描述】:

我是使用 Oracle 数据库 11g 的新手。

我正在使用 SQL Developer 测试表和行锁。

我的表中有这样一行:

  • id : 1
  • 描述:'abc'

我进行了更新,但未提交将字段 desc 更改为 'zxc'。在另一个会话中,我做了一个返回旧记录的选择:

  • id : 1
  • 描述:'abc'

我在想它会给我一个错误或其他东西,因为我不想看到旧数据。

最后,当我在另一个会话中提交时,我在第二个会话中再次执行了查询并返回了提交的数据。

如何防止读取旧数据?

更新:

我阅读了有关 sql“SELECT FOR UPDATE”的信息,它阻止获取未提交的行,但例如有人告诉我有关银行的信息,所以我不确定这种方法是否具有良好的性能,而其他问题是关于丢失的没有提交的连接。也许我需要使用函数或 PLSQL 来最小化丢失的连接,实际上我正在使用 PHP 脚本(Laravel 框架)。

提前致谢。

【问题讨论】:

  • 就像编辑共享文档一样。您真的希望其他用户在您点击Save 之前看到您的更改吗?数据库提交就像保存文档。只有在您明确声明您通过提交批准更改后,更改才应该对全世界可见。您可以更改隔离级别(读取未提交)以更改该行为,但是对于像 Oracle 这样的数据库,我想不出一个好的理由来这样做。
  • 我希望 sql 会给我一个错误。仅在提交或回滚后获取行
  • @user2876735 想象一下这将如何在银行交易环境中工作。插入一行时,一切都必须停止。系统不知道哪个客户的账户会受到影响,所以一切都必须停止,直到“提交”或“回滚”。在那种世界里,几乎没有什么工作是可能的。

标签: php oracle isolation-level database-locking rowlocking


【解决方案1】:

您看到的是正常的“已提交读”行为。提交意味着“我准备好让世界其他地方看到我的交易结果”。如果您不提交它,那么对于任何其他数据库会话,它都不算存在。您所说的“旧数据”是最新提交的数据。

如果您可以在提交之前看到更新,那将是糟糕的,这就是“读取未提交”隔离级别。事务的存在使您可以原子地对数据库进行更改,以便查询查看一致的状态,而不是半生不熟的更改。

例如,可能有两个表,一个 Orders 表和一个 Line Items 表,其中 Orders 表包含所有行项目的总计,当我添加一个行项目时,我想更新它的 Order相同的交易,以便总计反映新的行项目。我不希望其他用户能够看到对订单行或新行项目的更改而没有看到其他更改,我希望这两个更改一起可见,因此我在事务中进行更改。

【讨论】:

    【解决方案2】:

    只读提交的数据有很好的理由。一个简单的例子就足以让你相信你认为你想要的实际上是一个坏主意。

    仅在事务结束时提交,而不是在每次更新或插入后提交的一个原因是为了便于输入具有参照完整性约束的数据,其中仅在事务结束时检查约束。假设已经创建了一个新部门,并且它有一个经理。您在“departments”表中创建了一个新行,但这需要一个 manager 值。您在“员工”表中创建“经理”行,但这需要一个部门。你先做哪个?答案 - 没关系,因为仅在事务结束时检查完整性(插入到两个表中)。

    现在假设您坚持要查看未提交的更改。新部门已添加到“部门”,但在 NOT NULL 约束列中,经理为 NULL。你真的想看到吗?您可能会想出三种不同的方式来解决您的应用程序中的严重问题。

    (我在这里跳过了延迟约束之类的微妙之处,这就是可能出现上述情况的情况 - 这不是我回答的重点。)

    【讨论】:

      猜你喜欢
      • 2019-06-16
      • 2017-12-01
      • 1970-01-01
      • 2016-12-21
      • 1970-01-01
      • 1970-01-01
      • 2014-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多