MySQL 事務 例外 事務隔離的級別
事務
在你操作資料庫的同時,有可能其他用戶還會不斷地對資料進行增刪改查操作,為了避免并行進行時出現混亂,就產生了“事務”,事務就是要保證一組資料庫操作,要么全部成功要么全部失敗,以此來保證不混亂,
事務支持是在引擎層實作的,MySQL支持多系統,不是所有引擎都支持事務,

事務的特性(ACID)
- Atomicity(原子性):原子即不可分割,即事務是進行資料處理的基本單位
- Consistency(一致性):事務使資料庫從一種狀態到另一種狀態,且資料庫的約束性不被破壞
- Isolation(隔離性):指事務之間保持獨立性,不被其他事務影響的特性,分為四個隔離等級
- Durability(持久性):事務提交后對資料庫的修改時“持久的”,持久性是用過日志來實作的(回滾日志+重做日志),即使發生故障,資料修改依然有效,因為當事務完成,日志就會被更新,我們依然可以恢復到最后一次成功提交事務時的狀態,
原子性是基礎,一致性是約束,隔離性是手段,持久性是目的,
事務操作方式
Mysql默認引數autocommit = 1,compelation = 0
autocommit = 1:每條SQL都自動提交
autocommit = 0:不論是否使用START TRANSACTON或BEGIN,總要使用commit才能提交,有些客戶端框架會默認連接后先執行set autocommit = 0的命令,這就容易造成長連接,從而造成長事務,
盡量不要長事務,詳見"可重復讀的實作"
compelation = 0:執行commit僅提交事務
compelation = 1:commit時相當于commit and chain,開啟鏈式事務,提交事務后開啟一個相同的事務
compelation = 2: commit時相當于commit and release,提交后會自動斷開服務器連接
在MySQL默認的設定下
-
使用
START TRANSACTION或BEGIN顯式開啟一個事務,然后再用COMMIT提交 -
使用
ROLLBACK進行回滾,或者回滾到ROLLBACK TO [SAVEPOINT],例如,在一個事務中為有唯一約束(包含主鍵)的欄位插入了 多條有相同值的該欄位記錄, 那么,在mysql默認情況下就會產生錯誤,再執行ROLLBACK后就會只有未插入前的資料,如下列代碼,執行后前后查詢結果一致,SELECT * FROM t; ... BEGIN; INSERT INTO t id VALUES 1; INSERT INTO t id VALUES 1; ROLLBACK; SELECT * FROM t;需要注意的是,插入錯誤后只有手動
ROLLBACK后才會執行后前后查詢結果一致,不執行ROLLBACK的結果是后面的查詢結果會比前面多一條id為1的記錄, -
連續的
BEGIN這時資料庫會隱式地提交第一個BEGIN事務并進入第二個事務 -
而
ROLLBACK是僅針對當前事務的,比如連續進行了兩個BEGIN事務,在第二個事務中進行ROLLBACK,資料庫僅能回滾到第一個事務提交后的狀態
三種例外
- 臟讀:事務并行進行時,事務A讀到了事務B中新增但未提交的內容,讀到了其他事務回滾前的臟資料,
- 不可重復讀:事務并行進行,事務A對表進行查詢時事務B對表某行進行修改,導致事務A發現兩次讀取時的結果不同,
- 幻讀:事務并行進行,事務A進行查詢時事務B對表新增資料,導致事務A兩次讀取時讀到更多的資料,
用于解決例外的四個事務隔離級別
隔離得越嚴實,效率就會越低,我們需要在生產中尋找一個平衡點,按業務決定,
對于隔離級別從低到高分別是
-
讀未提交(READ UNCOMMIT) --- 允許讀到未提交的資料 --- 不使用鎖,無法避免三種例外
-
讀已提交(READ COMMIT) --- 只能讀到已提交的資料 --- 其本身可避免臟讀(也是Oracle和SQL
Server默認的隔離級別) --- 可以撰寫帶鎖的SQL陳述句來避免“不可重復讀”和“幻讀”
-
可重復讀(REPEATABLE READ) --- 事務在執行期間看到的資料必須前后一致 --- 避免 “臟讀”和“不可重復讀” (是MySQL默認的隔離級別)
-
可串行化(SERIALIZABLE)--- 將所有事務串行化,是最高隔離等級,可以避免所有例外,但是犧牲了并發性
隔離級別效用說明例題:

- 讀未提交:V1=2 V2=2 V3=2
- 讀已提交:V1=1 V2=2 V3=2
- 可重復讀:V1=1 V2=1 V3=2 (事務在執行期間看到的資料必須一致)
- 可串行化:V1=2 V2=2 V3=2 (串行化時B在執行“將1改為2”時會被鎖住,直到事務A被提交)
查詢mysql當前的隔離等級
mysql> show variables like 'transaction_isolation';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.02 sec)
“可重復讀”的實作
-
隔離的實作主要有
讀寫鎖和多版本并發處理(MVCC)兩種方式,(因為讀寫鎖降低了事務并發效率,為了讓讀寫之間也不沖突,就發明了MVCC) -
事務隔離的實作拓展閱讀見此處,有一定了解后再整理自己的版本
-
下面簡單介紹MVCC利用ReadView(快照)實作可重復讀
-
MySQL中每條記錄在更新的時候都會同時記錄一潭訓滾日志
在將1依次改為2,3,4的程序中,回滾日志有如下記錄
ReadView_A:將2改為1
ReadView_B:將3改為2
ReadView_C:將4改為3
而當前:
值為4
這就讓同一條記錄在系統中可以有多個版本,這就是MVCC,此時如果有"將4改為5"的事務,它并不會影響回滾日志中的A、B、C,
-
盡量不要使用
長事務:長事務意味著有很多舊的ReadView(影響回滾空間,5.5之前甚至有可能回滾空間大于真實資料),這會導致占用大量的存盤空間,而且長事務還會占用鎖資源,有可能拖垮整個庫, -
洗掉回滾日志:默認情況下,系統會自行判斷,當沒有事務需要用到這些回滾日志時就會被洗掉,在上述例子中,如果修改為4之后就commit(相當短的事務),即會造成“沒有事務需要用到這些回滾日志”,上述回滾日志就會被洗掉,
也就是說
事務未提交前可以回滾,提交后回滾日志會被洗掉(5.7實驗通過)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/19733.html
標籤:MySQL
上一篇:MySQL的事務隔離級別
