1. 程式人生 > 其它 >關於事務的四個特性、事務的隔離級別、事務的併發問題

關於事務的四個特性、事務的隔離級別、事務的併發問題

關於事務的四個特性、事務的隔離級別、事務的併發問題

事務的四個特性

MySQL事務,首先要提他的四大特性(ACID),正是這些特性,才保證了資料庫事務的安全性。

  • 原子性(Atomicity)
  • 一致性(Consistent)
  • 隔離性(Isolation)
  • 永續性(Durable)

原子性

原子性是指一個事務是一個不可分割的工作單位,其中的操作要麼都做,要麼都不做;如果事務中一個sql語句執行失敗,則已執行的語句也必須回滾,資料庫退回到事務前的狀態。

一致性

一致性是指事務執行結束後,資料庫的完整性約束沒有被破壞,事務執行的前後都是合法的資料狀態。

隔離性

與原子性、永續性側重於研究事務本身不同,隔離性研究的是不同事務之間的相互影響。隔離性是指,事務內部的操作與其他事務是隔離的,併發執行的各個事務之間不能互相干擾。

永續性

永續性是指事務一旦提交,它對資料庫的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響。

事務的併發問題

  • 髒讀:事務A讀取了事務B更新的資料,然後B回滾操作,那麼A讀取到的資料是髒資料
  • 不可重複讀:事務 A 多次讀取同一資料,事務 B 在事務A多次讀取的過程中,對資料作了更新並提交,導致事務A多次讀取同一資料時,結果 不一致。
  • 幻讀:系統管理員A將資料庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。

小結不可重複讀的和幻讀

很容易混淆,不可重複讀側重於修改,幻讀側重於新增刪除。解決不可重複讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表

MySQL的事務隔離級別

  • 讀未提交(READ UNCOMMITTED)
  • 讀提交 (READ COMMITTED)
  • 可重複讀 (REPEATABLE READ)
  • 序列化 (SERIALIZABLE)

從上往下,隔離強度逐漸增強,效能逐漸變差。採用哪種隔離級別要根據系統需求權衡決定,其中,可重複讀是 MySQL 的預設級別。

MySQL 的 InnoDB 引擎才支援事務,其中可重複讀是預設的隔離級別。

Read uncommitted(未授權讀取、讀未提交)

如果一個事務已經開始寫資料,則另外一個事務則不允許同時進行寫操作,但允許其他事務讀此行資料。該隔離級別可以通過“排他寫鎖”實現。這樣就避免了更新丟失,卻可能出現髒讀。也就是說事務B讀取到了事務A未提交的資料。

Read committed(授權讀取、讀提交)

讀取資料的事務允許其他事務繼續訪問該行資料,但是未提交的寫事務將會禁止其他事務訪問該行。該隔離級別避免了髒讀,但是卻可能出現不可重複讀。事務A事先讀取了資料,事務B緊接了更新了資料,並提交了事務,而事務A再次讀取該資料時,資料已經發生了改變。

Repeatable read(可重複讀取)

可重複讀是指在一個事務內,多次讀同一資料。在這個事務還沒有結束時,另外一個事務也訪問該同一資料。那麼,在第一個事務中的兩次讀資料之間,即使第二個事務對資料進行修改,第一個事務兩次讀到的的資料是一樣的。這樣就發生了在一個事務內兩次讀到的資料是一樣的,因此稱為是可重複讀。讀取資料的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。這樣避免了不可重複讀取和髒讀,但是有時可能出現幻象讀。(讀取資料的事務)這可以通過“共享讀鎖”和“排他寫鎖”實現。

Serializable(序列化)

提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接著一個地執行,但不能併發執行。如果僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的資料不會被剛執行查詢操作的事務訪問到。序列化是最高的事務隔離級別,同時代價也花費最高,效能很低,一般很少使用,在該級別下,事務順序執行,不僅可以避免髒讀、不可重複讀,還避免了幻像讀。

悲觀鎖和樂觀鎖

雖然資料庫的隔離級別可以解決大多數問題,但是靈活度較差,為此又提出了悲觀鎖和樂觀鎖的概念。

悲觀鎖

悲觀鎖就是某事務在更新資料過程中將資料鎖定,其他任何事務都不能讀取或修改,必須修改完成後才能訪問資料(類似於Java的執行緒同步機制)。悲觀鎖的特點是具有排他性,通常依賴於資料庫的鎖機制,一般適合短事務處理。

樂觀鎖

樂觀鎖相對悲觀鎖而言,樂觀鎖假設認為資料一般情況下不會造成衝突,所以只會在資料進行提交更新的時候,才會正式對資料的衝突與否進行檢測,如果發現衝突了,則返回使用者錯誤的資訊,讓使用者決定如何去做。樂觀鎖的特點是併發性較好,事務修改資料時,其他事務仍可以修改資料。

