讀/寫死鎖

我喜歡寫死鎖這個話題,由於在你寫代碼的時候,若是不考慮仔細,會有太多不一樣的方法和狀況形成死鎖。在今天的文章裏,我想向你展現下,從同個表,用不一樣的順序來讀寫記錄時,會發生死鎖的狀況。sql

讀/寫死鎖

下列代碼展現了簡單的表定義,這裏我也插入2條記錄。 spa

-- Create a new table
CREATE TABLE Foo
(
    Col1 INT IDENTITY(1, 1) NOT NULL PRIMARY KEY,
    Col2 INT,
    Col3 INT
)
GO

-- Insert 2 records
INSERT INTO Foo VALUES (1, 1), (2, 2)
GO

SELECT * FROM Foo
GO

如今假設下列狀況:你有2個查詢,用來讀寫訪問記錄,但你用不一樣的順序訪問記錄。第1個事務進行下列操做code

  • UPDATE第1條記錄
  • SELECT第2條記錄

第2個事務用相反的順序訪問一樣的記錄:blog

  • UPDATE第2條記錄
  • SELECT第1條記錄

下列代碼展現了這2個事務:事務

-- UPDATE 1st record
-- SELECT 2nd record
BEGIN TRANSACTION

UPDATE Foo SET Col3 = 3
WHERE Col1 = 1

SELECT * FROM Foo
WHERE Col1 = 2

ROLLBACK
GO

-- UPDATE 2nd record
-- SELECT 1st record
BEGIN TRANSACTION

UPDATE Foo SET Col3 = 3
WHERE Col1 = 2

SELECT * FROM Foo
WHERE Col1 = 1

ROLLBACK
GO

若是時機合適的話,這裏很容易觸發死鎖。由於2個事務都要在第1條和第2條記錄上得到排它鎖(X),而後他們不能在另外一條記錄上得到共享鎖(S)——死鎖發生!get

你如何解決這個死鎖呢?有不少方法:it

  • 在你整個事務裏按一樣的順序訪問記錄(第1條,而後第2條)
  • 在事務外進行SELECT語句
  • 在SELECT語句期間,啓用提交讀快照隔離級別( Read Committed Snapshot Isolation )來避免共享鎖

小結

在今天的文章裏,我向你展現了,SQL Server裏,當你在一個表,在不一樣的順序訪問的事務裏,是很容易觸發死鎖的。當你寫你的查詢時,你必需要認真考慮,按實際狀況實現你的查詢。常常有其餘人能夠阻塞你。io

原文連接:

https://www.sqlpassion.at/archive/2016/12/19/writeread-deadlocks table

相關文章
相關標籤/搜索