1. 程式人生 > 其它 >mysql加強(7)~事務、事務併發、解決事務併發的方法

mysql加強(7)~事務、事務併發、解決事務併發的方法


一、事務Transaction(簡寫tx):

在資料庫中,事務是指一組邏輯操作不可分割的多個操作---一個事務,從一個狀態變成另外一個狀態。),無論成或敗,都作為一個整體進行工作,要麼全部執行,要麼全部不執行。


引入背景:銀行轉賬突遇斷電的bug


1、事務的ACID屬性:

① 原子性:事務是滿足原子操作單元的,要麼都執行,要麼都不執行。

② 一致性:事務必須使資料庫從一個一致性狀態變成另外一個一致性狀態。事務開始和完成,資料必須保持一致。(資料不被破壞)'資料守恆'】

③ 隔離性:事務之間有各自的空間,事務之間不被打擾。併發執行的事務之間彼此相互獨立、互相不干擾.

④ 永續性:事務一旦提交後,資料是永久性的、不可回滾。(資料的修改是永久的)

事務只是一個改變,是一些操作的集合,事務本身不具備4個特性,但是我們需要讓事務滿足ACID特性,才能稱它為一個正確的事務。

■ 在開發中,我們可以不使用外來鍵,但是必須要有事務(儲存引擎- innoDB)


■ 處理事務的兩個動作:

  • 提交 commit:當整個事務中,所有的邏輯操作都是正常執行成功。 --》提交事務

  • 回滾 rollback:當整個事務中,有一個或多個邏輯操作執行失敗。 --》回滾事務,撤銷該事務中所有的操作,恢復到最初的狀態。



2、隔離級別:

  • 事務的ACID特性中的隔離性是具有級別的哈,所以才有事務併發出現的各種情況。

  • 隔離級別越高,越能保證資料的完整性和一致性,但是對併發效能的影響也越大。

  • mysql 是使用可重複讀取(Repeatable Read), 保證了資料的讀取一致性,避免了髒讀、不可重複讀。

    • 預設情況,mysql不會出現幻讀[除非 select * from 表名 lock in share mode;]
    • mysql中鎖是基於索引機制,也不會出現第一類丟失更新(回滾丟失)
    隔離級別 髒讀 不可重複讀 幻讀
    oracle---讀已提交(只是避免了髒讀)
    mysql---可重複讀取(避免了髒讀和不可重複讀)

■ mysql中的4種隔離級別(重點看是否會出現髒讀、不可重複讀、幻讀即可)

  • ■ 這裡最嚴重的就是丟失更新問題

    【第一類丟失更新(回滾丟失)、第二類丟失更新(覆蓋丟失)】

    • 讀取未提交:會出現髒讀,還有事務A的資料仍然會因為事務B的insert/update、delete 從而出現幻讀、不可重複讀

    • 讀取已提交:未提交的寫操作的事務不允許被其他事務訪問到。避免了髒讀,但是事務A的資料,仍然會因為事務B的insert/update、delete 從而出現幻讀、不可重複讀。

    • 可重複讀取:避免了不可重複讀,但是卻有可能出現幻讀。

    • 序列化:要求事務一個接著一個進行執行,不可能併發執行。



二、事務併發

1、資料庫的事務併發問題:多個事務併發訪問/修改同一個資源

★ 跟java中的執行緒問題---併發問題差不多,都是針對同一資源,同時訪問/修改出現的問題。


事務併發可能導致的問題【例子:兩個客戶端同時對同一個銀行賬號進行操作,一個客戶端進行存取,一個客戶端進行取錢】

(1)第一類丟失更新:撤銷rollback一個事務時,把其他事務已經提交更新的資料回滾掉了

(2)第二類丟失更新:提交commit一個事務時,把其他事務已經提交更新的資料覆蓋掉了。

(3)髒讀:A事務未提交,但是B事務卻讀取到A事務的結果【讀取到了B事務未提交的結果】(破壞隔離性)

(4)幻讀:A事務在本次事務中,自己未操作過的資料B事務insert了一些資料),A事務進行兩次讀取,發現第一次讀取時,記錄不存在,第二次讀取,記錄出現了(破壞一致性,insert)

(5)不可重複讀:跟幻讀類似,A事務在本次事務中,自己未操作過的資料B事務update/delete了一些資料),A事務進行兩次讀取,發現兩次讀取的記錄值不同(破壞一致性,update/delete)


❀ 每一個事務是有自己的空間的概念

  • 【第一類丟失更新】回滾丟失,把前一個提交的事務的結果回滾到資料庫最初的數
  • 【第二類丟失更新】覆蓋丟失,通過提交事務,把前一個提交的事務的結果給覆蓋掉
  • 髒讀: 事務A讀到事務B未提交的更新資料 (Oracle不會出現髒讀)
  • 幻讀:事務A第二次查詢時,讀到了事務B新增提交的資料,即事務A兩次查詢時的記錄條數不同,"產生幻覺"。【一般使用表鎖機制,防止新增資料。】
  • 不可重複讀:跟幻讀類似(只是幻讀是讀到事務B新增資料),事務A第二次查詢時,讀到了事務B修改提交的資料,即事務A兩次查詢時的結果的值不同不同



三、解決事務併發的方法(悲觀鎖/樂觀鎖)

1、悲觀鎖:事務A在操作時,悲觀地認為其他事務會進來干擾自己。---[用的比較多,非常安全]。

(1)悲觀鎖:使用資料庫自身的排它鎖機制 [★原理資料庫自身的鎖機制(寫鎖)]

  • DML操作會自動加上排它鎖(排斥其他鎖)
  • DQL操作需要我們手動加上排它鎖
    • select * from 表名 for update;

■ 使用客戶端工具Navicat模擬(開啟兩個命令列視窗,可以拖動出來方便檢視)併發:

  • DML操作會自動加上排它鎖(排斥其他鎖)

  • DQL操作需要我們手動加上排它鎖

■ 查詢事務加上了 for update,其中一個事務處於阻塞狀態,等著另一個事務的提交或回滾。



2、樂觀鎖:事務A在操作時,樂觀地認為其他事務不會進來干擾自己。

(1) ★原理:在表中額外新增一個列,用來表示修改的版本(整型型別),修改一次就把版本增加1.

  • 舉例:事務A併發修改person表中的name欄位。

(2)樂觀鎖的操作步驟: