JDBC(7)數據庫事務

免費錄播jdbc視頻

最全JDBC 視頻 https://ke.qq.com/course/280836#tuin=5740604a

事務

將一組業務作爲一個整體,所有的內容要麼全部成功,要麼全部不成功。那麼在數據庫當中 就是連續的sql執行

  1. 類似銀行取錢,要麼取出且扣款成功,要麼都不成功
  2. 或者轉賬(A賬號轉到B賬號 A扣款 B進賬都成功 要麼都失敗)

* 事務操作*
1. 開啓事務
2. 事務提交(全部成功)
3. 事務回滾(全部不成功)

事務的特性ACID(面試)

我們從上面的概念(要麼…,要麼…),就能概括出一些特性
1. 原子性:事務不可分割整體 (以前的物理中 原子不可分割 那麼應用到現在其他領域還表示這個事物不可分割)
2. 一致性:事務前後數據的一致。
3. 隔離性:事務的併發訪問 (一個用戶的事務不能被其它用戶的事務所幹擾,多個併發事務之間數據要相互隔離。)
4. 持久性:持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即使數據庫發生故障也不應該對其有任何影響。

事務的隔離性存在問題

  • 1、 髒讀(Drity Read):一個事務讀到另一個事務未提交的更新數據
    事務A修改了一個數據,但未提交,事務B讀到了事務A未提交的更新結果,如果事務A提交失敗,事務B讀到的就是髒數據。(A 往B卡種打100元 A還沒確認,這時候B卡已經讀到A卡打來的錢)

  • 2.不可重複讀(Non-repeatable read) :在一個事務中 連續讀取兩次,第二次讀取到另一個事務 已經提交update修改數據(update更新)
    比如我一個事務中 我第一次查詢自己的賬戶是100元,然後在發出第二次查詢的sql之前 有人給我轉賬了100,這時候,第二次就查詢到了轉賬後的數據了

  • 3.虛讀(幻讀)Phantom Read) :一個事務 讀取 另一個事務已經提交的插入數據 (強調的是記錄條數的改變)

事務A新增了一條記錄,事務B在事務A提交前後各執行了一次查詢操作,發現後一次比前一次多了一條記錄。幻讀僅指由於併發事務增加記錄導致的問題,這個不能像不可重複讀通過記錄加鎖解決,因爲對於新增的記錄根本無法加鎖。需要將事務串行化,才能避免幻讀(insert錄入)

除了以上的問題還有
- 丟失更新:兩個事務同事修改數據,後提交的數據覆蓋了先提交事務的結果
這裏寫圖片描述
丟失更新是兩個事務同時修改數據
這裏寫圖片描述

事務的隔離級別

數據庫爲了解決事務的隔離性問題,提供了四種4中隔離級別(不是所有數據庫都支持這四種級別)

    * 事務的隔離級別
        * 讀未提交:read uncommitted ,存在所有問題
        * 讀已提交:read committed,解決了髒讀問題,其他問題沒有解決
        * 可重複讀:repeatable read ,解決了髒讀與不可重複讀問題,其他問題沒有解決
        * 串行化:serializable,等價java同步代碼,單線程。解決所有問題 不准許兩個事務 同事操作一個目標數據 根本不存在併發,不存在併發問題


    * 數據庫默認隔離級別
        * mysql的默認值:repeatable read 
        * oracle的默認值:read committed

     * 對比
        * 性能: read uncommitted > read committed > repeatable read > serializable
        * 安全: read uncommitted < read committed < repeatable read < serializable

丟失更新如何解決

悲觀鎖 和 樂觀鎖
1.悲觀鎖: 採用數據庫內部鎖機制,在一個事務操作數據時,爲數據加鎖,另一個事務無法操作

    * 排它鎖 (寫鎖),數據庫中每張表只能添加一個排它鎖,排它鎖與其他鎖互斥 
    * 在修改數據時,自動添加排它鎖 
    * 在查詢數據時 添加排它鎖 select * from customers for update; 

這裏寫圖片描述
悲觀鎖解決丟失更新,效率問題 , 數據不能同時修改

hibernate中使用悲觀鎖 
Customer customer = (Customer) session.load(Customer.class, 1,LockMode.UPGRADE); // MySQL

2.樂觀鎖 : 與數據庫鎖無關,在數據表中爲數據添加 版本字段,每次數據修改都會導致版本號+1

hibernate 爲Customer表 添加版本字段 
    1) 在customer類 添加 private Integer version; 版本字段
    2) 在Customer.hbm.xml 定義版本字段
        <!-- 定義版本字段 -->
        <!-- name是屬性名 -->
        <version name="version"></version>

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章