可重複讀隔離級別裡的可能死鎖

2021-09-22 07:10:55 字數 3551 閱讀 2629

在今天的文章裡我想談論下在可重複讀隔離級別(transaction isolation level repeatable read)裡,當你執行事務時可能引起的2類死鎖。當你使用可重複讀(repeatable read)隔離級別設定你的事務,sql server對讀取資料把持需要的共享鎖(shared locks)直到事務的結束(commit或rollbak)。然後當你嘗試修改讀取的資料(通過update語句),如果同樣的事務多次併發執行,它會英氣不同型別的死鎖。

迴圈死鎖是其中乙個最常見的死鎖——你就以不同順序訪問資源(例如不同表),最後每個查詢等待另乙個。使用可重複讀隔離級別,但你用多個事務只讀寫乙個表時,也是有可能引起迴圈死鎖。我們來看第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

13select

*from

person.person

14where modifieddate =

'20030209'15

16update

person.person

17set firstname =

'...'18

where modifieddate =

'20030209'19

20rollback

21go

這是第2個事務的t-sql**:

1

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

從2個**可以看到,2個資料範圍被讀取,最後被更新。如果2個事務在同個時間執行,會發生迴圈死鎖,因為資料範圍在不同順序裡被訪問。

當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

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

因此在剛開始只有乙個select語句能獲得必須的更新鎖(update locks)(更新鎖(update lock)與本身更新鎖(update lock)不相容),繼續使用update語句,最後會釋放需要的鎖。然後第2個事務會繼續它的select和update語句。

這裡你要使用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 一書中,講到這種隔離級別很好的解決了髒讀問題,也就是讀取的資料都是事務開...