oracle中ddl爲何不能回滾

ITPUB上看到有人提出了這個問題。在Sqlserver或一些其餘的數據庫中,DDL語句也是能夠回滾的,那麼Oracle爲何不能回滾DDL語句呢。html

這個問題來自:http://www.itpub.net/thread-1300088-1-5.html數據庫

 

 

要說明這個問題,首先須要說明什麼是DDL語句。DDL語句是數據定義語句,包括各類數據對象的建立、修改和刪除,以及受權等操做。併發

OracleDDL語句將轉化爲修改數據字典表的DML語句。一個簡單的修改表的DDL語句,會致使Oracle在後臺經過遞歸SQL語句進行大量的查詢和修改的操做。spa

若是有興趣,能夠經過SQL_TRACE根據一下DDL語句,檢查一下Oracle後臺實際執行了哪些操做。.net

Oracle中,Oracle執行DDL前會發出一個COMMIT語句,而後執行DDL操做,最後再發出一個COMMIT操做。設計

前面提到了對於Oracle而言,DDL其實是數據字典表的一系列的修改,也就是數據字典表的DML操做,那麼理論上講Oracle是徹底有能力實現DDL語句的回滾的,那麼Oracle爲何設計成如今的工做方式。要知道Oracle以靈活和強大的可定製性著稱,可是Oracle沒有給用戶任何回滾DDL的可能性,顯示是存在着十分充分的理由。server

首先分析一下Oracle爲何要在DDL語句以前和以後各執行一次COMMIT,其實道理很簡單,Oracle是爲了將用戶的讀寫操做和數據字典的修改隔離開,用戶數據的讀寫不該該和數據字典的操做放在同一個事務中。htm

爲了說明Oracle爲何不回滾DDL語句,下面假設Oracle能夠回滾DDL語句,看看這會給Oracle數據庫帶來什麼影響。對象

從如今開始,假設DDL並不會自動提交,而是事務中的一部分。遞歸

那麼DDL就要知足READ COMMIT隔離機制,也就是說,用戶執行的DDL語句在提交前,其餘用戶是沒法看到的。好比A用戶執行CREATE TABLE T的語句,而後對T執行了一些DML。而這時其餘會話是沒法看到T表的。

那麼考慮這樣的狀況,存在表T,包含兩個列,一個ID列,一個CREATED列。

A會話執行了ALTER TABLE T MODIFY CREATED DEFAULT SYSDATE NOT NULL,而後對T表進行了一些插入,可是沒有提交。

這時B會話嘗試插入T表,若是DDL語句不是事務的一部分,那麼B的插入和A會話的插入之間沒有衝突,可是如今狀況不一樣,因爲A執行了T表的修改,爲CREATED列增長了默認值並設置爲NOT NULL,並且這個修改B會話當前是看不到的,由於A並無提交修改。這時若是B會話的插入沒有提供CREATED列的值,則插入操做將被鎖定。對於B而言,表結構中CREATED列仍然是可空的,所以容許插入CREATED列爲空的記錄,可是因爲A已經設置TCREATED列非空,且包含默認值,所以B的插入必須被鎖定,不然若是AB所有提交,A會話會發現即便執行了DDL語句,T表中仍然存在CREATED爲空的記錄。Oracle爲了實現DDL能夠回滾的功能,且實現多版本讀一致性,那麼就必須在DDL發生後,將修改的表鎖定,避免其餘會話的訪問形成不一致。這會致使Oracle中出現鎖升級的狀況,而且嚴重的影響Oracle的併發性,並且會大大增長死鎖產生的概率。

也許有人奇怪SQLSERVER或一些其餘的數據庫爲何能夠實現DDL語句的回滾。事實上,前面提到了Oracle也是有能力實現DDL回滾的,只是這會極大的影響Oracle的併發性。要知道,Oracle的鎖機制和多版本讀一致性使得Oracle的併發性在全部數據庫產品中數一數二。顯然爲了實現DDL的回滾而損失最值得稱道的併發性,Oracle認爲得不償失。其餘數據庫之因此能夠實現,是由於這些數據庫的鎖機制自己就存在必定缺陷,好比大量的鎖會佔用系統的資源、讀寫操做互相阻塞、行級鎖可能自動升級爲表級鎖。因爲已經存在這些問題,因此實現DDL的回滾並不會在很大程度上使得併發性惡化,由於即便DDL不將行鎖升級爲表鎖,可能其餘的因素也會致使這種狀況的發生。

相關文章
相關標籤/搜索