2017-05-20 68 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