我有两个事务:T1使用SERIALIZABLE
隔离级别,而T2(我认为使用默认的READ COMMITTED
隔离级别,但这并不重要)。
事务T1执行SELECT
,然后WAITFOR
2秒,然后SELECT
。
事务T2对T1读取的数据进行UPDATE
。
这会导致死锁,为什么事务T2不等待T1结束?
当T1具有REPEATABLE READ
隔离级别时,一切正常,即会出现幻行。我认为当我将隔离级别提高到SERIALIZABLE
时,T2将等待T1的结束。
这是我的大学练习的一部分。我必须展示在具有不正确隔离级别和缺乏这些效果的两个并行事务中的负面影响,并展示在正确的隔离级别下没有这些效果。
这里是代码,遗憾的是字段名称是用波兰语写的。
T1:
USE MR;
SET IMPLICIT_TRANSACTIONS OFF; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
-- 1.查询 SELECT www.IdSamochodu,s.Model,s.Marka,s.NrRejestracyjny,o.PESEL,o.Nazwisko,o.Imie,o.NrTelefonu FROM WizytyWWarsztacie www JOIN Samochody s ON s.IdSamochodu = www.IdSamochodu JOIN Osoby o ON o.PESEL = s.PESEL WHERE www.[Status] ='gotowy_do_odbioru' ORDER BY www.IdSamochodu ASC ;
WAITFOR DELAY '00:00:02';
-- 2.查询 SELECT u.IdSamochodu,tu.Nazwa,tu.Opis,u.Oplata FROM Uslugi u JOIN TypyUslug tu ON tu.IdTypuUslugi = u.IdTypuUslugi JOIN WizytyWWarsztacie www ON www.IdSamochodu = u.IdSamochodu AND www.DataOd = u.DataOd WHERE www.[Status] ='gotowy_do_odbioru' ORDER BY u.IdSamochodu ASC,u.Oplata DESC ;
COMMIT;
T2:
使用MR;
SET IMPLICIT_TRANSACTIONS OFF; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN TRANSACTION;
UPDATE Uslugi SET [Status] = '已完成' WHERE IdUslugi = 2 ;
UPDATE www SET www.[Status] = '准备接收' FROM WizytyWWarsztacie www WHERE www.[Status] = '正在执行服务' AND EXISTS ( SELECT 1 FROM Uslugi u WHERE u.IdSamochodu = www.IdSamochodu AND u.DataOd = www.DataOd AND u.[Status] = '已完成' GROUP BY u.IdSamochodu, u.DataOd HAVING COUNT(u.IdUslugi) = ( SELECT COUNT(u2.IdUslugi) FROM Uslugi u2 WHERE u2.IdSamochodu = www.IdSamochodu AND u2.DataOd = www.DataOd GROUP BY u2.IdSamochodu, u2.DataOd ) ) ;
COMMIT;
我使用SQL Management Studio,每个事务都在不同的文件中。我通过在T1中单击F5然后快速切换到包含T2的文件再次单击F5来运行此操作。
我阅读了有关mssql中死锁和锁定机制的文章,但显然我还没有理解这个主题。
SQL Server 2008 R2 (.Net 2.0应用程序)中的死锁问题
SQL Server在select/update或多个select之间死锁
http://msdn.microsoft.com/en-us/library/ms173763(v=sql.105).aspx
http://www.sql-server-performance.com/2004/advanced-sql-locking/
编辑
我发现T2中的第一个UPDATE语句引起了问题,为什么?
SELECT
和UPDATE
查询。 - Martin Smith