【问题标题】:Will delete from inside transaction remove records from after transaction将从内部事务中删除从事务后删除记录
【发布时间】:2015-12-24 21:06:12
【问题描述】:

我有一个简短的问题要问你...如果我运行以下命令:

BEGIN TRANSACTION
 <commands...>
 DELETE FROM <table>
COMMIT TRANSACTION

当上述事务正在运行时,会在表上执行插入操作。是否会删除:

  1. 删除事务开始后添加的数据
  2. 仅删除事务开始时存在的数据或作为事务的一部分添加的数据

希望有人能提供帮助。

【问题讨论】:

  • 您的问题的答案取决于您的事务的隔离级别。
  • 读取提交的隔离级别

标签: sql-server sql-server-2012 transactionscope


【解决方案1】:

您需要深入了解锁和事务隔离级别主题。看这个例子,这可能比上一个答案更常见。 INSERT 在这里没有被阻止,因为 DELETE 只是锁定了一组用于 DELETE 操作的键。

无论如何,在 DELETE 操作开始之前,如果该事务中的其他查询没有对该表持有锁,则 SQL Server 没有理由阻止其他事务的 INSERT 操作。

CREATE TABLE t (Id int PRIMARY KEY)
GO

INSERT INTO t VALUES(1)
GO

BEGIN TRAN

DELETE FROM t

-- separate window
INSERT INTO t VALUES(2)

【讨论】:

    【解决方案2】:

    我假设您在一个 SPID 中运行您的代码,并且插入将在另一个 SPID 上运行,并且隔离级别是 SQL SERVER 中的默认级别 - READ COMMITTED

    很快,答案是否定的,因为 INSERT 将等待 DELETE 结束。像这样测试:

    1) 设置:

    -- drop table dbo.Test
    CREATE TABLE dbo.Test
    (
        Id INT NOT NULL,
        Value NVARCHAR(4000)
    )
    GO
    
    INSERT INTO Test (Id, Value) 
    SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT 1)), text
    from sys.messages
    GO
    

    2) 在查询窗口1中

    BEGIN TRANSACTION
    DELETE FROM dbo.Test where ID > 100000
    

    3) 在查询窗口 2 中

    INSERT INTO Test (Id, Value) 
    SELECT 100000000 + ROW_NUMBER() OVER (ORDER BY (SELECT 1)), text
    from sys.messages
    

    sp_who2 active 表示第二个查询(SPID)被第一个查询阻塞,所以查询正在等待获取锁

    3) 在查询窗口1中

    COMMIT -- query 1 will finish
    

    4) 第二次查询将完成

    因此,INSERT 必须等到 DELETE 完成。

    【讨论】:

    • 太好了。感谢您的信息/
    • 这个答案不正确。此 INSERT 使用 SELECT 作为源,并且当它使用 SELECT 时,它将使用共享锁进行读取,因此这就是 INSERT 等待的原因。此外,此示例假设表没有主键,因此所有表都将被锁定以进行删除操作,而对于更常见的情况 - 具有主键的表来说,情况并非如此。
    • 正如我所不明白的,denimknight 想知道在 DELETE 发生时 INSERT 是否会引入数据。正如 MS docs for DELETE 中所述,它将锁定表:默认情况下,DELETE 语句总是在它修改的表上获取排他 (X) 锁,并持有该锁直到事务完成。使用排他(X)锁,没有其他事务可以修改数据;只有使用 NOLOCK 提示或读取未提交的隔离级别才能进行读取操作。 (msdn.microsoft.com/en-us/library/ms189835.aspx - 锁定行为)
    【解决方案3】:
    1. 是的。为什么不?如果您的事务中的其他查询不会在 your_table 上持有锁,SQL Server 将在 DELETE 操作开始后开始使用更新锁锁定 your_table。因此,在此操作之前,所有其他进程都可以成功地将新行添加到表中。
    2. 在您的情况下,DELETE 将删除所有已提交的数据,这些数据在 DELETE 操作之前存在于您的表中。该交易未提交的数据也将被删除。

    【讨论】:

      猜你喜欢
      • 2019-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      • 2018-07-27
      相关资源
      最近更新 更多