樂觀鎖的兩種實現方式:

  1. 使用版本號:使用資料版本(Version)記錄機制實現,這是樂觀鎖最常用的一種實現方式。何謂資料版本?即為資料增加一個版本標識,一般是通過為資料庫表增加一個數字型別的 “version” 欄位來實現。當讀取資料時,將version欄位的值一同讀出,資料每更新一次,對此version值加一。當我們提交更新的時候,判斷資料庫表對應記錄的當前版本資訊與第一次取出來的version值進行比對,如果資料庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期資料。
  2. 使用時間戳: 樂觀鎖定的第二種實現方式和第一種差不多,同樣是在需要樂觀鎖控制的table中增加一個欄位,名稱無所謂,欄位型別使用時間戳(timestamp), 和上面的version類似,也是在更新提交的時候檢查當前資料庫中資料的時間戳和自己更新前取到的時間戳進行對比,如果一致則OK,否則就是版本衝突。
    說白了,樂觀鎖其實根本不是一種資料庫鎖機制,而是一種衝突檢測機制,這種衝突檢測機制是依賴軟體或應用程式實現的。那樂觀鎖為何樂觀呀,樂觀在它的併發性比悲觀鎖好,一個事務在修改資料時,其他事務仍然可以修改資料。

悲觀鎖和樂觀鎖的使用場景

悲觀鎖的優點是可以保障資料庫的資料是絕對安全的,它是依賴資料庫的鎖機制,能很好的解決資料庫訪問的併發性問題,但是缺點就是會導致資料庫訪問效能低下,所以適合短事務(也就是事務執行時間很短)的情況。你想一想,如果事務執行時間很長,那麼後面的事務就得一直排隊等待嘛。它的使用場景是對資料安全性要求非常高的場景,比如銀行系統、金融系統等。

樂觀鎖的優點是可以保障併發性比較好,也就景資料庫訪問效能可以,它是依賴軟體的衝突檢測機制實現的,但是缺點就是並沒徹底解決資料庫訪問的併發性問題,所以資料庫的資料不是絕對安全的。它的使用場景是對資料安全性要求不高而對效能要求很高的場景,比如各種資訊管理系統等。

Mysql資料庫引擎Innodb和Myisam

Innodb和Myisam的區別

1、MyISAM:預設表型別,它是基於傳統的ISAM型別,ISAM是Indexed Sequential Access Method (有索引的順序訪問方法) 的縮寫,它是儲存記錄和檔案的標準方法。不是事務安全的,而且不支援外來鍵,如果執行大量的select,insert MyISAM比較適合。

2、InnoDB:支援事務安全的引擎,支援外來鍵、行鎖、事務是他的最大特點。如果有大量的update和insert,建議使用InnoDB,特別是針對多個併發和QPS較高的情況。

  • innodb 支援事務, myisam 不支援事務
  • innodb 支援外來鍵, myisam 不支援外來鍵
  • innodb 支援行級鎖, myisam 支援表級鎖
  • myisam 儲存了表的總行數count(*), innodb沒有儲存,需要掃描全表查詢

MySQL的兩種引擎下的鎖機制

1.innodb儲存引擎:
行級鎖(也相容了表級鎖)
行級鎖又分為共享鎖和排他鎖 (另外還有意向共享鎖和意向排他鎖,儲存引擎會自動加)
執行update、insert、delete語句,引擎會自動加排它鎖
執行select,引擎是不加任何鎖的
行級鎖是基於索引欄位的,如果sql語句中沒有涉及索引則會使用表級鎖。
行級鎖記憶體開銷大,鎖定資料量小,適合高併發場景

2.myisam儲存引擎;
表級鎖。
表示鎖又分為讀鎖和寫鎖
讀鎖是共享的即其他事務可以同時讀,但不能寫。
加寫鎖時,其他事務不能讀也不能寫
表級鎖記憶體開銷小,鎖定資料量大,適合存在大量select場景

總結

  1. 資料庫的事務預設四個特性:ACID
    1. 原子性(Atomicity)
    2. 一致性(Consistent)
    3. 隔離性(Isolation)
    4. 永續性(Durable)
  2. 資料庫訪問的併發性問題(更新丟失、髒讀、不可重複讀、幻象讀)會導致的資料的一致性被破壞。
  3. 資料庫指定了4種事務的隔離級別,目的是為了解決資料庫訪問的併發性問題(更新丟失、髒讀、不可重複讀、幻象讀)導致的資料的一致性被破壞。
    1. Read uncommitted(未授權讀取、讀未提交)
    2. Read committed(授權讀取、讀提交)
    3. Repeatable read(可重複讀取) MySQL 預設隔離級別
    4. Serializable(序列化)
  4. 由於資料庫的隔離級別靈活度較差,所以又有了悲觀鎖和樂觀鎖,也是用於解決資料庫訪問的併發性問題。
    1. 悲觀鎖
    2. 樂觀鎖
  5. Innodb和Myisam兩種引擎