mysql 默认事务隔离级别_MySQL 事务隔离级别详解
簡介: MySQL的事務隔離級別一共有四個,分別是讀未提交、讀已提交、可重復讀以及可串行化。
四個特性ACID
原子性 (Atomicity)
事務開始后所有操作,要么全部做完,要么全部不做,不可能停滯在中間環節。事務執行過程中出錯,會回滾到事務開始前的狀態,所有的操作就像沒有發生一樣。例如,如果一個事務需要新增 100 條記錄,但是在新增了 10 條記錄之后就失敗了,那么數據庫將回滾對這 10 條新增的記錄。也就是說事務是一個不可分割的整體,就像化學中學過的原子,是物質構成的基本單位。
一致性 (Consistency)
指事務將數據庫從一種狀態轉變為另一種一致的的狀態。事務開始前和結束后,數據庫的完整性約束沒有被破壞。例如工號帶有唯一屬性,如果經過一個修改工號的事務后,工號變的非唯一了,則表明一致性遭到了破壞。
隔離性 (Isolation)
要求每個讀寫事務的對象對其他事務的操作對象能互相分離,即該事務提交前對其他事務不可見。 也可以理解為多個事務并發訪問時,事務之間是隔離的,一個事務不應該影響其它事務運行效果。這指的是在并發環境中,當不同的事務同時操縱相同的數據時,每個事務都有各自的完整數據空間。由并發事務所做的修改必須與任何其他并發事務所做的修改隔離。例如一個用戶在更新自己的個人信息的同時,是不能看到系統管理員也在更新該用戶的個人信息(此時更新事務還未提交)。
注:MySQL 通過鎖機制來保證事務的隔離性。
持久性 (Durability)
事務一旦提交,則其結果就是永久性的。即使發生宕機的故障,數據庫也能將數據恢復,也就是說事務完成后,事務對數據庫的所有更新將被保存到數據庫,不能回滾。這只是從事務本身的角度來保證,排除 RDBMS(關系型數據庫管理系統,例如 Oracle、MySQL 等)本身發生的故障。
注:MySQL 使用 redo log 來保證事務的持久性。
四種隔離級別
READ UNCOMMITTED(未提交讀)
一個事務還沒提交時,它做的變更就能被別的事務看到。 事務可以讀取未提交的數據,這也被稱為臟讀(Dirty Read)。
READ COMMITTED(讀提交)
一個事務提交之后,它做的變更才會被其他事務看到。 一個事務從開啟事務到提交事務之前,對其他事務都是不可見的,因此在同一個事務中的兩次相同查詢結果可能不一樣。故這種隔離級別有時候也叫不可重復讀(NONREPEATABLE READ)。
REPEATABLE READ(可重復讀)
一個事務執行過程中看到的數據,總是跟這個事務在啟動時看到的數據是一致的。 當然在可重復讀隔離級別下,未提交變更對其他事務也是不可見的。
SERIALIZABLE(可串行化)
顧名思義是對于同一行記錄,“寫”會加“寫鎖”,“讀”會加“讀鎖”。當 出現讀寫鎖沖突的時候,后訪問的事務必須等前一個事務執行完成,才能繼續執行。
幻讀
上文對臟讀,不可重復讀概念都進行了詳細介紹,還有一種現象叫做幻讀,概念如下:
幻讀是針對數據插入(INSERT)操作來說的。假設事務A對某些行的內容作了更改,但是還未提交,此時事務B插入了與事務A更改前的記錄相同的記錄行,并且在事務A提交之前先提交了,而這時,在事務A中查詢,會發現好像剛剛的更改對于某些數據未起作用,但其實是事務B剛插入進來的,讓用戶感覺很魔幻,感覺出現了幻覺,這就叫幻讀。匯總
raft-node="block" data-draft-type="table" data-size="normal" data-row-style="striped">
隔離級別臟讀不可重復讀幻讀讀未提交yesyesyes讀提交noyesyes可重復讀nonoyes可重復讀nonono舉個栗子
假設數據表 T 中只有一列,其中一行的值為 1,下面是按照時間順序執行兩個事務的行為。
mysql> create table T(c int) engine=InnoDB; insert into T(c) values(1);| 啟動事務 查詢得到值1 | 啟動事務 |
| 查詢值為1 | |
| 將1更新成2 | |
| 查詢值為V1 | |
| 提交事務B | |
| 查詢值為V2 | |
| 提交事務A | |
| 查詢值為V3 |
若隔離級別是讀未提交: 則 V1 的值就是 2。這時候事務 B 雖然還沒有提交,但是結果已經被 A 看到了。因此,V2、V3 也都是 2。
若隔離級別是讀提交: 則 V1 是 1,V2 的值是 2。事務 B 的更新在提交后才能被 A看到。所以, V3 的值也是 2。
若隔離級別是可重復讀: 則 V1、V2 是 1,V3 是 2。之所以 V2 還是 1,遵循的就是這個要求:事務在執行期間看到的數據前后必須是一致的。
若隔離級別是串行化: 則在事務 B 執行“將 1 改成 2”的時候,會被鎖住。直到事務 A 提交后,事務 B 才可以繼續執行。所以從 A 的角度看, V1、V2 值是 1,V3 的值是 2。
可以看到在不同的隔離級別下,數據庫行為是有所不同的。Oracle 數據庫的默認隔離級別其實就是“讀提交”,因此對于一些從 Oracle 遷移到 MySQL 的應用,為保證數據庫隔離級別的一致,你一定要記得將 MySQL 的隔離級別設置為“讀提交”。 配置的方式是,將啟動參數 transaction-isolation 的值設置成 READ-COMMITTED。 你可以用 show variables 來查看當前的值。
mysql> show variables like 'transaction_isolation'; +-----------------------+----------------+ | Variable_name | Value | +-----------------------+----------------+ | transaction_isolation | READ-COMMITTED | +-----------------------+----------------+總結來說,存在即合理,哪個隔離級別都有它自己的使用場景,你要根據自己的業務情況 來定。那什么時候需要“可重復讀”的場景呢?我們來看一個數據校對邏輯的案例。
假設你在管理一個個人銀行賬戶表。一個表存了每個月月底的余額,一個表存了賬單明細。這時候你要做數據校對,也就是判斷上個月的余額和當前余額的差額,是否與本月的賬單明細一致。你一定希望在校對過程中,即使有用戶發生了一筆新的交易,也不影響你的校對結果。 這時候使用“可重復讀”隔離級別就很方便。事務啟動時的視圖可以認為是靜態的,不受其他事務更新的影響。
小結
MySQL 的 InnoDB 引擎才支持事務,其中可重復讀是默認的隔離級別。 讀未提交和串行化基本上是不需要考慮的隔離級別,前者不加鎖限制,后者相當于單線程執行,效率太差。 讀提交解決了臟讀問題,行鎖解決了并發更新的問題。 本文主要介紹四種隔離級別和產生的問題,下一篇文章會深入解析隔離級別的實現原理MVCC和解決幻讀的Next-Key 鎖實現。
http://weixin.qq.com/r/gRPA2OrEK7dUra6790aT (二維碼自動識別)
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的mysql 默认事务隔离级别_MySQL 事务隔离级别详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python功能函数_Python-功能
- 下一篇: sql计算留存_SQL基础第七讲:关于用