1、 Oracle並發控制的基礎,是多版本。
2、 Oracle保證讀一致性,並且永遠都不會髒讀(即讀其他事務的未提交資料)。Oracle查詢得到的結果集肯定是某個時間點的當前結果集:
i. 遊標(cursor)開啟時的時間點。
ii. 語句開始執行時的時間點。Oracle總是保證語句級的讀一致性。
iii. 查詢所屬事務開始的時間點。當交易隔離等級是serializable或read only時。
3、 Oracle中的查詢,不會被寫入阻塞,Oracle中沒有讀共用鎖定。並且Oracle的非阻塞讀,不是以髒讀為代價的:Oracle永遠都不會髒讀(第2條)。
4、 Oracle提供了read committed、serializable和read only三種交易隔離等級。
i. Oracle不需要read uncommited層級,Oracle不允許髒讀。因為Oracle不需要髒讀,就完全可以得到髒讀的好處(即無阻塞讀)。
ii. read committed是oracle的預設隔離等級,也是最常用的隔離等級。SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
iii. Oracle沒有提供read repeatable隔離等級。
1. Oracle不使用共用讀鎖就保證了讀一致性,更具並發性。
2. Oracle在非serializable和read only隔離等級下,沒法保證不產生丟失更新。需要採用鎖定來解決。(第5條)
iv. Oracle實現serializable隔離等級,就是把通常在語句級得到的讀一致性擴充到事務級。Oracle採用了一種樂觀的方法來實現serializable隔離等級,它認為本事務想要更新的資料不會被其他事務所更新。如果被更新了,Oracle就會產生ORA-08117錯誤。
v. read only隔離等級就是唯讀serializable隔離等級。用於為報表查詢需求提供支援。在serializable和read only隔離等級中,如果重建資料所需的undo資訊已經被迴繞而不存在了,則會產生ORA-1555錯誤。
5、 Oracle的多版本讀一致性,需要使用鎖定來解決順序讀問題。
i. 悲觀鎖定:僅用於有狀態或有串連環境。select … for update [nowait]。如果指定nowait,則如果其他事務正在更新或已經更新了這一行,則會產生ORA-00054錯誤;如果不指定nowait,則會一直等待下去。
ii. 樂觀鎖定:
1. 樂觀鎖定,如果探索資料已經被修改,那麼要根據實際業務需求,來採取措施:
a) 擷取新值,重新開始。
b) 根據商務規則解決更新衝突,試圖合并兩個更新的值。
2. 實現樂觀鎖定的方法:更新時,除了主鍵作為條件,另外增加一個條件。判斷更新行數,如果是0行,說明資料已經改變。
a) 儲存所有欄位的舊值,作為更新條件。注意NULL值的判斷。最簡單的方法,不需要額外增加列。
b) 增加一個版本列,每次更新加1。適用於非10g的新表。
c) 增加一個時間戳記列(TIMESTAMP),為最後一次更新時間。如果這個時間戳記沒有業務意義,建議用預存程序封裝更新。適用於非10g的新表,並且可以獲得得到最後一次更新時間的額外好處。
d) 使用所有欄位校正和的舊值。不需要額外增加列,但是計算大欄位時效能低下。
e) 使用Oracle 10g新提供的ORA_ROWSCN。為了避免“假警示”,需要帶上ROWDEPENDENCIES重建資料庫表。不需要額外增加列,輕量級。
6、 Oralce的多版本讀一致性,可能造成小的“熱表”上的大量IO。方法就是減少事務執行時間。啟動並執行時間越長,也就需要更多的IO來讀取undo中的舊資料,這是一個惡性迴圈。
7、 寫阻塞:
i. 兩個會話同時插入(insert)一行,主鍵或有唯一約束的列值相同。通過使用序列(sequence)產生主鍵,避免了一半問題。
ii. 如果update或delete產生阻塞,則說明程式可能丟失問題的BUG。
8、 寫一致性:為了保證寫一致性,Oracle可能會悄悄的復原更新,並重新啟動。這會導致BEFORE觸發器執行兩次。方法就是不在BEFORE觸發器中使用自治事務,和執行非事務性語句。
9、 死結:Oracle極少出現死結。檢測到死結會產生ORA-00060錯誤。
10、 Oracle的約束,可以設定為deferrable。這樣,可以設定約束為延遲狀態(set constraint 約束名 deferred/immediate),來允許事務過程中的暫時違反約束。如外鍵的串聯更新。
11、 在Oracle中,每個事務都應該只在必要時才提交,而在此之前不能提交。事務的大小要根據需求而定。鎖、阻塞等問題並不是決定事務大小的關鍵,資料完整性才是確定事務大小的根本。
12、 rollback會做大量的工作,與rollback相比,commit完成的工作非常少。除非不得已,否則不希望復原。常識是:既然不想commit,又何苦去做所有這些工作。