国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

可重復讀隔離級別里的可能死鎖

2024-07-21 02:46:13
字體:
來源:轉載
供稿:網友
可重復讀隔離級別里的可能死鎖

在今天的文章里我想談論下在可重復讀隔離級別(Transaction Isolation Level Repeatable Read)里,當你運行事務時可能引起的2類死鎖。當你使用可重復讀(Repeatable Read)隔離級別設置你的事務,SQL Server對讀取數據把持需要的共享鎖(Shared Locks)直到事務的結束(COMMIT或ROLLBAK)。然后當你嘗試修改讀取的數據(通過UPDATE語句),如果同樣的事務多次并發運行,它會英氣不同類型的死鎖。

循環死鎖(Cycle Deadlock)

循環死鎖是其中一個最常見的死鎖——你就以不同順序訪問資源(例如不同表),最后每個查詢等待另一個。使用可重復讀隔離級別,但你用多個事務只讀寫一個表時,也是有可能引起循環死鎖。我們來看第1個事務的T-SQL代碼:

 1 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ 2 GO 3  4 BEGIN TRANSACTION 5  6 SELECT * FROM Person.Person 7 WHERE ModifiedDate = '20030208' 8  9 UPDATE Person.Person10 SET FirstName = '...'11 WHERE ModifiedDate = '20030208'12 13 SELECT * FROM Person.Person14 WHERE ModifiedDate = '20030209'15 16 UPDATE Person.Person17 SET FirstName = '...'18 WHERE ModifiedDate = '20030209'19 20 ROLLBACK21 GO

這是第2個事務的T-SQL代碼:

 1 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ 2 GO 3  4 BEGIN TRANSACTION 5  6 SELECT * FROM Person.Person 7 WHERE ModifiedDate = '20030209' 8  9 UPDATE Person.Person10 SET FirstName = '...'11 WHERE ModifiedDate = '20030209'12 13 SELECT * FROM Person.Person14 WHERE ModifiedDate = '20030208'15 16 UPDATE Person.Person17 SET FirstName = '...'18 WHERE ModifiedDate = '20030208'19 20 ROLLBACK21 GO

從2個代碼可以看到,2個數據范圍被讀取,最后被更新。如果2個事務在同個時間執行,會發生循環死鎖,因為數據范圍在不同順序里被訪問。

當SQL Server開始執行UPDATE語句,必須的更新鎖(Update Lock(U))不能被獲取,因為更新鎖(Update Lock)與來自不同會話已授予的共享鎖(Shared Lock)不兼容。因為在其它會話共享鎖(Shared Lock)已獲得,最后2個UPDATE語句會等待——在一個表上就有了經典的循環鎖!在這個情況下你必須重寫你的代碼來讓這個特定鎖得到解決——以同個順序訪問你的數據范圍。

讀寫/更新死鎖(Read/Update Deadlock)

使用可重復讀隔離級別的第2類死鎖會發生,如果你讀取數據,有意向稍后去更新。我們來看1個簡單事務的T-SQL代碼:

 1 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ 2 GO 3  4 BEGIN TRANSACTION 5  6 SELECT * FROM Person.Person 7 WHERE ModifiedDate = '20030208' 8  9 UPDATE Person.Person10 SET FirstName = '...'11 WHERE ModifiedDate = '20030208'12 13 ROLLBACK14 GO

為了引起這類死鎖,你只要通過多個會話運行事務。如你從代碼里所見,你甚至不需要訪問不同數據范圍。我們來解釋下這里反生了什么。當這個事務在多個會話并發執行時,對讀取的數據,所有的會話會獲得共享鎖。

因為你在可重復讀里把持共享受(Shared Lock)直到事務的結束(COMMIT或ROLLBACK),下列UPDATE語句不能獲得需要的更新鎖(Update Locks),因為它們已被不同會話里獲得的共享鎖(Shared Locks)所阻塞。死鎖!

這里死鎖可以通過在SELECT語句里使用提示來提前獲取一個更新鎖(Update Lock)。

 1 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ 2 GO 3  4 BEGIN TRANSACTION 5  6 SELECT * FROM Person.Person WITH (UPDLOCK) 7 WHERE ModifiedDate = '20030208' 8  9 UPDATE Person.Person10 SET FirstName = '...'11 WHERE ModifiedDate = '20030208'12 13 ROLLBACK14 GO

因此在剛開始只有一個SELECT語句能獲得必須的更新鎖(Update Locks)(更新鎖(Update Lock)與本身更新鎖(Update Lock)不兼容),繼續使用UPDATE語句,最后會釋放需要的鎖。然后第2個事務會繼續它的SELECT和UPDATE語句。

這里你要使用SQL Server內部在更新執行計劃里使用的同樣的技術:在可重復讀隔離級別里,當你讀取的數據稍后有意向去更新時,在讀取階段你需要獲得一個更新鎖來阻止這類死鎖。

小結

從這篇文章里可以看到,如果你使用可重復讀隔離級別是很容易引起各類死鎖。因此當你在這個特定隔離級別里寫事務時,你必須要非常小心。

感謝關注!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 敖汉旗| 宁波市| 黄梅县| 綦江县| 玉龙| 临漳县| 全椒县| 浪卡子县| 哈密市| 都江堰市| 民和| 忻州市| 富锦市| 广丰县| 婺源县| 嘉义县| 中方县| 桐乡市| 久治县| 绥阳县| 哈巴河县| 抚州市| 文山县| 武安市| 山东省| 江口县| 咸丰县| 湖北省| 龙陵县| 六枝特区| 武夷山市| 宜阳县| 德州市| 嘉黎县| 新巴尔虎左旗| 英德市| 乌海市| 望谟县| 望谟县| 遂宁市| 辰溪县|