2011-08-15 56 views
2

想象我有這個簡單的表:甲骨文 - Oracle如何管理交易的具體DML語句

Table Name: Table1 
Columns: Col1 NUMBER (Primary Key) 
      Col2 NUMBER 

如果我將記錄插入表1沒有提交...

INSERT INTO Table1 (Col1, Col2) Values (100, 1234); 

Oracle如何知道下一個INSERT語句違反PK約束,因爲還沒有提交到數據庫。

INSERT INTO Table1 (Col1, Col2) Values (100, 5678); 

凡/ Oracle如何管理事務,以便它知道我違反約束的時候我還沒有提交事務呢。

回答

8

Oracle創建一個索引來強制執行主鍵約束(默認情況下爲唯一索引)。當會話A插入第一行時,索引結構會更新,但不會提交更改。當會話B嘗試插入第二行時,索引維護操作注意到索引中已經有一個具有該特定鍵的未決條目。會話B無法獲取保護共享索引結構的鎖存器,因此它將阻塞,直到會話A的事務完成。此時,會話B將能夠獲得鎖存器並對索引進行自己的修改(因爲A回滾),或者它會注意到其他條目已經被提交併且會拋出唯一的約束違例(因爲A提交)。

+0

Oracle在哪裏/如何管理?在某種系統表中? – contactmatt

+0

@contactmatt - 在索引結構本身。就像在表中的一個塊的每一行中都有一個鎖標誌一樣,以便Oracle不需要單獨的鎖管理器,索引塊中也有類似的結構。 –

+0

+1。很好解釋。我總是有這個問題問某人:「這些信息寫在哪裏(索引條目,表條目)?在重做/撤消日誌中?」 – Guru

1

僅僅因爲您還沒有完成提交,並不意味着第一條記錄尚未發送到服務器。 Oracle已經知道你打算插入第一條記錄。當你插入第二條記錄時,Oracle知道肯定沒有違反約束條件就無法成功,所以它拒絕。

如果另一個用戶要插入第二條記錄,如果第一條記錄尚未提交,Oracle將接受它。如果第二個用戶在提交之前提交,則提交將失敗。

+0

不完全 - 第二次會議掛起,等待第一筆交易的結果。嘗試一下。 – DCookie

+0

你是什麼意思,「所以它拒絕。」?是你提到的錯誤信息? – Guru

+0

我確實嘗試過(請參閱我對其他答案的評論),並且您是正確的:第二個會話掛起,直到第一個提交/回滾。有了'拒絕',我預計會違反約束條件。 – Jeff

2

這是因爲執行主鍵約束的唯一索引。即使插入到數據塊中尚未提交,即使在另一個會話中完成了將重複條目添加到索引中的嘗試也無法成功。

+0

我做了一些測試,事實上:第二個事務將等待(鎖定),直到您提交或回滾第一個會話。 – Jeff

0

除非特定約束是「延遲」,否則將在語句執行時檢查。如果它被推遲,它將在交易結束時被檢查。我假設你沒有推遲你的PRIMARY KEY,這就是爲什麼你甚至在你提交之前得到違規。

這是如何真正完成的實現細節,可能因不同的數據庫系統甚至同一系統的不同而不同。應用程序開發人員不應該對此做過多的假設。在甲骨文的情況下,PRIMARY KEY使用基礎指數出於性能原因,而有些系統甚至不需要索引(如果您可以接受相應的性能影響)。

順便說一句,可延遲Oracle PRIMARY KEY約束依賴於非唯一索引(與使用唯一索引的不可延遲PRIMARY KEY相比)。

---編輯---

我才意識到,你甚至不提交第一個INSERT。我認爲Justin的回答很好地解釋了鎖定爭用如何導致其中一項交易停滯。