事務 事務是作為單個邏輯工作單元執行的一系列操作。一個邏輯工作單元必須有四個屬性,稱為原子性、一致性、隔離性和持久性 (ACID) 屬性,只有這樣才能成為一個事務。 事務併發 資料庫是多個用戶(事務)共用的,當多個用戶同時訪問數據時,那麼在這種情況下就叫做併發。 事務併發下可能出現的問題 更新丟失 ...
事務
事務是作為單個邏輯工作單元執行的一系列操作。一個邏輯工作單元必須有四個屬性,稱為原子性、一致性、隔離性和持久性 (ACID) 屬性,只有這樣才能成為一個事務。
事務併發
資料庫是多個用戶(事務)共用的,當多個用戶同時訪問數據時,那麼在這種情況下就叫做併發。
事務併發下可能出現的問題
更新丟失
兩個事務都同時更新一行數據,一個事務對數據的更新把另一個事務對數據的更新覆蓋了。這是因為系統沒有執行任何的鎖操作,因此併發事務並沒有被隔離開來。
臟讀
一個事務讀取到了另一個事務未提交的數據操作結果。這是相當危險的,因為很可能所有的操作都被回滾。
不可重覆讀
一個事務對同一行數據重覆讀取兩次,但是卻得到了不同的結果。
幻讀
幻讀發生在當兩個完全相同的查詢執行時,第二次查詢所返回的結果集跟第一個查詢不相同。
事務的隔離級別
讀未提交
當前事務可以讀取另一個事務未提交的記錄,非常危險,因為另一個事務可能完全回滾!
讀已提交
保證一個事務修改的數據提交後才能被另外一個事務讀取。
可重覆讀
這種事務隔離級別可以防止臟讀,不可重覆讀。但是可能出現幻讀!
序列化
事務被處理為順序執行。除了防止臟讀,不可重覆讀外,還避免了幻像讀。
LBCC-隔離級別
讀未提交
不加任何鎖
讀已提交
讀數據加共用鎖
更改數據加排他鎖
共用鎖讀完立即釋放
可重覆讀
讀數據加共用鎖
更改數據加排他鎖
共用鎖事務結束才釋放
序列化
讀數據加共用鎖
更改數據加排他鎖
共用鎖事務結束才釋放
增加範圍鎖
什麼鬼?可重覆讀和讀已提交兩種隔離級別得出的結論跟LBCC協議不一致!!!懷疑人生中……
MVCC協議
MVCC–多版本併發控制協議
通過保存數據在某個時間點的快照來實現,也就是說,不管需要執行多長時間,每個事務看到的數據都是一致的。不同的存儲引擎MVCC的實現是不同的,典型的有樂觀併發控制和悲觀併發控制。
MVCC實現原理(Innodb引擎)
Innodb引擎會為每一行添加兩個隱藏的列來實現的,分別表示該行創建版本和刪除版本,創建版本是事務的版本號,每開始一個新的事務,版本號會自動遞增。
舉個慄子,偷幾張圖...
初始化數據
事務1
事務2
讀已提交
讀事務每次都讀取undo log中最近的版本,因此兩次對同一欄位的讀可能讀到不同的數據(幻讀),但能保證每次都讀到最新的數據
可重覆讀
每次都讀取指定的版本,這樣保證不會產生幻讀,但可能讀不到最新的數據
總結
-
對於許多SQL,隔離級別越高,InnoDB給記錄集加的鎖就越嚴格,產生鎖衝突的可能性就越高,從而對併發事務處理性的影響也就越大。
-
因此我們在項目中,應該儘量使用較低的隔離級別,以減少鎖爭用的幾率。
- InnoDB引擎儘量使用索引,防止鎖表。
- 合理使用事務的大小,小事務發生鎖衝突的幾率也更小。
- 儘量使用相等條件,避免Next-key鎖對併發插入的影響(gap鎖)
參考
- 高性能Mysql
- 深入淺出Mysql