[TOC] #### 1. MySQL 事務(wù)的四大特性 --- **MySQL 事務(wù)具有四個(gè)特性:原子性、一致性、隔離性、持久性,這四個(gè)特性簡(jiǎn)稱 ACID 特性** **一、原子性(Atomicity ):一個(gè)事務(wù)是一個(gè)不可再分割的整體,要么全部成功,要么全部失敗** 事務(wù)在數(shù)據(jù)庫中就是一個(gè)基本的工作單位,事務(wù)中包含的邏輯操作(SQL 語句),只有兩種情況:成功和失敗。事務(wù)的原子性其實(shí)指的就是這個(gè)邏輯操作過程具有原子性,不會(huì)出現(xiàn)有的邏輯操作成功,有的邏輯操作失敗這種情況 **二、一致性(Consistency ):一個(gè)事務(wù)可以讓數(shù)據(jù)從一種一致狀態(tài)切換到另一種一致性狀態(tài)** 舉例說明:張三給李四轉(zhuǎn)賬 100 元,那么張三的余額應(yīng)減少 100 元,李四的余額應(yīng)增加 100 元,張三的余額減少和李四的余額增加這是兩個(gè)邏輯操作具有一致性 **三、隔離性(Isolution ):一個(gè)事務(wù)不受其他事務(wù)的影響,并且多個(gè)事務(wù)彼此隔離** 一個(gè)事務(wù)內(nèi)部的操作及使用的數(shù)據(jù),對(duì)并發(fā)的其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不會(huì)互相干擾 **四、持久性(Durability ):一個(gè)事務(wù)一旦被提交,在數(shù)據(jù)庫中的改變就是永久的,提交后就不能再回滾** 一個(gè)事務(wù)被提交后,在數(shù)據(jù)庫中的改變就是永久的,即使系統(tǒng)崩潰重新啟動(dòng)數(shù)據(jù)庫數(shù)據(jù)也不會(huì)發(fā)生改變 #### 2. MySQL 事務(wù)的并發(fā)問題 --- 上面講到了事務(wù)的隔離性,當(dāng)有多個(gè)任務(wù)時(shí),應(yīng)當(dāng)讓多個(gè)事務(wù)同時(shí)執(zhí)行,這就是事務(wù)的并發(fā)。既然事務(wù)存在并發(fā)執(zhí)行,那必然存在兩個(gè)事務(wù)操作同一個(gè)數(shù)據(jù)的沖突問題,那么我們來看一下會(huì)出現(xiàn)哪些問題 下面介紹臟讀、不可重復(fù)讀、幻讀時(shí)會(huì)涉及到事務(wù)隔離級(jí)別,可先略過。按照提示設(shè)置事務(wù)隔離級(jí)別即可,本文后面會(huì)介紹事務(wù)隔離級(jí)別。測(cè)試這幾個(gè)事務(wù)并發(fā)問題可以通過打開兩個(gè)終端窗口進(jìn)行測(cè)試 查看事務(wù)隔離級(jí)別 ``` select @@transaction_isolation; ``` **一、臟讀** ![](https://img.itqaq.com/art/content/b8518f13e4ac6a7026fccb843bcd39e0.png) 測(cè)試臟讀: 將事務(wù)隔離級(jí)別修改為讀未提交 ``` # READ-UNCOMMITTED 讀未提交 set session transaction isolation level read uncommitted; ``` 現(xiàn)在有兩個(gè)事務(wù),分別是事務(wù) A 和事務(wù) B。在事務(wù) A 中查詢一條數(shù)據(jù),查詢結(jié)果中 score 的值是 80,然后事務(wù) B 去修改這一條數(shù)據(jù),將 score 的值改為 90,但是它沒有提交,這時(shí)候事務(wù) A 去查詢這條數(shù)據(jù),發(fā)現(xiàn)數(shù)據(jù)竟然發(fā)生了變化。 臟讀: 在一個(gè)事務(wù)里面,由于其他事務(wù)修改了數(shù)據(jù)并且沒有提交,而導(dǎo)致前后兩次讀取的數(shù)據(jù)不一致的情況,這種事務(wù)并發(fā)問題稱之為 “臟讀” **二、不可重復(fù)讀** ![](https://img.itqaq.com/art/content/78dd96ba91b46c6cd2014abc2189e757.png) 測(cè)試不可重復(fù)讀: 將事務(wù)隔離級(jí)別修改為讀已提交 ``` # READ-COMMITTED 讀已提交 set session transaction isolation level read committed; ``` 同樣是兩個(gè)事務(wù),事務(wù) A 查詢一條數(shù)據(jù),事務(wù) B 修改了這條數(shù)據(jù),特別注意,這里事務(wù) B 執(zhí)行了提交,但是事務(wù) A 還沒有提交或回滾,這種事務(wù)并發(fā)問題稱為不可重復(fù)讀 不可重復(fù)讀: 一個(gè)事務(wù)讀取到其他事務(wù)已提交的數(shù)據(jù)導(dǎo)致前后兩次讀取數(shù)據(jù)不一樣的情況 **三、幻讀** ![](https://img.itqaq.com/art/content/79d65dec18ddaef56875a9b546bd0add.png) 測(cè)試可重復(fù)讀: 將事務(wù)隔離級(jí)別修改為可重復(fù)讀 ``` # REPEATABLE-READ 可重復(fù)讀(默認(rèn)的事務(wù)隔離級(jí)別) set session transaction isolation level repeatable read; ``` 幻讀: 一個(gè)事務(wù)前后兩次讀取的數(shù)據(jù)不一致,是因?yàn)槠渌聞?wù)插入數(shù)據(jù)導(dǎo)致的事務(wù)并發(fā)情況 #### 3. MySQL 事務(wù)的隔離級(jí)別 --- MySQL 事務(wù)有四種隔離級(jí)別,如下所示,表格中的 “是” 代表存在這個(gè)問題,“否” 代表沒有這個(gè)問題 | 隔離級(jí)別 | 臟讀 | 不可重復(fù)讀 | 幻讀 | | ------------ | ------------ | ------------ | ------------ | | Read uncommitted(讀未提交) | 是 | 是 | 是 | | Read committed(讀已提交) | 否 | 是 | 是 | | Repeatable read(可重復(fù)讀,默認(rèn)的隔離級(jí)別) | 否 | 否 | 是 | | Serializable(可串行化) | 否 | 否 | 否 | 查看事務(wù)隔離級(jí)別 ``` # 查看全局事務(wù)隔離級(jí)別 select @@global.tx_isolation; # 查看會(huì)話事務(wù)隔離級(jí)別(也就是當(dāng)前窗口) select @@tx_isolation; select @@transaction_isolation; ``` 設(shè)置事務(wù)隔離級(jí)別 ``` # 讀未提交 set session transaction isolation level read uncommitted; # 讀已提交 set session transaction isolation level read committed; # 可重復(fù)讀(默認(rèn)隔離級(jí)別) set session transaction isolation level repeatable read; # 可串行化 set session transaction isolation level serializable; ``` 總結(jié): MySQL 的默認(rèn)隔離級(jí)別是可重復(fù)讀,不是讀已提交 隔離性從低到高分別是:讀未提交、讀已提交、可重復(fù)讀、可串行化 并發(fā)性跟隔離性恰好相反,從低到高是:可串行化、可重復(fù)讀、讀已提交、讀未提交 這也非常好理解,隔離性越高,說明鎖的粒度越細(xì),并發(fā)性自然就會(huì)降低