[TOC]
# 一、事務
## 概念
事務指的是滿足 ACID 特性的一組操作,可以通過 Commit 提交一個事務,也可以使用 Rollback 進行回滾。

## ACID
### 1. 原子性(Atomicity)
事務被視為不可分割的最小單元,事務的所有操作要么全部提交成功,要么全部失敗回滾。
回滾可以用回滾日志(Undo Log)來實現,回滾日志記錄著事務所執行的修改操作,在回滾時反向執行這些修改操作即可。
### 2.一致性(Consistency)
數據庫在事務執行前后都保持一致性狀態。在一致性狀態下,所有事務對同一個數據的讀取結果都是相同的。
### 3. 隔離性(Isolation)
一個事務所做的修改在最終提交以前,對其它事務是不可見的。
### 4. 持久性(Durability)
一旦事務提交,則其所做的修改將會永遠保存到數據庫中。即使系統發生崩潰,事務執行的結果也不能丟失。
系統發生奔潰可以用重做日志(Redo Log)進行恢復,從而實現持久性。與回滾日志記錄數據的邏輯修改不同,重做日志記錄的是數據頁的物理修改。
* * *
事務的 ACID 特性概念簡單,但不是很好理解,主要是因為這幾個特性不是一種平級關系:
* 只有滿足一致性,事務的執行結果才是正確的。
* 在無并發的情況下,事務串行執行,隔離性一定能夠滿足。此時只要能滿足原子性,就一定能滿足一致性。
* 在并發的情況下,多個事務并行執行,事務不僅要滿足原子性,還需要滿足隔離性,才能滿足一致性。
* 事務滿足持久化是為了能應對系統崩潰的情況。

## AUTOCOMMIT
MySQL 默認采用自動提交模式。也就是說,如果不顯式使用`START TRANSACTION`語句來開始一個事務,那么每個查詢操作都會被當做一個事務并自動提交。
# 二、并發一致性問題
在并發環境下,事務的隔離性很難保證,因此會出現很多并發一致性問題。
## 丟失修改
T1和 T2兩個事務都對一個數據進行修改,T1先修改,T2隨后修改,T2的修改覆蓋了 T1的修改。

## 讀臟數據
T1修改一個數據,T2隨后讀取這個數據。如果 T1撤銷了這次修改,那么 T2讀取的數據是臟數據。

## 不可重復讀
T2讀取一個數據,T1對該數據做了修改。如果 T2再次讀取這個數據,此時讀取的結果和第一次讀取的結果不同。

## 幻影讀
T1讀取某個范圍的數據,T2在這個范圍內插入新的數據,T1再次讀取這個范圍的數據,此時讀取的結果和和第一次讀取的結果不同。

產生并發不一致性問題的主要原因是破壞了事務的隔離性,解決方法是通過并發控制來保證隔離性。并發控制可以通過封鎖來實現,但是封鎖操作需要用戶自己控制,相當復雜。數據庫管理系統提供了事務的隔離級別,讓用戶以一種更輕松的方式處理并發一致性問題。
# 三、封鎖
## 封鎖粒度
MySQL 中提供了兩種封鎖粒度:行級鎖以及表級鎖。
應該盡量只鎖定需要修改的那部分數據,而不是所有的資源。鎖定的數據量越少,發生鎖爭用的可能就越小,系統的并發程度就越高。
但是加鎖需要消耗資源,鎖的各種操作(包括獲取鎖、釋放鎖、以及檢查鎖狀態)都會增加系統開銷。因此封鎖粒度越小,系統開銷就越大。
在選擇封鎖粒度時,需要在鎖開銷和并發程度之間做一個權衡。