天天看點

資料庫事務四個特性

資料庫事務需要滿足四個特性,ACID,即原子性(Atomic),一緻性(Consistency),隔離性(Isolation),持久性(Durability)。

在關系資料庫中,這些特性需要借助借助redo log、鎖、snapshot等手段來實作。

隔離性要求各事務之間互相獨立,所進行的操作不會互相影響,其用意還是保證各資料讀寫操作的一緻性

标準SQL92規範定義了四種隔離級别,以及相應要禁止的三種現象(Phenomena)。

隔離級别越高,資料一緻性的保證越強,但同時資料庫的并發能力也越差。  資料庫并發操作引起的問題(現象 ) 有:

1. 髒讀(Dirty read)。

事務A讀取了事務B中尚未送出的資料。如果事務B復原,則A讀取使用了錯誤的資料。

2. 不可重複度(Unrepeatable read)。

在事務A多次的讀取過程中,事務 B對資料進行了修改,導緻事務A多次讀取的資料不一緻。

3. 幻讀(Phantom read)。

在事務A多次讀取構成中,事務B對資料進行了新增操作,導緻事務A多次讀取的資料不一緻。幻讀和不可重複讀的差別在于,

不可重複是針對記錄的update操作,隻要在記錄上加寫鎖,就可避免;幻讀是對記錄的insert操作,

要禁止幻讀必須加上全局的寫鎖(比如在表上加寫鎖)。 另外說一下兩類丢失更新:

4. 第一類丢失更新(復原丢失,Lost update)。

在事務A期間,事務 B對資料進行了更新;在事務A撤銷之後,覆寫了事務B已經送出的資料。SQL92沒有定義這種現象,标準定義的所有隔離界别都不允許第一類丢失更新發生。

5. 第二類丢失更新(覆寫丢失, Second lost update)。

在事務A期間,事務B對資料進行了更新;在事務A送出之後,覆寫了事務B已經送出的資料。第二類丢失更新,實際上和不可重複讀是同一種問題。

SQL92定義的四種隔離級别:

1. 未送出讀(Read uncommitted)。

寫操作加寫鎖,讀操作不加鎖。禁止第一類丢失更新,但是會出現所有其他資料并發問題。

2.送出讀(Read committed)。

寫操作加寫鎖,讀操作加讀鎖。禁止第一類丢失更新和髒讀。這是大部分關系資料庫的預設 隔離級别。

3.可重複讀(Read repeatable)。

對于讀操作加讀鎖到事務結束,其他事務的更新操作隻能等到事務結束之後進行。和送出 讀的差別在于,

送出讀的讀操作是加讀鎖到本次讀操作結束,可重複讀的鎖粒度更大。禁止兩類丢失更新,禁止髒讀和不可 重複度,但是可能出現幻讀.

4.序列化(Serializable)。

讀操作加表級讀鎖至事務結束。可以禁止幻讀。

                                第一類丢失更新   不可重複讀     髒讀    第二類丢失更新     幻讀

Read uncommitted         禁止               不禁止      不禁止      不禁止         不禁止 

Read committed        禁止                禁止       不禁止      不禁止         不禁止

Read repeatable        禁止                禁止       禁止        禁止           不禁止 

Serializable        禁止                禁止       禁止       禁止             禁止

大多數關系資料庫預設使用Read committed的隔離級别,Mysql InnoDB預設使用Read repeatable的隔離級别,

這和Mysql replication 機制使用Statement日志格式有關。各資料庫隔離級别的實作也是有差别的,

例如Oracle支援Read committed 和Serializable兩種隔離級别,

另外可以通過使用讀快照在Read committed級别上禁止不可重複讀問題;

Mysql InnoDB在Read repeatable級别上使用next-key locking 政策來避免幻讀現象的産生。