資料庫隔離級別詳解

2021-07-16 10:21:04 字數 4082 閱讀 7777

引用自:

髒讀(事務沒提交,提前讀取):髒讀就是指當乙個事務正在訪問資料,並且對資料進行了修改,而這種修改還沒有提交到資料庫中,這時,另外乙個事務也訪問這個資料,然後使用了這個資料。

不可重複讀(兩次讀的不一致) :是指在乙個事務內,多次讀同一資料。在這個事務還沒有結束時,另外乙個事務也訪問該同一資料。那麼,在第乙個事務中的兩次讀資料之間,由於第二個事務的修改,那麼第乙個事務兩次讀到的的資料可能是不一樣的。這樣就發生了在乙個事務內兩次讀到的資料是不一樣的,因此稱為是不可重複讀。例如,乙個編輯人員兩次讀取同一文件,但在兩次讀取之間,作者重寫了該文件。當編輯人員第二次讀取文件時,文件已更改。原始讀取不可重複。如果只有在作者全部完成編寫後編輯人員才可以讀取文件,則可以避免該問題。

第一類更新丟失(回滾丟失):

當2個事務更新相同的資料來源,如果第乙個事務被提交,而另外乙個事務卻被撤銷,那麼會連同第乙個事務所做的跟新也被撤銷。也就是說第乙個事務做的跟新丟失了。

第二類更新丟失(覆蓋丟失):

第二類更新丟失實在實際應用中經常遇到的併發問題,他和不可重複讀本質上是同一類併發問題,通常他被看做不可重複讀的特例:當2個或這個多個事務查詢同樣的記錄然後各自基於最初的查詢結果更新該行時,會造成第二類丟失更新。因為每個事務都不知道不知道其他事務的存在,最後乙個事務對記錄做的修改將覆蓋其他事務對該記錄做的已提交的跟新…

事務(transaction)是資料庫管理系統的執行單位,可以是乙個資料庫操作(如select操作)或者是一組操作序列。事務acid屬性,即原子性(atomicity)、一致性(consistency)、隔離性(isolation)、永續性(durability)。

- 原子性:保證事務中的所有操作全部執行或全部不執行。例如執行轉賬事務,要麼轉賬成功,要麼失敗。成功,則金額從轉出帳戶轉入到目的帳戶,並且兩個帳戶金額將發生相應的變化;失敗,則兩個賬戶的金額都不變。不會出現轉出帳戶扣了錢,而目的帳戶沒有收到錢的情況。

- 一致性:保證資料庫始終保持資料的一致性——事務操作之前是一致的,事務操作之後也是一致的,不管事務成功與否。如上面的例子,轉賬之前和之後資料庫都保持資料上的一致性。

- 隔 離性:多個事務併發執行的話,結果應該與多個事務序列執行效果是一樣的。顯然最簡單的隔離就是將所有事務都序列執行:先來先執行,乙個事務執行完了才允許 執行下乙個。但這樣資料庫的效率低下,如:兩個不同的事務只是讀取同一批資料,這樣完全可以併發進行。為了控制併發執行的效果就有了不同的隔離級別。下面 將詳細介紹。

- 永續性:永續性表示事物操作完成之後,對資料庫的影響是持久的,即使資料庫因故障而受到破壞,資料庫也應該能夠恢復。通常的實現方式是採用日誌。

資料庫隔離級別有四種,應用《高效能mysql》一書中的說明:

事務隔離級別(transaction isolation levels):隔離級別就是對對事務併發控制的等級。ansi/ iso sql將其分為序列化(serializable)、可重複讀(repeatable read)、讀已提交(read commited)、讀未提交(read uncommited)四個等級。為了實現隔離級別通常資料庫採用鎖(lock)。一般在程式設計的時候只需要設定隔離等級,至於具體採用什麼鎖則由資料庫來設定。首先介紹四種等級,然後舉例解釋後面三個等級(可重複讀、讀已提交、讀未提交)中會出現的併發問題。

1.序列化(serializable):所有事務都乙個接乙個地序列執行,這樣可以避免幻讀(phantom reads)。對於基於鎖來實現併發控制的資料庫來說,序列化要求在執行範圍查詢(如選取年齡在10到30之間的使用者)的時候,需要獲取範圍鎖(range lock)。如果不是基於鎖實現併發控制的資料庫,則檢查到有違反序列操作的事務時,需要滾回該事務。

