Oracle 和 DB2 比較與相容性/程序模型/鎖定
隔離。
當您在資料庫上擁有超過一個使用者時,您必須擁有一個機制來防止他們同時訪問相同的資料。交易對記憶體中資料的更改方式、這些更改如何記錄以及這些記憶體中的更改如何寫入磁碟,都有一個順序。每個步驟都需要一定的時間來執行,並且一些步驟旨在規避昂貴的 I/O 操作——更改不會在進行時寫入,它們將被儲存起來,以便可以一舉寫入一組更改。此操作序列中的每個步驟都需要時間,如果資料庫正在為多個使用者提供服務,則來自一個使用者的更改有機會影響來自另一個使用者的更改。隨著現代高速處理器的出現、延遲寫入以及眾多併發使用者,這種事件發生的可能性急劇增加,但它只需要發生一次就會成為一個大問題。
此類問題的示例是,如果兩個使用者讀取和更改相同的資料,如果沒有控制,則最後寫入更改的使用者“獲勝”——他們將覆蓋另一個使用者所做的更改。此類問題稱為丟失更新。
Oracle 和 DB2 處理此問題的方式是使用鎖定——首先鎖定要更新的記錄。與資料庫操作的許多方面一樣,使用鎖時存在權衡,這種權衡是,如果您鎖定資料庫的大部分,資料庫將很快變得無法使用。為了解決這個問題,資料庫在資料庫內採用不同級別的鎖定,以及不同的鎖定和鎖升級策略。此概述描述了資料庫在其鎖定策略中需要考慮的各種情況,Oracle 和 DB2 的各個部分描述了它們如何實施這些策略。
問題
當用戶在沒有任何控制的情況下讀取和寫入相同資料時,會發生以下問題
• 幻讀——一個事務讀取多個行,而另一個獨立事務刪除或新增行。如果第一個事務發出完全相同的讀取,它將獲得不同的行數。
• 髒讀——一個事務讀取來自另一個事務的未提交資料。
• 丟失更新——一個事務中的更新覆蓋了另一個事務中的資料。
• 不可重複讀——一個讀取資料的兩次事務不應該在其他事務讀取之間發生資料更改。
需要注意的是,不僅僅是 DML 會改變資料庫,像 Drop 或 Alter 這樣的 DDL 也會改變表。您的鎖定策略需要針對 DDL 更改以及 DML 更改。
許多資料庫操作都涉及遊標。遊標是用於遍歷一組返回行的裝置——它是指向您在集合中的位置的指標。鎖定需要滿足遊標操作,以便對集合中的行(插入和刪除)的更改不會中斷遊標處理,這種中斷稱為遊標不穩定,當大量使用者可以同時獲取大量行時,這是一個特別敏感的區域。在這種情況下,使用者不會影響單行資料,而是影響多行資料。如果您有許多使用者這樣做,實施不當的鎖定策略可能會使資料庫陷入癱瘓。
解決方案
為了避免這些問題,ANSI/ISO SQL 標準定義了許多隔離級別
SERIALIZABLE. 所有事務都像序列發出一樣執行(即一個接一個)。即使 DBMS 可以同時執行多個事務,這也適用,就所有意圖和目的而言,事務執行就像它們完全隔離一樣。
REPEATABLE READ. SELECT 讀取的所有行都不能更改。但是,如果 SELECT 具有範圍 WHERE 子句,則可能會發生幻讀,因為此隔離級別會在所有檢索到的資料上獲取讀鎖,但不會獲取範圍鎖。
READ COMMITTED. 在 SELECT 語句中檢索的資料可能會被修改,因此可能會發生不可重複讀取。這是因為讀鎖是在選定的資料上獲取的,但它們會立即釋放,而寫鎖是在事務結束時釋放的。
READ UNCOMMITTED. 一個事務可能會看到另一個事務所做的未提交更改。
DBMS 的預設隔離級別各不相同,大多數供應商允許使用者更改隔離級別並在其 SELECT 語法中指定不同的鎖。
隔離級別是平衡需要維護讀取一致性的多使用者資料庫的需求的一種方法。這是一個雙重問題,首先您需要了解供應商採用的方法,然後您需要了解在您正在使用的系統中實施了哪些方法(以及原因)。