事務處理是所有大型資料庫產品的乙個關鍵問題,各資料庫廠商都在這個方面花費了很大精力,不同的事務處理方式會導致資料庫效能和功能上的巨大差異。
事務處理也是資料庫管理員與資料庫應用程式開發人員必須深刻理解的乙個問題,對這個問題的疏忽可能會導致應用程式邏輯錯誤以及效率低下。
下面我們針對oracle及sql server這兩種當前廣泛使用的大型資料庫產品,**一下它們在事務處理方面的一些差異。如沒有特殊說明,本文內容適用的資料庫產品版本為oracle9i及sql server 2000,其中的示例sql語句,對於oracle是在sql*plus中執行,而對於sql server 2000是在osql中執行。
一.事務的概念
事務可以看作是由對資料庫的若干操作組成的乙個單元,這些操作要麼都完成,要麼都取消,從而保證資料滿足一致性的要求。事務的乙個典型例子是銀行中的轉帳操作,帳戶a把一定數量的款項轉到帳戶b上,這個操作包括兩個步驟,乙個是從帳戶a上把存款減去一定數量,二是在帳戶b上把存款加上相同的數量。這兩個步驟顯然要麼都完成,要麼都取消,否則銀行就會受損失。顯然,這個轉帳操作中的兩個步驟就構成乙個事務。
資料庫中的事務還有如下acid特徵。
acid分別是四個英文單詞的首寫字母,這四個英文單詞是atomicity、consistency、isolation、durability,分別翻譯為原子性、一致性、隔離性、永續性。
原子性:指事務中的操作,或者都完成,或者都取消。
一致性:指事務中的操作保證資料庫中的資料不會出現邏輯上不一致的情況,一致性一般會隱含的包括在其他屬性之中。
隔離性:指當前的事務與其他未完成的事務是隔離的。在不同的隔離級別下,事務的讀取操作,可以得到的結果是不同的。
永續性:指對事務發出commit命令後,即使這時發生系統故障,事務的效果也被持久化了。與此相反的是,當在事務執行過程中,系統發生故障,則事務的操作都被回滾,即資料庫回到事務開始之前的狀態。
對資料庫中的資料修改都是在記憶體中完成的,這些修改的結果可能已經寫到硬碟也可能沒有寫到硬碟,如果在操作過程中,發生斷電或系統錯誤等故障,資料庫可以保證未結束的事務對資料庫的資料修改結果即使已經寫入磁碟,在下次資料庫啟動後也會被全部撤銷;而對於結束的事務,即使其修改的結果還未寫入磁碟,在資料庫下次啟動後會通過事務日誌中的記錄進行「重做」,即把丟失的資料修改結果重新生成,並寫入磁碟,從而保證結束事務對資料修改的永久化。這樣也保證了事務中的操作要麼全部完成,要麼全部撤銷。
二.事務設定及型別的區別
在sql server中有三種事務型別,分別是:隱式事務、顯式事務、自動提交事務,預設為自動提交。
自動提交,是指對於使用者發出的每條sql語句,sql server都會自動開始乙個事務,並且在執行後自動進行提交操作來完成這個事務,也可以說在這種事務模式下,乙個sql語句就是乙個事務。
顯式事務,是指在自動提交模式下以begin transaction開始乙個事務,以commit或rollback結束乙個事務,以commit結束事務是把事務中的修改永久化,即使這時發生斷電這樣的故障。例如下面是sql server中的乙個顯式事務的例子。
begintran
updateempsetename=』smith』whereempno=7369
insertintodeptvalues(60,』hr』,』gzh』)
commit
隱式事務,是指在當前會話中用set implicit_transactions on命令設定的事務型別,這時任何dml語句(delete、update、insert)都會開始乙個事務,而事務的結束也是用commit或rollback。
在oracle中沒有sql server的這些事務型別,預設情況下任何乙個dml語句都會開始乙個事務,直到使用者發出commit或rollback操作,這個事務才會結束,這與sql server的隱式事務模式相似。
三.事務隔離級別
在sql92標準中,事務隔離級別分為四種,分別為:read uncommitted、read committed、read repeatable、serializable,其中read uncommitted與read committed為語句級別的,而read repeatable與serializable是針對事務級別的。
在oracle和sql server中設定事務隔離級別的語句是相同的,都使用sql92標準語法,即:
set transaction isolation level read committed
上面示例中的read committed可以被替換為其他三種隔離級別中的任意一種。
1.sql server中的隔離級別及實現機制
在sql server中提供了所有這四種隔離級別。
下面我們討論在sql server中,這幾種隔離級別的含義及其實現方式。
read uncommitted:乙個會話可以讀取其他事務未提交的更新結果,如果這個事務最後以回滾結束,這時的讀取結果就可能是錯誤的,所以多數的資料庫應用都不會使用這種隔離級別。
read committed:這是sql server的預設隔離級別,設定為這種隔離級別的事務只能讀取其他事務已經提交的更新結果,否則,發生等待,但是其他會話可以修改這個事務中被讀取的記錄,而不必等待事務結束,顯然,在這種隔離級別下,乙個事務中的兩個相同的讀取操作,其結果可能不同。
read repeatable:在乙個事務中,如果在兩次相同條件的讀取操作之間沒有新增記錄的操作,也沒有其他更新操作導致在這個查詢條件下記錄數增多,則兩次讀取結果相同。換句話說,就是在乙個事務中第一次讀取的記錄保證不會在這個事務期間發生改變。sql server是通過在整個事務期間給讀取的記錄加鎖實現這種隔離級別的,這樣,在這個事務結束前,其他會話不能修改事務中讀取的記錄,而只能等待事務結束,但是sql server不會阻礙其他會話向表中新增記錄,也不阻礙其他會話修改其他記錄。
serializable:在乙個事務中,讀取操作的結果是在這個事務開始之前其他事務就已經提交的記錄,sql server通過在整個事務期間給表加鎖實現這種隔離級別。在這種隔離級別下,對這個表的所有dml操作都是不允許的,即要等待事務結束,這樣就保證了在乙個事務中的兩次讀取操作的結果肯定是相同的。
2.oracle中的隔離級別及實現機制
在oracle中,沒有read uncommitted及repeatable read隔離級別,這樣在oracle中不允許乙個會話讀取其他事務未提交的資料修改結果,從而避免了由於事務回滾發生的讀取錯誤。oracle中的read committed和serializable級別,其含義與sql server類似,但是實現方式卻大不一樣。
在oracle中,存在所謂的回滾段(oracle9i之前版本)或撤銷段(oracle9i版本),oracle在修改資料記錄時,會把這些記錄被修改之前的結果存入回滾段或撤銷段中,就是因為這種機制,oracle對於事務隔離級別的實現與sql server截然不同。在oracle中,讀取操作不會阻礙更新操作,更新操作也不會阻礙讀取操作,這樣在oracle中的各種隔離級別下,讀取操作都不會等待更新事務結束,更新操作也不會因為另乙個事務中的讀取操作而發生等待,這也是oracle事務處理的乙個優勢所在。
oracle預設的設定是read committed隔離級別(也稱為語句級別的隔離),在這種隔離級別下,如果乙個事務正在對某個表進行dml操作,而這時另外乙個會話對這個表的記錄進行讀取操作,則oracle會去讀取回滾段或撤銷段中存放的更新之前的記錄,而不會象sql server一樣等待更新事務的結束。
在serializable隔離級別(也稱為事務級別的隔離),事務中的讀取操作只能讀取這個事務開始之前已經提交的資料結果。如果在讀取時,其他事務正在對記錄進行修改,則oracle就會在回滾段或撤銷段中去尋找對應的原來未經更改的記錄(而且是在讀取操作所在的事務開始之前存放於回滾段或撤銷段的記錄),這時讀取操作也不會因為相應記錄被更新而等待。
四.ddl語句對事務的影響
1.oracle中ddl語句對事務的影響
在oracle中,執行ddl語句(如create table、create view等)時,會在執行之前自動發出乙個commit命令,並在隨後發出乙個commit或者rollback命令,也就是說,ddl會象如下偽碼一樣執行:
commit;
ddl_statement;
if(error)then
rollback;
else
commit;
endif;
我們通過分析下面例子來看oracle中,ddl語句對事務的影響:
insertintosome_tablevalues(『before』);
creaatetablet(xint);
insertintosome_tablevalues(『after』);
rollback;
由於在oracle執行create table語句之前進行了提交,而在create table執行後也會自動發出commit命令,所以只有插入after的行被回滾,而插入before的行不會被回滾,create table命令的結果也不會被回滾,即使create table語句失敗,所進行的before插入也會被提交。如果最後發出commit命令,因為插入before及create table的操作結果已經在之前提交,所以commit命令影響的只有插入after的操作。
2.sql server中ddl語句對事務的影響
在sql server中,ddl語句對事務的影響與其他dml語句相同,也就是說,在dml語句發出之前或之後,都不會自動發出commit命令。
在sql server 2000中,對於與上面oracle同樣的例子,最後發出rollback後,資料庫會回滾到插入before之前的狀態,即插入before和after的行都會被回滾,資料表t也不會被建立。
如果最後發出commit操作,則會把三個操作的結果全部提交。
五.使用者斷開資料庫連線對事務的影響
另外,對應於oracle的管理客戶端工具sql*plus,在sql server 2000中是osql,兩種管理工具都是命令列工具,使用方式及作用也類似,但是在sql*plus中,使用者退出連線時,會自動先發出commit命令,然後再退出,而在osql中,如果使用者退出連線,會自動發出rollback命令,這對於sql server的自動提交模式沒有什麼影響,但如果處於隱式事務模式,其影響是顯而易見的。對於兩種資料庫產品的其他客戶端管理工具也有類似的不同之處。
spring中唯讀事務的概念
唯讀事務 並不是乙個強制選項,它只是乙個 暗示 提示資料庫驅動程式和資料庫系統,這個事務並不包含更改資料的操作,那麼jdbc驅動程式和資料庫就有可能根據這種情況對該事務進行一些特定的優化,比方說不安排相應的資料庫鎖,以減輕事務對資料庫的壓力,畢竟事務也是要消耗資料庫的資源的。但是你非要在 唯讀事務 ...
Spring學習筆記 六 事務概念
spring學習筆記 六 事務概念 事務事務管理器 mybatis事務的處理 spring統一管理事務,將不同的資料庫訪問技術的事務處理統一起來,開發只需掌握spring的事務處理方案就可以實現不同的資料庫訪問技術,spring使用事務管理器處理 spring事務管理器 spring事務管理使用環繞...
Spring事務(一) Spring事務的使用
事務的經典舉例 某人要在商店使用電子貨幣購買100元的東西,當中至少包括兩個操作 該人賬戶減少100元 商店賬戶增加100元 事務就是要確保以上兩個操作 都能完成 或者 一起取消,否則就會出現100元平白消失或出現的情況。摘自wiki spring事務有兩種方式 程式設計式事務管理 宣告式事務管理 ...