事務如何是原子的?
對於如何消化事務是原子的這一事實,我真的很困惑。如果事務是一組“查詢”,那麼它將如何是原子的。我將“查詢”一詞與一般 SQL 查詢相關聯。因此,一個事務就變成了同時執行的一組 SQL 查詢。但是事實上,每個查詢都有多個操作,如果以後的查詢中發生錯誤,我真的不知道以前執行的查詢(在同一個集合中)如何回滾。我在這裡想念什麼?謝謝!
像這樣封裝的事務是原子的:
BEGIN TRAN UPDATE dbo.Users SET Reputation = Reputation + 1 WHERE Id = 26837; UPDATE dbo.Posts SET Score = Score + 1 WHERE Id = 227563; COMMIT
在這種情況下,兩個單獨表上的兩個更新將一起送出,或者它們將一起回滾(失敗)。原子性意味著這是將送出的事務的最小單元。
但是,如果稍後您嘗試在該範圍之外執行單獨的查詢,那將是一個單獨的事務。
如果你嘗試這樣的事情:
BEGIN TRAN UPDATE dbo.Users SET Reputation = Reputation + 1 WHERE Id = 26837;
然後在您的應用程序中,您執行其他類型的工作,例如 C# 程式碼,然後稍後返回數據庫並執行以下操作:
UPDATE dbo.Posts SET Score = Score + 1 WHERE Id = 227563; COMMIT
然後,較早的使用者更新和您後續的文章更新都將同時成功或失敗。
但是,在現實生活中,您不能長時間保持這樣的事務打開,因為您將阻止其他人在數據庫中工作。這就是為什麼你會經常看到諸如“讓你的交易簡短而甜蜜”之類的建議,這意味著,進入,完成你的工作,然後退出。不要明確保持交易開放。
TL;博士; 事務日誌包含重新創建或撤消每個事務所需的所有資訊,具體取決於它是否包含該事務的送出記錄。
在 SQL 數據庫中,事務原子性最常使用預寫日誌來實現(這意味著事務日誌條目是在實際表和索引更新之前寫入的)。
嚴格意義上的查詢,
SELECT
即不改變數據庫狀態的語句和其他讀取操作,不會被記錄,因為沒有任何東西可以送出或回滾,因此原子性的概念在這裡並不適用,至少在 DBMS 級別。如果後續查詢之一失敗並導致回滾,則使用查詢結果的應用程序可能需要通過丟棄先前查詢的結果來強制執行原子性。當 DML 語句 (
INSERT
,UPDATE
,DELETE
,MERGE
) 和其他更改數據庫狀態的語句被執行時,它們所做的更改首先被寫入預寫日誌 (WAL)。如果所有語句都成功並且發出了送出(顯式或隱式),則該事實也記錄在 WAL 中,並且日誌被持久化。這使更改持久。在檢查點或日誌重放期間,它們可能會在稍後的某個時間被寫入實際的表和索引段。但是,如果其中一條語句失敗,則該事務的日誌中將沒有送出記錄,並且 DBMS 將使用該事務的先前日誌記錄撤消到目前為止所做的表和索引更改。
同樣,如果 DBMS 程序崩潰,或者斷電,也不會有正在進行的事務的送出記錄,並且可能已經持久化的表或索引更改將在日誌重放期間撤消。