1. 程式人生 > >[Java]Spring資料庫事務基礎知識

[Java]Spring資料庫事務基礎知識

Spring雖然提供了靈活方便的事務管理功能,但這些功能都是基於底層資料庫本身的事務處理機制工作的。要深入瞭解Spring的事務管理和配置,有必要先對資料庫事務的基礎知識進行學習。 

何為資料庫事務

“一榮俱榮,一損俱損”這句話很能體現事務的思想,很多複雜的事物要分步進行,但它們組成一個整體,要麼整體生效,要麼整體失效。這種思想反映到資料庫上,就是多個SQL語句,要麼所有執行成功,要麼所有執行失敗。 
資料庫事務有嚴格的定義,它必須同時滿足 4 個特性:原子性(Atomic)、一致性(Consistency)、隔離性(Isolation)和永續性(Durabiliy),簡稱為ACID。下面是對每個特性的說明。 


  • 原子性:表示組成一個事務的多個數據庫操作是一個不可分割的原子單元,只有所有的操作執行成功,整個事務才提交,事務中任何一個數據庫操作失敗,已經執行的任何操作都必須撤銷,讓資料庫返回到初始狀態。
  • 一致性:事務操作成功後,資料庫所處的狀態和它的業務規則是一致的,即資料不會被破壞。如從A賬戶轉賬100元到B賬戶,不管操作成功與否,A和B的存款總額是不變的。
  • 隔離性:在併發資料操作時,不同的事務擁有各自的資料空間,它們的操作不會對對方產生干擾。準確地說,並非要求做到完全無干擾,資料庫規定了多種事務隔離級別,不同隔離級別對應不同的干擾程度,隔離級別越高,資料一致性越好,但併發性越弱。
  • 永續性:一旦事務提交成功後,事務中所有的資料操作都必須被持久化到資料庫中,即使提交事務後,資料庫馬上崩潰,在資料庫重啟時,也必須能保證能夠通過某種機制恢復資料。


在這些事務特性中,資料“一致性”是最終目標,其他的特性都是為達到這個目標的措施、要求或手段。 

資料庫管理系統一般採用重執行日誌保證原子性、一致性和永續性,重執行日誌記錄了資料庫變化的每一個動作,資料庫在一個事務中執行一部分操作後發生錯誤退出,資料庫即可以根據重執行日誌撤銷已經執行的操作。此外,對於已經提交的事務,即使資料庫崩潰,在重啟資料庫時也能夠根據日誌對尚未持久化的資料進行相應的重執行操作。 

和Java程式採用物件鎖機制進行執行緒同步類似,資料庫管理系統採用資料庫鎖機制保證事務的隔離性。當多個事務試圖對相同的資料進行操作時,只有持有鎖的事務才能操作資料,直到前一個事務完成後,後面的事務才有機會對資料進行操作。Oracle資料庫還使用了資料版本的機制,在回滾段為資料的每個變化都儲存一個版本,使資料的更改不影響資料的讀取。 


資料併發的問題

一個數據庫可能擁有多個訪問客戶端,這些客戶端都可以併發方式訪問資料庫。資料庫中的相同資料可能同時被多個事務訪問,如果沒有采取必要的隔離措施,就會導致各種併發問題,破壞資料的完整性。這些問題可以歸結為5類,包括3類資料讀問題(髒讀、不可重複讀和幻象讀)以及2類資料更新問題(第一類丟失更新和第二類丟失更新)。下面,我們分別通過例項講解引發問題的場景。 

髒讀(dirty read)

A事務讀取B事務尚未提交的更改資料,並在這個資料的基礎上操作。如果恰巧B事務回滾,那麼A事務讀到的資料根本是不被承認的。來看取款事務和轉賬事務併發時引發的髒讀場景: 



在這個場景中,B希望取款500元而後又撤銷了動作,而A往相同的賬戶中轉賬100元,就因為A事務讀取了B事務尚未提交的資料,因而造成賬戶白白丟失了500元。在Oracle資料庫中,不會發生髒讀的情況。 