2.可重複讀(repeatable read):所有被select獲取的資料都不能被修改,這樣就可以避免乙個事務前後讀取資料不一致的情況。但是卻沒有辦法控制幻讀,因為這個時候其他事務不能更改所選的資料,但是可以增加資料,因為前乙個事務沒有範圍鎖。mysql本來預設也是這個級別

3.讀已提交(read commited):被讀取的資料可以被其他事務修改。這樣就可能導致不可重複讀。也就是說,事務的讀取資料的時候獲取讀鎖,但是讀完之後立即釋放(不需要等到事務結束),而寫鎖則是事務提交之後才釋放。釋放讀鎖之後,就可能被其他事物修改資料。該等級也是sql server預設的隔離等級。

4.讀未提交(read uncommited):這是最低的隔離等級,允許其他事務看到沒有提交的資料。這種等級會導致髒讀(dirty read)。

例子:下面考察後面三種隔離等級對應的併發問題。假設有兩個事務。事務1執行查詢1,然後事務2執行查詢2,然後提交,接下來事務1中的查詢1再執行一次。查詢基於以下表進行:

users

idname

age1

joe20

2jill25

1.可重複讀(幻讀,phantom reads)

乙個事務中先後各執行一次同乙個查詢,但是返回的結果集卻不一樣。發生這種情況是因為在執行select操作的時候沒有獲取範圍鎖(range lock),導致其他事務仍然可以插入新的資料。

transaction 1

transaction 2

select * from users where age between 10 and 30;

insert into users values ( 3, 『bob』, 27 );

commit;

select * from users where age between 10 and 30;

注意transaction 1對同乙個查詢語句(query 1)執行了兩次。 如果採用更高階別的隔離等級(即序列化)的話,那麼前後兩次查詢應該返回同樣的結果集。但是在可重複讀隔離等級中卻前後兩次結果集不一樣。但是為什麼叫做可重複讀等級呢?那是因為該等級解決了下面的不可重複讀問題。

2.讀已提交(不可重複讀,non-repeatable reads)

在採用鎖來實現併發控制的資料庫系統中,不可重複讀是因為在執行select操作的時候沒有加讀鎖(read lock)。

transaction 1

transaction 2

select * from users where id = 1;

update users set age = 21 where id = 1;;

commit;

select * from users where id = 1;

在這個例子當中,transaction 2提交成功,所以transaction 1第二次將獲取乙個不同的age 值.在serializable和repeatable read隔離級別中,資料庫應該返回同乙個值。而在read committed和read uncommitted級別中資料庫返回更新的值。這樣就出現了不可重複讀。

3. 讀未提交 (髒讀,dirty reads)

如果乙個事務2讀取了另乙個事務1修改的值,但是最後事務1滾回了,那麼事務2就讀取了乙個髒資料,這也就是所謂的髒讀。發生這種情況就是允許事務讀取未提交的更新。

transaction 1

transaction 2

select * from users where id = 1;

update users set age = 21 where id = 1;

select * from users where id = 1;

rollback

綜上述,可以等到下面的**:

隔離等級

髒讀不可重複讀

幻讀讀未提交

yesyes

yes讀已提交

noyes

yes可重複讀

nono

yes序列化

nono

no

資料庫隔離級別詳解

事務 transaction 是資料庫管理系統的執行單位,可以是乙個資料庫操作 如select操作 或者是一組操作序列。事務acid屬性,即原子性 atomicity 一致性 consistency 隔離性 isolation 永續性 durability 原子性 保證事務中的所有操作全部執行或全部...

資料庫事務隔離級別詳解

資料庫事務的隔離級別有4個,由低到高依次為read uncommitted read committed repeatable read serializable,這四個級別可以逐個解決髒讀 不可重複讀 幻讀這幾類問題。可能出現 不會出現 髒讀不可重複讀 幻讀read uncommitted rea...

資料庫隔離級別

read uncommited 讀未提交 最低級別,可讀取未提交事物的資料,這會導致髒讀,比如 某時刻會話a修改了乙個資料,但還未提交,此時會話b,讀取了該資料,這是,會話a回滾了事物,這就導致資料出現了不一致狀態,這就是髒讀 read commited 提交讀 避免了髒讀,但會導致不可重複讀,例如...