在今天的文章裡我想談論下在可重複讀隔離級別(transaction isolation level repeatable read)裡,當你執行事務時可能引起的2類死鎖。當你使用可重複讀(repeatable read)隔離級別設定你的事務,sql server對讀取資料把持需要的共享鎖(shared locks)直到事務的結束(commit或rollbak)。然後當你嘗試修改讀取的資料(通過update語句),如果同樣的事務多次併發執行,它會英氣不同型別的死鎖。
迴圈死鎖是其中乙個最常見的死鎖——你就以不同順序訪問資源(例如不同表),最後每個查詢等待另乙個。使用可重複讀隔離級別,但你用多個事務只讀寫乙個表時,也是有可能引起迴圈死鎖。我們來看第1個事務的t-sql**:
1這是第2個事務的t-sql**:settransaction
isolation
level
repeatable
read2go
34begin
transaction56
select
*from
person.person
7where modifieddate =
'20030208'8
9update
person.person
10set firstname =
'...'11
where modifieddate =
'20030208'12
13select
*from
person.person
14where modifieddate =
'20030209'15
16update
person.person
17set firstname =
'...'18
where modifieddate =
'20030209'19
20rollback
21go
1從2個**可以看到,2個資料範圍被讀取,最後被更新。如果2個事務在同個時間執行,會發生迴圈死鎖,因為資料範圍在不同順序裡被訪問。settransaction
isolation
level
repeatable
read2go
34begin
transaction56
select
*from
person.person
7where modifieddate =
'20030209'8
9update
person.person
10set firstname =
'...'11
where modifieddate =
'20030209'12
13select
*from
person.person
14where modifieddate =
'20030208'15
16update
person.person
17set firstname =
'...'18
where modifieddate =
'20030208'19
20rollback
21go
當sql server開始執行update語句,必須的更新鎖(update lock(u))不能被獲取,因為更新鎖(update lock)與來自不同會話已授予的共享鎖(shared lock)不相容。因為在其它會話共享鎖(shared lock)已獲得,最後2個update語句會等待——在乙個表上就有了經典的迴圈鎖!在這個情況下你必須重寫你的**來讓這個特定鎖得到解決——以同個順序訪問你的資料範圍。
使用可重複讀隔離級別的第2類死鎖會發生,如果你讀取資料,有意向稍後去更新。我們來看1個簡單事務的t-sql**:
1為了引起這類死鎖,你只要通過多個會話執行事務。如你從**裡所見,你甚至不需要訪問不同資料範圍。我們來解釋下這裡反生了什麼。當這個事務在多個會話併發執行時,對讀取的資料,所有的會話會獲得共享鎖。settransaction
isolation
level
repeatable
read2go
34begin
transaction56
select
*from
person.person
7where modifieddate =
'20030208'8
9update
person.person
10set firstname =
'...'11
where modifieddate =
'20030208'12
13rollback
14go
因為你在可重複讀裡把持共享受(shared lock)直到事務的結束(commit或rollback),下列update語句不能獲得需要的更新鎖(update locks),因為它們已被不同會話裡獲得的共享鎖(shared locks)所阻塞。死鎖!
這裡死鎖可以通過在select語句裡使用提示來提前獲取乙個更新鎖(update lock)。
1因此在剛開始只有乙個select語句能獲得必須的更新鎖(update locks)(更新鎖(update lock)與本身更新鎖(update lock)不相容),繼續使用update語句,最後會釋放需要的鎖。然後第2個事務會繼續它的select和update語句。settransaction
isolation
level
repeatable
read2go
34begin
transaction56
select
*from person.person with
(updlock)
7where modifieddate =
'20030208'8
9update
person.person
10set firstname =
'...'11
where modifieddate =
'20030208'12
13rollback
14go
這裡你要使用sql server內部在更新執行計畫裡使用的同樣的技術:在可重複讀隔離級別裡,當你讀取的資料稍後有意向去更新時,在讀取階段你需要獲得乙個更新鎖來阻止這類死鎖。
從這篇文章裡可以看到,如果你使用可重複讀隔離級別是很容易引起各類死鎖。因此當你在這個特定隔離級別裡寫事務時,你必須要非常小心。
感謝關注!
可重複讀隔離級別裡的可能死鎖
在今天的文章裡我想談論下在可重複讀隔離級別 transaction isolation level repeatable read 裡,當你執行事務時可能引起的2類死鎖。當你使用可重複讀 repeatable read 隔離級別設定你的事務,sql server對讀取資料把持需要的共享鎖 share...
事務隔離級別 可重複讀
mysql pom 5 select global.tx isolation global.tx isolation repeatable read 如果事務隔離級別顯示repeatable read,即是可重複讀。在資料庫操作中,為了有效保證併發讀取資料的正確性,提出的事務隔離級別。我們的資料庫鎖...
MySQL事務隔離級別可重複讀測試
開啟rds,查詢當前的事務隔離級別select tx isolation查詢得到時候可重複讀,於是做了如下測試。可重複隔離級別的特點是,每個事務可以在乙個事務中可以反覆讀取資料,每次讀取到的資料都是相同的。在 高效能mysql 一書中,講到這種隔離級別很好的解決了髒讀問題,也就是讀取的資料都是事務開...