引用一個有結巴的人在飲料店櫃檯前轉悠,老闆很熱情地迎上來說:“喝一瓶?”結巴連忙說:“我…喝…喝…”老闆麻利地開啟易拉罐遞給結巴,結巴終於憋出了他的那句話:“我…喝…喝…喝不起啊!”

不可重複讀(unrepeatable read)

不可重複讀是指A事務讀取了B事務已經提交的更改資料。假設A在取款事務的過程中,B往該賬戶轉賬100元,A兩次讀取賬戶的餘額發生不一致: 



在同一事務中,T4時間點和T7時間點讀取賬戶存款餘額不一樣。 

幻象讀(phantom read)

A事務讀取B事務提交的新增資料,這時A事務將出現幻象讀的問題。幻象讀一般發生在計算統計資料的事務中,舉一個例子,假設銀行系統在同一個事務中,兩次統計存款賬戶的總金額,在兩次統計過程中,剛好新增了一個存款賬戶,並存入100元,這時,兩次統計的總金額將不一致: 



如果新增資料剛好滿足事務的查詢條件,這個新資料就進入了事務的視野,因而產生了兩個統計不一致的情況。 

幻象讀和不可重複讀是兩個容易混淆的概念,前者是指讀到了其他已經提交事務的新增資料,而後者是指讀到了已經提交事務的更改資料(更改或刪除),為了避免這兩種情況,採取的對策是不同的,防止讀取到更改資料,只需要對操作的資料新增行級鎖,阻止操作中的資料發生變化,而防止讀取到新增資料,則往往需要新增表級鎖——將整個表鎖定,防止新增資料(Oracle使用多版本資料的方式實現)。 

第一類丟失更新

A事務撤銷時,把已經提交的B事務的更新資料覆蓋了。這種錯誤可能造成很嚴重的問題,通過下面的賬戶取款轉賬就可以看出來: 



A事務在撤銷時,“不小心”將B事務已經轉入賬戶的金額給抹去了。 

第二類丟失更新

A事務覆蓋B事務已經提交的資料,造成B事務所做操作丟失: 



上面的例子裡由於支票轉賬事務覆蓋了取款事務對存款餘額所做的更新,導致銀行最後損失了100元,相反如果轉賬事務先提交,那麼使用者賬戶將損失100元。 

資料庫鎖機制

資料併發會引發很多問題,在一些場合下有些問題是允許的,但在另外一些場合下可能卻是致命的。資料庫通過鎖的機制解決併發訪問的問題,雖然不同的資料庫在實現細節上存在差別,但原理基本上是一樣的。 

按鎖定的物件的不同,一般可以分為表鎖定和行鎖定,前者對整個表進行鎖定,而後者對錶中特定行進行鎖定。從併發事務鎖定的關係上看,可以分為共享鎖定和獨佔鎖定。共享鎖定會防止獨佔鎖定,但允許其他的共享鎖定。而獨佔鎖定既防止其他的獨佔鎖定,也防止其他的共享鎖定。為了更改資料,資料庫必須在進行更改的行上施加行獨佔鎖定,INSERT、UPDATE、DELETE和SELECT FOR UPDATE語句都會隱式採用必要的行鎖定。下面我們介紹一下Oracle資料庫常用的5種鎖定。 

  • 行共享鎖定:一般通過SELECT FOR UPDATE語句隱式獲得行共享鎖定,在Oracle中使用者也可以通過LOCK TABLE IN ROW SHARE MODE語句顯式獲得行共享鎖定。行共享鎖定並不防止對資料行進行更改的操作,但是可以防止其他會話獲取獨佔性資料表鎖定。允許進行多個併發的行共享和行獨佔性鎖定,還允許進行資料表的共享或者採用共享行獨佔鎖定。
  • 行獨佔鎖定:通過一條INSERT、UPDATE或DELETE語句隱式獲取,或者通過一條LOCK TABLE IN ROW EXCLUSIVE MODE語句顯式獲取。這個鎖定可以防止其他會話獲取一個共享鎖定、共享行獨佔鎖定或獨佔鎖定。
  • 表共享鎖定:通過LOCK TABLE IN SHARE MODE語句顯式獲得。這種鎖定可以防止其他會話獲取行獨佔鎖定(INSERT、UPDATE或DELETE),或者防止其他表共享行獨佔鎖定或表獨佔鎖定,它允許在表中擁有多個行共享和表共享鎖定。該鎖定可以讓會話具有對錶事務級一致性訪問,因為其他會話在使用者提交或者回溯該事務並釋放對該表的鎖定之前不能更改這個被鎖定的表。
  • 表共享行獨佔:通過LOCK TABLE IN SHARE ROW EXCLUSIVE MODE語句顯式獲得。這種鎖定可以防止其他會話獲取一個表共享、行獨佔或者表獨佔鎖定,它允許其他行共享鎖定。這種鎖定類似於表共享鎖定,只是一次只能對一個表放置一個表共享行獨佔鎖定。如果A會話擁有該鎖定,則B會話可以執行SELECT FOR UPDATE操作,但如果B會話試圖更新選擇的行,則需要等待。
  • 表獨佔:通過LOCK TABLE IN EXCLUSIVE MODE顯式獲得。這個鎖定防止其他會話對該表的任何其他鎖定。


