在Oracle中,Oracle會在執行DDL之前發出COMMIT語句,然後執行DDL操作,最後發出COMMIT操作。
從現在開始,假設DDL不是自動提交的,而是事務的壹部分。
那麽DDL必須滿足READ COMMIT隔離機制,即用戶執行的DDL語句在提交前不能被其他用戶看到。例如,用戶執行CREATE TABLE T的語句,然後對T執行壹些DML .此時,其他會話無法看到T表。
會話a執行了alter tablet modify,創建了default sysdate not null,然後在t表中插入了壹些內容,但是沒有提交。
此時,會話B試圖插入T表。如果DDL語句不是事務的壹部分,則插入會話B和插入會話A之間沒有沖突,但現在情況不同了。因為A已經修改了T表,所以默認值已經添加到創建的列中並設置為NOT NULL,並且此修改當前對會話B不可見,因為A尚未提交修改。此時,如果B會話的插入沒有提供所創建列的值,則插入操作將被鎖定。對於B,表結構中的創建列仍然為空,因此允許插入創建列為空的記錄。但是,由於A已經將T的CREATED列設置為非空並包含默認值,因此B的插入必須被鎖定,否則,如果A和B都提交了,會話A將發現即使執行了DDL語句,T表中仍有CREATED列為空的記錄。為了實現DDL可回滾和多版本讀取壹致性的功能,Oracle必須在DDL發生後鎖定修改後的表,以避免其他會話訪問造成的不壹致性。這將導致Oracle中的鎖升級,嚴重影響Oracle的並發性,並大大增加死鎖的概率。
有些人可能想知道為什麽SQLSERVER或其他壹些數據庫可以回滾DDL語句。事實上,如前所述,Oracle也有能力實現DDL回滾,但這會極大地影響Oracle的並發性。要知道,Oracle的鎖定機制和多版本讀取壹致性使得Oracle的並發性在所有數據庫產品中首屈壹指。顯然,為了實現DDL的回滾而損失最值得稱贊的並發性是不值得的。其他數據庫之所以可以實現,是因為這些數據庫的鎖定機制存在壹些缺陷,例如大量的鎖會占用系統資源,讀寫操作會相互阻塞,以及行級鎖可能會自動升級為表級鎖。