2017-05-20 41 views
1

我已经读完的文章(https://www.simple-talk.com/sql/t-sql-programming/questions-about-t-sql-transaction-isolation-levels-you-were-too-shy-to-ask/)混乱,我根据有一个问题:SQL Server中的序列化隔离级别

“SERIALIZABLE:一个在当前事务中不能读取由未另一个事务修改数据查询没有其他事务可以修改当前事务正在读取的数据直到它完成,并且没有其他事务可以插入与当前事务中的搜索条件匹配的新行直到它完成为止,结果是,Serializable隔离级别阻止脏读,不可重复读取和幻像读取,但与其他隔离级别相比,它对性能影响最大。“

我很困惑插入新的行不满足搜索条件从1会话/查询。下面的例子:

让我们假设我有表中单独的选项卡

EmpID FirstName 
1  john 
2  new employee 
3  A new employee 

和查询:

--session 1---------------------------------- 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 

BEGIN TRANSACTION; 

    SELECT FirstName FROM EmployeeInfo 
    WHERE FirstName like 'new empl%' 

    WAITFOR DELAY '00:00:10' 

    SELECT FirstName FROM EmployeeInfo 
    WHERE FirstName like 'new empl%' 

ROLLBACK TRANSACTION; 

---------session 2--------------------------- 
begin transaction; 

    UPDATE EmployeeInfo 
    SET FirstName = 'frank' 
    WHERE EmpID = 1; 

commit transaction; 

-----session 3---- 
insert into EmployeeInfo values('A new employe 2') 

我执行后,其他查询之一:会话1,会话2,会话3 我期望会话1不会停止执行会话2和会话3,因为来自此会话的更新和插入不满足第一个查询中使用的搜索条件。但是,在结果中,我可以看到会话1必须在会话2和会话3执行之前完成(回滚)。

然而,虽然我使用其他搜索条件在会话1象下面这样:

--session 1 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 

BEGIN TRANSACTION; 

SELECT EmpID, FirstName FROM EmployeeInfo 
WHERE EmpID = 2 

WAITFOR DELAY '00:00:10' 

SELECT FirstName FROM EmployeeInfo 

ROLLBACK TRANSACTION; 

然后,会话2和会话3独立会话的完成1. 为什么呢?为什么像条件块插入时,“=”不?

编辑: 1.在EmpID上只有一个主键。

+1

包含索引的表的定义是什么? –

回答

1

这是因为“没有其他事务可以插入与当前事务中的搜索条件相匹配的新行直到它完成”。并且SQL Server通过使用防止冲突插入的范围锁来强制执行此操作。

如果您在EmployeeInfo.FirstName上有一个索引,SQL可能可以采用一个窄锁来执行此操作。但是如果没有索引,SQL将会阻止任何插入。另外,如果SELECT查询谓词不支持索引,则会阻塞所有插入。

可以对锁的当前状态:

select @@spid this_session, * 
from sys.dm_tran_locks 

。并注意,这种行为使得SERIALIZABLE成为一个不太有用的隔离级别。而且您应该只使用READ COMMITTED和SNAPSHOT,可能会为特定事务添加锁定提示。

+0

您是否可以扩展您的断言,这种行为使'serializable'不是很有用?我觉得它是一个非常有用的隔离级别,我想知道更多关于是什么使你得出相反的结论。 – SqlZim

+0

这种情况确实是一个例子。一个简单的SELECT查询阻塞了整个表上的插入,原因不明显。所以它往往会大大降低应用程序的并发性。而这种令人讨厌的副作用是它为死锁创造了很多机会。并没有什么好处,因为它所保证的隔离行为并不是非常有用。 –

+0

听起来更像是你说它不是非常有用的_default_隔离级别。这是你的意思吗? – SqlZim