事務隔離級別

儘管資料庫為使用者提供了鎖的DML操作方式,但直接使用鎖管理是非常麻煩的,因此資料庫為使用者提供了自動鎖機制。只要使用者指定會話的事務隔離級別,資料庫就會分析事務中的SQL語句,然後自動為事務操作的資料資源新增上適合的鎖。此外資料庫還會維護這些鎖,當一個資源上的鎖數目太多時,自動進行鎖升級以提高系統的執行效能,而這一過程對使用者來說完全是透明的。 

ANSI/ISO SQL 92標準定義了4個等級的事務隔離級別,在相同資料環境下,使用相同的輸入,執行相同的工作,根據不同的隔離級別,可以導致不同的結果。不同事務隔離級別能夠解決的資料併發問題的能力是不同的,如表9-1所示。 



事務的隔離級別和資料庫併發性是對立的,兩者此增彼長。一般來說,使用READ UNCOMMITED隔離級別的資料庫擁有最高的併發性和吞吐量,而使用SERIALIZABLE隔離級別的資料庫併發性最低。 

SQL 92定義READ UNCOMMITED主要是為了提供非阻塞讀的能力,Oracle雖然也支援READ UNCOMMITED,但它不支援髒讀,因為Oracle使用多版本機制徹底解決了在非阻塞讀時讀到髒資料的問題並保證讀的一致性,所以,Oracle的READ COMMITTED隔離級別就已經滿足了SQL 92標準的REPEATABLE READ隔離級別。 

SQL 92推薦使用REPEATABLE READ以保證資料的讀一致性,不過使用者可以根據應用的需要選擇適合的隔離等級。 

JDBC對事務支援

並不是所有的資料庫都支援事務,即使支援事務的資料庫也並非支援所有的事務隔離級別,使用者可以通過Connection#getMetaData()方法獲取DatabaseMetaData物件,並通過該物件的supportsTransactions()、supportsTransactionIsolationLevel(int level)方法檢視底層資料庫的事務支援情況。 

Connection預設情況下是自動提交的,也即每條執行的SQL都對應一個事務,為了能夠將多條SQL當成一個事務執行,必須先通過Connection#setAutoCommit(false)阻止Connection自動提交,並可通過Connection#setTransactionIsolation()設定事務的隔離級別,Connection中定義了對應SQL 92標準4個事務隔離級別的常量。通過Connection#commit()提交事務,通過Connection#rollback()回滾事務。下面是典型的JDBC事務資料操作的程式碼: 

程式碼清單9-1  JDBC事務程式碼 
Java程式碼  收藏程式碼
  1. Connection conn ;  
  2. try{  
  3.      conn = DriverManager.getConnection();//①獲取資料連線  
  4.      conn.setAutoCommit(false); //②關閉自動提交的機制  
  5.      conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); //③設定事務隔離級別  
  6.      Statement stmt = conn.createStatement();   
  7.      int rows = stmt.executeUpdate( "INSERT INTO t_topic VALUES(1,’tom’) " );  
  8.      rows = stmt.executeUpdate( "UPDATE t_user set topic_nums = topic_nums +1 "+  
  9. "WHERE user_id = 1");   
  10.      conn.commit();//④提交事務  
  11. }catch(Exception e){  
  12.      …  
  13.      conn.rollback();//⑤回滾事務  
  14. }finally{  
  15.    …  
  16. }  


