MySQL InnoDB 事務

事務的定義sql

事務:數據庫操做的最小工做單元,是做爲單個邏輯工做單元執行的一系列操做; 事務是一組不可再分割的操做集合(工做邏輯單元)。數據庫

典型事務使用場景:轉帳編程

MySQL InnoDB 事務
MySQL 開啓事務:併發

MySQL InnoDB 事務
MySQL 默認是開啓事務的,經過 SHOW VARIABLES like 'autocommit'; 能夠查看 MySQL 的事務開啓狀況。ide

在 autocommit = ON(自動提交事務)的狀況下,能夠執行 BEGIN; 或者 START TRANSACTION; 命令,改成手動提交事務,執行完 SQL 語句後,須要經過 COMMIT 命令提交事務,或者經過 ROLLBACK 命令回滾事務。
在 autocommit = OFF(手動提交事務)的狀況下,執行完 SQL 語句後,須要經過 COMMIT 命令提交事務,或者經過 ROLLBACK命令回滾事務。
JDBC 編程:測試

MySQL InnoDB 事務
測試命令:3d

MySQL InnoDB 事務
事務 ACID 特性blog

原子性(Atomicity):最小的工做單元,整個工做單元要麼一塊兒提交成功,要麼所有失敗回滾。事務

一致性(Consistency):事務中操做的數據及狀態改變是一致的,即寫入資料的結果必須徹底符合預設的規則,不會由於出現系統意外等緣由致使狀態的不一致。ci

隔離型(Isolation):一個事務所操做的數據在提交以前,對其餘事務的可見性設定(通常設定爲不可見)。

持久性(Durability):事務所作的修改就會永久保存,不會由於系統意外致使數據的丟失。

參考(原子性和一致性的區別是什麼?)這篇博文,講了一下原子性和一致性的區別。

事務併發帶來了哪些問題

髒讀

MySQL InnoDB 事務MySQL InnoDB 事務
好比 user 表中有一條用戶數據,執行了以下操做:

事務B更新 id=1 的數據,age 更新爲18,不提交事務
事務A查詢 id=1 的數據
事務B回滾剛纔的更新操做
這個時候,事務A中查詢出的 id=1 的數據,age 的值是16仍是18?

不可重複讀

MySQL InnoDB 事務
好比 user 表中有一條用戶數據,執行了以下操做:

事務A查詢 id=1 的數據
事務B更新 id=1 的數據,age 更新爲18,並提交事務
事務A再次查詢 id=1 的數據
這個時候,事務A兩次查詢出的 id=1 的數據,age 的值是16仍是18?

幻讀

MySQL InnoDB 事務
好比在 user 表中執行了以下操做:

事務A查詢 age>15 的數據
事務B新增一條數據,age=22,並提交事務
事務A再次查詢 age>15 的數據
這個時候,事務A兩次查詢出的數據,數量是1條仍是2條?

事務四種隔離級別

SQL92 ANSI/ISO標準:http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

Read Uncommitted(未提交讀) --未解決併發問題

事務未提交對其餘事務也是可見的,髒讀(dirty read)

Read Committed(提交讀) --解決髒讀問題

一個事務開始以後,只能看到本身提交的事務所作的修改,不可重複讀(non repeatable read)

Repeatable Read(可重複讀) --解決不可重複讀問題

在同一個事務中屢次讀取一樣的數據結果是同樣的,這種隔離級別未定義解決幻讀的問題

Serializable(串行化) --解決全部問題

最高的隔離級別,經過強制事務的串行執行

InnoDB 引擎對隔離級別的支持程度

MySQL InnoDB 事務
事務隔離級別的併發能力:未提交讀 > 已提交讀 > 可重複讀 > 串行化

InnDB 引擎默認的事務隔離級別是可重複讀(Repeatable Read),在該級別中它把幻讀的問題也解決了。InnDB 中事務隔離級別經過鎖、MVCC 實現。

經過以下語句查看 InnoDB 的默認事務隔離級別:

MySQL InnoDB 事務MySQL InnoDB 事務
MySQL InnoDB 事務MySQL InnoDB 事務
經過以下語句設置 InnoDB 的事務隔離級別:

MySQL InnoDB 事務MySQL InnoDB 事務
接下來咱們來測試一下 InnoDB 的默認事務隔離級別(Repeatable Read)是否解決了髒讀、不可重複讀、幻讀的問題。

數據準備:

MySQL InnoDB 事務MySQL InnoDB 事務
是否解決了髒讀的問題?

MySQL InnoDB 事務MySQL InnoDB 事務
開啓兩個 MySQL 客戶端,模擬事務A和事務B的操做,執行步驟以下:

事務B開啓手動事務,更新 id=1 的數據,age 更新爲18,不提交事務
事務A查詢 id=1 的數據
事務B回滾剛纔的更新操做
圖中的數字是執行步驟,經過下圖能夠看出事務A的執行結果是16,InnDB 的默認事務隔離級別完美的解決了髒讀的問題。

MySQL InnoDB 事務MySQL InnoDB 事務
是否解決了不可重複讀的問題?

MySQL InnoDB 事務MySQL InnoDB 事務
開啓兩個 MySQL 客戶端,模擬事務A和事務B的操做,執行步驟以下:

事務A開啓手動事務,查詢 id=1 的數據
事務B更新 id=1 的數據,age 更新爲18,並提交事務
事務A再次查詢 id=1 的數據
圖中的數字是執行步驟,經過下圖能夠看出事務A兩次的執行結果都是16,沒有受事務B更新操做的影響,InnDB 的默認事務隔離級別完美的解決了不可重複讀的問題。

MySQL InnoDB 事務MySQL InnoDB 事務
是否解決了幻讀的問題?

MySQL InnoDB 事務MySQL InnoDB 事務
開啓兩個 MySQL 客戶端,模擬事務A和事務B的操做,執行步驟以下:

事務A開啓手動事務,查詢 age>15 的數據
事務B新增一條數據,age=22,並提交事務
事務A再次查詢 age>15 的數據
圖中的數字是執行步驟,經過下圖能夠看出事務A兩次的執行結果都是一條數據,沒有受事務B新增操做的影響,InnDB 的默認事務隔離級別完美的解決了幻讀的問題。

MySQL InnoDB 事務MySQL InnoDB 事務

相關文章
相關標籤/搜索