插入并删除事务中始终阻止行



我有此表:

TableAB
{
    IDA;
    IDB;
}

我想确保始终拥有对(ID1,ID2(和(ID2,ID1(。因此,我试图将其用于脚本:

插入:

begin tran
insert into tablaAB (IDTablaA, IDTablaB) VALUES(1,2);
insert into tablaAB (IDTablaA, IDTablaB) VALUES(2,1);
commit

删除:

begin tran
delete tablaAB where IDTablaA = 1 and IDTablaB = 2
delete tablaAB where IDTablaA = 2 and IDTablaB = 1;
commit

我正在使用Microsoft Management Studio的两个实例来运行两个查询,在大多数情况下,它有效,我得到了这两个行或任何一个。但是有时候,我只得到其中一个。

步骤是:

  • 将查询运行到删除(1,2(。
  • 运行查询以添加(1,2(。

在大多数情况下,它是封锁的,直到删除两行完成的交易为止,但是在某些情况下,它可以传递到下一行,以插入第二行。如果发生这种情况,那么我没有连贯的数据。

,但我不知道是因为我在测试中犯了一些错误还是在同一罕见情况下,第一个查询不会像我期望的那样被阻止。

实际上,在所有情况下,如果第一个删除完成了?

表是空的。因此,当我尝试删除时,这行似乎被阻塞了,并且不允许插入行,但是我不知道是否真的可以是某些罕见情况,在这些情况下,该行没有被阻止。

谢谢。

But I don't know if it is because I make some mistakes in the test or in same rare cases the first query is not blocked as I expect.
Really in all cases the first insert should be block if the first delete is done?

看来您正在使用读取的隔离级别运行。在这种情况下,当删除会话没有排名时,删除会话没有锁定,因此插入会话可以继续插入行。这将成为一种种族条件,您可能最终以零,一或两排。考虑导致一行的序列:

--session 1:
begin tran;
delete TableAB where IDTablaA = 1 and IDTablaB = 2;
--no row deleted, no lock held
--session 2:
begin tran
insert into TableAB (IDTablaA, IDTablaB) VALUES(1,2);
--row inserted, lock held
insert into TableAB (IDTablaA, IDTablaB) VALUES(2,1);
--row inserted, lock held
commit;
-- inserts committed and locks released
--session 1:
delete TableAB where IDTablaA = 2 and IDTablaB = 1;
--row deleted, lock held
commit;
--deleted committed, lock released

如果您使用SERIALIZABLE隔离级别,则DELETE语句将保持锁定(由于没有索引,在这种情况下锁定(并阻止插入会话。将在用于定位要删除的行的列上的索引上保留一个较小的键范围锁。

请注意,SERIALIZABLE比限制性的隔离水平更容易出现死锁。

最新更新