在JDBC 2.0中,事務最終只能有兩個操作:提交和回滾。但是,有些應用可能需要對事務進行更多的控制,而不是簡單地提交或回滾。JDBC 3.0(JDK 1.4及以後的版本)引入了一個全新的儲存點特性,Savepoint 介面允許使用者將事務分割為多個階段,使用者可以指定回滾到事務的特定儲存點,而並非像JDBC 2.0一樣只回滾到開始事務的點,如圖9-1所示。 



下面的程式碼使用了儲存點的功能,在發生特定問題時,回滾到指定的儲存點,而非回滾整個事務,如程式碼清單9-2所示: 

程式碼清單9-2  使用儲存點的事務程式碼 
Java程式碼  收藏程式碼
  1. …  
  2. Statement stmt = conn.createStatement();   
  3. int rows = stmt.executeUpdate( "INSERT INTO t_topic VALUES(1,’tom’)");  
  4. Savepoint svpt = conn.setSavepoint("savePoint1");//①設定一個儲存點  
  5. rows = stmt.executeUpdate( "UPDATE t_user set topic_nums = topic_nums +1 "+  
  6.           "WHERE user_id = 1");   
  7. …  
  8. //②回滾到①處的savePoint1,①之前的SQL操作,在整個事務提交後依然提交,  
  9. //但①到②之間的SQL操作被撤銷了  
  10. conn.rollback(svpt);   
  11. …  
  12. conn.commit();//③提交事務  


並非所有資料庫都支援儲存點功能,使用者可以通過DatabaseMetaData#supportsSavepoints()方法檢視是否支援。 

相關推薦

[Java]Spring資料庫事務基礎知識

Spring雖然提供了靈活方便的事務管理功能,但這些功能都是基於底層資料庫本身的事務處理機制工作的。要深入瞭解Spring的事務管理和配置,有必要先對資料庫事務的基礎知識進行學習。 何為資料庫事務“一榮俱榮,一損俱損”這句話很能體現事務的思想,很多複雜的事物要分步進行,但它們

JDBC(1)JAVA連線資料庫基礎知識學習

java連線資料庫 載入驅動類 匯入jar(jar中都是class) 專案名右鍵 屬性中新增JavaBuildPath 應該把資料庫的連線和資源的關閉包裝 把針對表的操作進行包裝。DAO 一張表會和一個類進行對應 列會對應屬性 一條記錄對應物件 java

Spring事務管理和資料庫事務相關知識

1 初步理解        理解事務之前,先講一個你日常生活中最常乾的事:取錢。         比如你去ATM機取1000塊錢,大體有兩個步驟:首先輸入密碼金額,銀行卡扣掉1000元錢;然後ATM出1000元錢。這兩個步驟必須是要麼都執行要麼都不執行。如果銀行卡扣除了1

java相關面試的基礎知識

111、3.4位double類型 ,float = 3.4是不對的,double位雙精度,8個字節64位,float位4個字節單精度32位,這樣向窄出轉換會使精度損失,正確寫成float = 3.4f int 為32位,Long位64位,Short為16位 Long a = 1L; Short b =12、M

數據庫事務基礎知識

事務數據庫事務的四個特性 原子性(Atomic)、一致性(Consistency)、隔離性(Isolation)、持久性(Durabiliy),簡稱 ACID 數據並發的問題 臟讀、不可重復讀、幻象讀、第一類丟失更新、第二類丟失更新 臟讀: 事務 A 讀取了事務 B 未提及的數據 不可重復讀: 事務 A 讀

》》HTTP 方法:GET 對比 POST《《Java:SpringMVC:基礎知識:Http協議()

