【问题标题】:What will happen if records are deleted during the data retrieving process?如果在数据检索过程中删除记录会怎样?
【发布时间】:2009-07-13 00:26:37
【问题描述】:

假设我有 6 条记录,我将提取大小设置为 2。

[Id] [Name]
 11   A   <-- 1st fetch, start from 1 position
 21   B
 31   C   <-- 2nd fetch, start from 3 position
 41   D
 51   E   <-- 3rd fetch, start from 5 position
 61   F

如果第一个用户发出“SELECT * from tablex”,第二个用户发出“DELETE FROM tablex WHERE Id = 2。删除过程恰好发生在第一次提取和第二次提取之间。

第一次提取(A)

[Id] [Name]
 11   A   <-- 1st fetch, start from 1
 21   B

从 (B) 中删除后

[Id] [Name]
 11   A   <-- 1st fetch, start from 1
 31   C   
 41   D
 51   E   
 61   F

现在 (A) 的第二次提取应该从 3 开始,但删除导致记录的位置已更改。如果第 2 次提取从位置 3 开始,将提取的记录是

[Id] [Name]
 41   D   <-- position 3
 51   E   

而不是

[Id] [Name]
 31   C   <-- 2nd fetch, start from 3 position
 41   D

我不确定这个问题是否会发生。还是现代数据库足够聪明,可以检测到它?或者只是在数据检索过程中锁定表?

【问题讨论】:

  • 我挖掘 DELECT 关键字
  • 很好,akf :D 我刚刚更正了。
  • 请详细说明您使用的是什么数据库和数据库访问api
  • 我将使用 Oracle。不过这个问题不限于Oracle,我也时不时处理mySQL、sybase。

标签: java sql concurrency


【解决方案1】:

你问的是“PHANTOM READ”。大多数数据库使用锁来防止在事务中发生这种情况。

某些数据库提供“READ COMMITTED”(或更低)隔离级别,在这种情况下可能会发生幻读..

【讨论】:

    【解决方案2】:

    在 MSSQL 中不可能出现这样的问题,因为在检索结果集时会发生锁定。 我不知道另一个 RDBMS 怎么样。

    【讨论】:

    • 啊,是的,Oracle 使用行版本控制 :)
    • 不正确:只有 SERIALIZABLE 隔离级别提供您所说的锁定级别。
    • 读取数据(SELECT)时,记录将被共享(S)锁锁定。在锁定解除之前,不能编辑或删除记录。如果使用 NOLOCK 提示,则不会有锁。
    • Alex_L,有大量证据证明你错了。就在我的脑海中,这是:“偏斜总数的案例”simple-talk.com/sql/t-sql-programming/…
    • @both Alexes:这里的任何答案都因“获取”而变得复杂。选择是一次性执行,还是客户端游标一次执行 2 行?
    【解决方案3】:

    会发生什么将部分取决于两个事务中有效的隔离级别。

    如果提取进程在可序列化隔离下运行,则 DELETE 操作将失败。如果提取进程在脏读(未提交的读)隔离下运行,那么几乎任何事情都是可能的,但最有可能的是,它会读取未删除的记录。

    【讨论】:

      猜你喜欢
      • 2011-10-21
      • 2017-10-29
      • 2021-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      相关资源
      最近更新 更多