将从内部交易中删除从交易后删除记录

Will delete from inside transaction remove records from after transaction

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

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

虽然上面的 t运行saction 是 运行,但在 table 上执行了插入。是否删除:

  1. 删除 t运行saction 开始后添加的数据
  2. 仅删除 t运行saction 开始时存在的数据或作为 t运行saction
  3. 的一部分添加的数据

希望有人能提供帮助。

我假设您 运行 在一个 SPID 中插入您的代码,并且插入将 运行 在其他 SPID 上并且隔离级别是 SQL 服务器中的默认级别 - 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) 在查询中 window 1

BEGIN TRANSACTION
DELETE FROM dbo.Test where ID > 100000

3) 在查询中 window 2

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

sp_who2 active 显示第二个查询 (SPID) 被第一个查询阻塞,因此查询正在等待获取锁

3) 在查询中 window 1

COMMIT -- query 1 will finish

4) 第二个查询将完成

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

  1. 是的。为什么不?如果您事务中的其他查询不会在 your_table 上持有锁,SQL 服务器将在 DELETE 操作开始后开始使用更新锁锁定 your_table。因此,在此操作之前,所有其他进程都可以成功地将新行添加到 table.
  2. 在您的案例中,DELETE 将删除所有已提交的数据,这些数据在 DELETE 操作之前存在于您的 table 中。此事务未提交的数据也将被删除。

您需要深入了解锁定和事务隔离级别主题。看看这个例子,它可能比之前的答案更常见。此处未阻止 INSERT,因为 DELETE 只是为 DELETE 操作锁定一组键。

而且无论如何,在 DELETE 操作开始之前,如果此事务中的其他查询未持有此 table 上的锁,SQL 服务器没有理由阻止来自其他事务的 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)