ipa .com 常用 code 有關 strong 註意 part html_ http://www.w3school.com.cn/tags/html_ref_httpmethods.asp 兩種最常用的 HTTP 方法是:GET 和 POST。 —————————

SQL與NoSQL資料庫入門基礎知識詳解

SQL與NoSQL資料庫入門基礎知識詳解 這幾年的大資料熱潮帶動了一激活了一大批hadoop學習愛好者。有自學hadoop的,有報名培訓班學習的。所有接觸過hadoop的人都知道,單獨搭建hadoop裡每個組建都需要執行環境、修改配置檔案測試等過程。對於我們這些入門級新手來說簡直每個都是坑。

Java異常處理的基礎知識

try clas 所有 code exc try語句 對象 異常類 程序 Java中的異常捕獲語句 Try{ //可能發生運行錯誤的代碼; } catch(異常類型 異常對象引用){

JAVA筆記一:基礎知識

基礎知識 一、註釋 1. // 2. /* */ 3. /** XXXX自動生成文件 */ 二、JAVA資料型別 型別 儲存需求(Byte) 取值範圍 int

深入Spring資料庫事務管理

一、Spring資料庫事務管理器的設計 在Spring中資料庫事務是通過PlatformTransactionManager進行管理的,而真正能夠支援事務的是org.springframework.transaction.support.TransactionTemplate模版,其核心

java常用資料結構基礎知識總結(二)

     在上一篇中,和大家交流了java常用資料結構的基礎知識。現在與大家分享各類資料結構的遍歷問題、轉換問題。 一、遍歷問題 (1) List的遍歷問題(以ArrayList為例) ①通過迭代器遍歷     public static void traverseArr

Spring資料庫事務管理

一.配置事務管理器 1.1.xml事務名稱空間 xmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/tx http://www.springf

Java核心技術 卷 基礎知識 原書第9版》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)

技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的

Java傳統IO / NIO基礎知識

1.IO的基本操作 只執行緒情況下只能有一個客戶端的連線 package xss.netty.basicio; import java.io.IOException; import java.io.InputStream; import java.net.ServerS

4面經---java 內附 計算機基礎知識連結(知識點概括)

1.應該從哪方面準備 就筆試而言,選擇題應該從資料結構,*作系統,基礎演算法,網路這四個方面準備。程式設計題應該側重動態規劃和回溯。 就面試而言,javaweb和Java原始碼、和jvm是基礎的,如果面試非阿里系的,準備這些足夠,但是要是面試阿里或者美團,就要學學中介

java入門之計算機基礎知識

什麼是計算機?計算機在生活中的應用舉例  計算機(Computer)全稱:電子計算機,俗稱電腦。是一種能夠按照程式執行,自動、高速處理海量資料的現代化智慧電子裝置。由硬體和軟體所組成,沒有安裝任何軟體的計算機稱為裸機。常見的形式有臺式計算機、筆記本計算機、大型計算機等。 應

[資料庫] MySQL基礎知識之日期判斷及新增排序序號

這篇文章主要記錄MySQL中遇到的幾個基礎問題,希望文章對你有所幫助!包括:         1.日期型別的判斷         2.decode函式的替代方法         3.查詢語句中新增一個

資料庫基礎知識要點

不論做機器學習,還是後臺開發,都需要了解資料庫的基本知識,這一篇blog主要是總結資料庫的一些基本概念。並不是為了講解,重點就是總結梳理。 資料庫主要是面向業務邏輯的,所以為了滿足前端業務對資料的需求,資料庫管理系統負責完成資料的定義、阻止、儲存、管理、操作、

[Java面試三]JavaWeb基礎知識總結.

[Java面試三]JavaWeb基礎知識總結. 1.web伺服器與HTTP協議 Web伺服器 l WEB,在英語中web即表示網頁的意思,它用於表示Internet主機上供外界訪問的資源。 l Internet上供外界訪問的Web資源分為: • 靜態web資源(如html 頁面)

Oracle資料庫入門—基礎知識

                                                                                          Oracle入門—基礎知識 Oracle資料庫的主要特點 1.       支援多使用者、大事