簡介
本文講述ms sql server和oracle對資料庫事務處理的差異性,以及oracle如何對事務處理的實現。
什麼是事務
資料庫事務(databasetransaction)是一組資料庫操作的處理單元。事務符合acid的特性:
atomic:原子性,要麼全部要麼一無所有。all or none.
consistent:一致性,所有依賴關係以及約束一致。
isolated:分離性,不同事務不互相影響。
durable:永續性,提交事務的資料需要持久化。
為什麼要使用事務
實現事務主要有兩大功能:
1.保證資料庫的consistent(一致性狀態),保持所有依賴關係以及約束一致)。哪怕資料庫管理系統出現故障時(例如斷電),也能恢復到一致性狀態。例如乙個銀行轉帳系統,張三給李四轉3000圓rmb,張三帳號上減3000和李四帳號上加3000需要同時完成,否則系統的帳就不平了。也例如有些銷售系統的彙總表和明細表,是乙個主表和乙個從表,需要同步更新。
2.併發時分離不同事務操作。例如編輯過程中的資料不給其他事務查詢到。這也是相對的,在特效需求下可能要支援dirty read(髒讀),但不是這裡討論的範圍了。
sql server 2008 的事務型別
1.自動提交事務 autocommit transactions
這是sql server預設的事務型別,每一條單獨的sql語句(sql statement)都是單獨的乙個事務,語句執行完畢後自動提交。呼叫方不需要手工控制事務流程。
2.顯示事務 explicit transactions
呼叫方需要呼叫api或者使用t-sql的begintransaction語句來開啟事務。需要呼叫commit或者rollbacktransaction 來提交或者回滾。
3.隱式事務 implicit transactions
使用setimplicit_transactions on把事務模式變成隱式模式。呼叫方不需要執行begin transaction 語句來開啟事務。資料庫引擎執行到sql語句的時候自動開啟事務。呼叫方需要呼叫commit 或者 rollback transaction 來提交或者回滾。當資料庫引擎執行下乙個sql語句時又自動開啟乙個新事務。
oracle的事務型別
oracle的事務處理型別有點像sqlserver的隱式事務。當執行到第乙個可執行的sql語句時自動開啟事務,然後需要呼叫方執行commit或者rollback來提交或者回滾事務,如果有ddl語句,oracle也會自動提交事務的。
參考:transactionmanagement
oracle的事務的實現
oracle的結構分邏輯上和物理上的區別。邏輯上的結構是表空間,而物理上的結構是資料檔案。
邏輯實現
oracle下實現事務在邏輯上是由undotablespace來實現的。undo tablespace包含undo segements(段),而undo segements包含undodata。undo data是支援事務的邏輯單元。
圖源自於《oracledatabase10g: administration workshop i》
undo data用於儲存修改前後的資料,以支援回滾,長時間查詢,和flashback查詢,以及失敗事務恢復的功能。
由於有了undo data,回滾事務變得容易了,因為undo data儲存了修改前後的資料,保證了事務的原子性。失敗事務恢復和事務回滾類似,當網路中斷或者其他原因導致事務異常停止,資料庫引擎可以恢復到一致性狀態。
同時undo data也支援長時間查詢(read-consistent),例如有**t,主鍵為key,有字段為f1,資料如下,儘管只有4條資料,假設需要很長時間進行查詢。
事務一開始查詢,一直沒結束,而事務二開始修改key為1的資料為z,事務二進行提交,資料變成下面的**。但是事務一查詢結束的時候還是讀出a,b,c,d,因為查詢是從undo中讀出快照。
flashback查詢是oracle 10g引進的功能,可以查詢出提交之後修改之前的資料,例如上面例子事務三在事務二提交後想查詢出a,b,c,d可以通過flashback查詢來完成。這也是有undodata來支援的。
物理實現
從上面的邏輯實現看,只是知道了事務以及undo data的作用,還不清楚oracle對事務的支援到底怎麼實現的。下面從物理結構上講述oracle怎麼對事務進行支援。請先看乙個物理結構圖。
為了簡化,我只是用個人的語言講述和事務有關的部件。sga可以理解為全域性記憶體。其中database buffer cache存放的是從資料檔案中讀取的資料快取。紫色的圓柱體為資料檔案。redo log buffer為重做日誌快取,也就是儲存日誌的記憶體塊,一切的資料的修改都會記錄在redo log buffer裡面。例如用回事務二更新key為1資料的例子。當事務二更新key為1資料從a到z。oracle資料庫引擎會把key為1的資料的 rowid,修改前資料a以及修改後資料z都記錄在redo log buffer裡面。如果事務二繼續更新key為2的資料為y,那麼key為2的資料的rowid,修改前資料b以及修改後資料y也記錄到redo log buffer裡面。每一筆資料都記錄,而且是流水線性記錄。一旦事務二進行提交,lgwr程序(log writer,日誌寫程序)就會把redo log buffer的資料按順序寫到log datafile裡面,也就是日誌資料檔案裡面,當寫日誌檔案完成,oracle資料庫引擎會生成乙個scn(system change number,系統更新號),到這時候oracle資料庫引擎會通知呼叫方提交完成了。這裡可以看到oracle在提交的時候不必要把更新資料寫回資料檔案,而是寫到日誌檔案裡面。因為順序寫線性的日誌檔案速度快很多,而寫資料檔案是需要隨機讀寫。由於線性記錄和scn號控制,資料庫引擎可以通過redo log(重做日誌檔案)的操作得到最新的資料。當然在checkpoint的時候資料檔案是最終還是會更新的,只是說事務提交的時候更新資料檔案不是必須步驟,這樣能很大的提高效能。
由於這個機制,回滾變得很簡單,要讀沒提交前之前的scn是很容易的事情。
對於初學者關於資料庫事務處理的建議
我自己也是從新手一步步走過來,現在也不是老鳥,算是有點經驗,如果是剛入門的同學,你覺得有用就看一下,沒用就過了。
對於資料庫事務的處理,開始的時候不需要很深入了解資料庫的原理,當然以後還是需要了解的,優先順序排後而已。高優先順序如下:
首先,事務不是什麼高深神秘的東西,我從入行開始所做的所有系統,包括現在的嵌入式系統,都用到事務。我並不覺得大部分系統事務有什麼問題,只是一些約束和同步機制,真的有問題從自身系統設計角度看,不一定說從資料庫技術角度去找解決方法。例如oracle的長時間查詢如果undo data(歷史資料)給覆蓋了,oracle會丟擲異常"ora-01555: snapshot too old」,如果出現這種問題,我會從自身系統設計角度入手,為什麼有那麼大的查詢,為什麼在這個查詢中其他事務會更新資料,這些查詢是否只是查一次就夠了,查的過程是否需要鎖住表等等。然而這個問題可以通過資料庫調優解決,但是我想問題的角度首先是從自身系統設計出發。
第二,要知道的是不同資料庫的事務型別的區別,例如ms sql sever是預設是自動提交事務,用的時候需要知道每個語句都有單獨的事務在操作。而oracle是類似於隱式事務,必須手工commit或者rollback。
第三,使用事務要知道一一對應,特別是巢狀事務的時候,有始有終。很多問題時候發生終的時候,注意異常處理需要結束已經開啟的事務。
第一點是心理問題,第二三點是技術問題,做好我覺得就可以入門開發系統了。以後碰到問題在一步步深入。
對資料庫與SQL的認知
1.什麼是資料庫 資料庫 database,儲存資料的倉庫。資料庫 高效的儲存和處理資料的介質 介質主要是兩種 磁碟和記憶體 ram 2.資料庫的分類 資料庫基於儲存介質的不同,進行了分類。分為兩類 關係型資料庫 sql 和非關係型資料庫 nosql not only sql不是關係型的資料庫都叫做...
oracle 對資料庫事務的理解
事務控制命令只與dml命令 insert update delete配合使用,比如我們不會在建立表之後使用commit語句,因為當表被建立後,它會自動被提交給資料庫。也不能使用rollback語句來恢復被撤銷的表。此外,還有其他類似的語句,也不能被撤銷,例如truncate語句。所以,在執行新的命令...
Oracle資料庫SQL總結
1oracle時間段的查詢 1.1 場景 根據使用者輸入的時間段過濾出相應記錄。1.2 解決辦法 第一種寫法 sql select from t xjxx xjgl where createdate to date 2011 6 13 yyyy mm dd and createdate to dat...