READ COMMITTED
READ COMMITTED這是數據庫默認的隔離級別。它能保證你不能讀取那張表格數據,只要有其它事務還在改變這張表格數據。可是,因為sql server在select操作的時,鎖表格時間就那么一小會兒,如果一個事務在READ COMMITTED級別下重復讀數據,這樣那個數據可能還是會變,或者新的行可能出現并且還是滿足了原來的查詢條件,能查詢到。你以為還是原來的那些數據,其實又有新的內容在里面了。
READ COMMITTED有兩個地方要注意。第一,它能阻止?dirty reads,但是第二,它還是允許non-repeatable reads和phantom reads.
第一點阻止?dirty reads,舉個例子,
-- Step 1:
-- Start a transaction but don't commit it
USE IsolationDB ;
GO
BEGIN TRAN
UPDATE IsolationTest
SET col2 = 'New Value' ;
-- 更新了數據,但未結束事務,事務還在影響這張表格。
-- Step 2:
-- Start a new connection and change your isolation level
USE IsolationDB ;
GO
SET TRANSACTION ISOLATION LEVEL READ COMMITTED ;
SELECT *
FROM IsolationTest ;
--
-- You should notice that the process blocks, and returns
-- no data or messages!
在READ COMMITTED級別下讀取。你注意到過程是堵塞的,不能返回數據,因為有一個修改事務影響著。
-- To finish up, perform the following two steps:
-- Step 3:
-- Return to the connection from Step 1 and issue a ROLLBACK
ROLLBACK TRANSACTION ;
-- 回滾事物嘍。
-- Step 4:
-- Rerun the SELECT statement in the connection from Step 2
SELECT *
FROM IsolationTest ;
--
-- Verify that the data is available 可以顯示數據了。只不過是原來的數據。
這個就不像READ UNCOMMITTED還能讀取。
看一下READ COMMITTED第二點,non-repeatable reads,舉個例子。
先關閉全部的查詢窗口。打開兩個新的查詢窗口。
-- Step 1:
-- Read data in the default isolation level
USE IsolationDB
SET TRANSACTION ISOLATION LEVEL READ COMMITTED ;
BEGIN TRAN
SELECT AVG(col1)
FROM IsolationTest ;
-- 第一步,設置了默認的隔離級別,開始一個事務來讀取平均值,
-- Step 2:
-- In a new connection, update the table:
USE IsolationDB ;
UPDATE IsolationTest
SET col1 =500
WHERE col1 =50 ;
-- 第二步,更新了表格。假設第一步已經結束了,那么第二步的將會更新成功,即使第一步的連接還是在事務里。這個UPDATE是一個自動提交的事務,所以SQL server會鎖住它,一旦提交完成又自動釋放它。
-- Step 3:
-- Go back to the first connection and
-- run the same SELECT statement:
SELECT AVG(col1)
FROM IsolationTest ;
-- 第三步,再次執行查詢語句,平均值就變了,這就是一個non-repeatable read。默認的READ COMMITTED隔離級別能阻止正在讀取的數據被改變,但是僅僅指的是正在被讀取的數據被改變。一旦這個讀取操作結束了,那么其它的事務就能改變數據,即使讀取操作所在的那個事務還打開著,沒有提交結束。結果就是,也不能保證我們能取得一樣的數據。