介紹MySQL 事務的ACID特性、隔離級別以及臟讀、不可重覆讀和幻讀等內容 ...
1. 事務的ACID
事務的ACID是指事務擁有的4個特性的首字母組合:atomicity(原子性), consistency(一致性), isolation(隔離性)和durability(持久性)。
①atomicity(原子性):表示事務是一個不可分割的工作單元,要麼在提交事務後所有更改成功,要麼在回滾事務時撤消所有更改,不可以只執行其中的一部分操作。
②consistency(一致性):在每次提交、回滾之後或正在進行的事務,資料庫始終保持一致狀態。如正在跨多個表更新相關數據,則查詢看到的將是所有舊值或所有新值,而不是新值和舊值的混合。
③isolation(隔離性):事務在進行過程中相互隔離,他們不能互相干擾,也不能看到彼此的未提交數據。但可以通過修改隔離級別,查看其他事務正在處理的數據。
④durability(持久性):事務提交成功後,該事務所做的更改將會保存在資料庫中。
2. 併發讀取數據的問題
當事務讀取另一個事務已修改的數據時,可能會發生dirty read(臟讀)、non-repeatable read(不可重覆讀)和phantom read(幻讀)之類的現象。
①dirty read(臟讀):當前事務讀取了另一個事務已更新但尚未提交的數據。後果就是另一個事務回滾了,此數據就為錯誤的無效數據。
②non-repeatable read(不可重覆讀):當前事務讀取相同數據2次的過程期間,另一個事務修改了此數據並提交,造成當前事務讀取的2次結果不一致。
③phantom read(幻讀):當前事務讀取相同數據2次的過程期間,另一個事務插入了新行或更新一行以此造成當前事務讀取的2次結果不一致。看上不可重覆讀與幻讀兩者差不多,但不可重覆讀偏向於行的修改,幻讀偏向於行的新增。
3. 隔離級別
隔離級別是一種用於在多個事務同時進行更改和執行查詢時修改事務隔離性(isolation)的設置,權衡事務的保護以提高性能和併發性。
InnoDB儲存引擎支持的隔離級別有(從低到高): READ UNCOMMITTED(未提交讀)、 READ COMMITTED(已提交讀)、REPEATABLE READ(可重覆讀) 和 SERIALIZABLE(可串列話)。
3.1 READ UNCOMMITTED(未提交讀)
說明:為最低的隔離級別,表示當前事務可以讀取其他事務已修改但未提交的數據。這個級別會導致很多問題,通常,具有此隔離級別的事務僅執行查詢,而不執行插入,更新或刪除操作。
3.2 READ COMMITTED(已提交讀)
說明:事務無法看到來自其他事務未提交的數據,簡單來講一個事務從開始直到提交前,所做的任何修改對其他事務而言是不可見的。
3.3 REPEATABLE READ(可重覆讀)
說明:InnoDB的預設隔離級別。保證了在同一個事務內多次讀取同樣的記錄的結果為一致。
3.4 SERIALIZABLE(可串列化)
說明:為最高的隔離級別,表示事務一個接一個的串列執行,訪問同一資源時,後面的事務必須等待前面的事務操作完成後才能進行操作。
4. 總結
4.1 關係
不同的隔離級別解決臟讀、不可重覆讀和幻讀的問題也不一樣,關係如下:
隔離級別 | dirty read(臟讀) | non-repeatable read(不可重覆讀) | phantom read(幻讀) |
READ UNCOMMITTED(未提交讀) | 未解決 | 未解決 | 未解決 |
READ COMMITTED(已提交讀) | 已解決 | 未解決 | 未解決 |
REPEATABLE READ(可重覆讀) | 已解決 | 已解決 | 未解決 |
SERIALIZABLE(可串列化) | 已解決 | 已解決 | 已解決 |
4.2 已提交讀與可重覆讀的區別
兩者的主要區別在於不可重覆讀的策略。
例如事務A讀取了2次行R1,在讀取2次期間事務B對行R1進行了修改,那麼:
當隔離級別為READ COMMITTED(已提交讀)時:事務A讀取2次行R1的數據不一樣。
當隔離級別為REPEATABLE READ(可重覆讀)時:事務A讀取2次行R1的數據一樣。
5. 參考資料
臟讀、不可重覆讀和幻讀:https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_read_phenomena
隔離級別:https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_isolation_level