事務的隔離級別與鎖的申請和釋放

2022-02-26 04:10:13 字數 4419 閱讀 1279

髒讀(dirty read)

髒讀意味著乙個事務讀取了另乙個事務未提交的資料,而這個資料是有可能回滾

不可重複讀(unrepeatable read)

不可重複讀意味著,在資料庫訪問中,乙個事務範圍內兩個相同的查詢卻返回了不同資料。這是由於查詢時系統中其他事務修改的提交而引起的。

例如:事務b中對某個查詢執行兩次,當第一次執行完時,事務a對其資料進行了修改。事務b中再次查詢時,資料發生了改變

幻讀(phantom read)

幻讀,是指當事務不是獨立執行時發生的一種現象,例如第乙個事務對乙個表中的資料進行了修改,這種修改涉及到表中的全部資料行。同時,第二個事務也修改這個表中的資料,這種修改是向表中插入一行新資料。那麼,以後就會發生操作第乙個事務的使用者發現表中還有沒有修改的資料行,就好象發生了幻覺一樣.

併發問題可歸納為以下幾類:

a.丟失更新:撤銷乙個事務時,把其他事務已提交的更新資料覆蓋(a和b事務併發執行,a事務執行更新後,提交;b事務在a事務更新後,b事務結束前也做了對該行資料的更新操作,然後回滾,則兩次更新操作都丟失了)。

b.髒讀:乙個事務讀到另乙個事務未提交的更新資料(a和b事務併發執行,b事務執行更新後,a事務查詢b事務沒有提交的資料,b事務回滾,則a事務得到的資料不是資料庫中的真實資料。也就是髒資料,即和資料庫中不一致的資料)。

c.不可重複讀:乙個事務讀到另乙個事務已提交的更新資料(a和b事務併發執行,a事務查詢資料,然後b事務更新該資料,a再次查詢該資料時,發現該資料變化了)。

d. 覆蓋更新:這是不可重複讀中的特例,乙個事務覆蓋另乙個事務已提交的更新資料(即a事務更新資料,然後b事務更新該資料,a事務查詢發現自己更新的資料變了)。

e.虛讀(幻讀):乙個事務讀到另乙個事務已提交的新插入的資料(a和b事務併發執行,a事務查詢資料,b事務插入或者刪除資料,a事務再次查詢發現結果集中有以前沒有的資料或者以前有的資料消失了)。

資料庫系統提供了四種事務隔離級別供使用者選擇:

a.serializable(序列化):乙個事務在執行過程中完全看不到其他事務對資料庫所做的更新(事務執行的時候不允許別的事務併發執行。事務序列化執行,事務只能乙個接著乙個地執行,而不能併發執行。)。

b.repeatable read(可重複讀):乙個事務在執行過程中可以看到其他事務已經提交的新插入的記錄,但是不能看到其他其他事務對已有記錄的更新。

c.read commited(讀已提交資料):乙個事務在執行過程中可以看到其他事務已經提交的新插入的記錄,而且能看到其他事務已經提交的對已有記錄的更新。

d.read uncommitted(讀未提交資料):乙個事務在執行過程中可以看到其他事務沒有提交的新插入的記錄,而且能看到其他事務沒有提交的對已有記錄的更新。

丟失更新

髒讀非重複讀

覆蓋更新

幻像讀未提交讀yy

yyy已提交讀nn

yyy可重複讀nn

nny序列化nn

nnn隔離級別

資料庫系統有四個隔離級別(大多數資料庫預設級別為read commited)。對資料庫使用何種隔離級別要審慎分析,因為

1. 維護乙個最高的隔離級別雖然會防止資料的出錯,但是卻導致了並行度的損失,以及導致死鎖出現的可能性增加。

2. 然而,降低隔離級別,卻會引起一些難以發現的bug。

serializable(序列化)

新增範圍鎖(比如表鎖,頁鎖等,關於range lock,我也沒有很深入的研究),直到transaction a結束。以此阻止其它transaction b對此範圍內的insert,update等操作。

幻讀,髒讀,不可重複讀等問題都不會發生。

repeatable read(可重複讀)

對於讀出的記錄,新增共享鎖直到transaction a結束。其它transaction b對這個記錄的試圖修改會一直等待直到transaction a結束。

可能發生的問題:當執行乙個範圍查詢時,可能會發生幻讀。

read committed(提交讀)

在transaction a中讀取資料時對記錄新增共享鎖,但讀取結束立即釋放。其它transaction b對這個記錄的試圖修改會一直等待直到a中的讀取過程結束,而不需要整個transaction a的結束。所以,在transaction a的不同階段對同一記錄的讀取結果可能是不同的。

可能發生的問題:不可重複讀。

read uncommitted(未提交讀)

不新增共享鎖。所以其它transaction b可以在transaction a對記錄的讀取過程中修改同一記錄,可能會導致a讀取的資料是乙個被破壞的或者說不完整不正確的資料。

另外,在transaction a中可以讀取到transaction b(未提交)中修改的資料。比如transaction b對r記錄修改了,但未提交。此時,在transaction a中讀取r記錄,讀出的是被b修改過的資料。

可能發生的問題:髒讀。

問題

我們看到,當執行不同的隔離級別時,可能會發生各種各樣不同的問題。下面對它們進行總結並舉例說明。

幻讀

幻讀發生在當兩個完全相同的查詢執行時,第二次查詢所返回的結果集跟第乙個查詢不相同。

發生的情況:沒有範圍鎖。

例子:事務1

事務2

select

* from

users

where

age between

10and

30

insert

into

users values(3

, 'bob'

, 27

);

commit;

select

* from

users where

age between

10and

30;

如何避免:實行序列化隔離模式,在任何乙個低階別的隔離中都可能會發生。

不可重複讀

在基於鎖的並行控制方法中,如果在執行select時不新增讀鎖,就會發生不可重複讀問題。

在多版本並行控制機制中,當乙個遇到提交衝突的事務需要回退但卻被釋放時,會發生不可重複讀問題。

事務1事務2

select

* from

users where

id = 1;

update

users set

age = 21

where

id = 1

;commit; /* in multiversion concurrency*/

control, or lock-based read committed *

select

* from

users where

id = 1;

commit; /* lock-based repeatable read */

在上面這個例子中,事務2提交成功,它所做的修改已經可見。然而,事務1已經讀取了乙個其它的值。在序列化和可重複讀的隔離級別中,資料庫管理系統會返回舊值,即在被事務2修改之前的值。在提交讀和未提交讀隔離級別下,可能會返回被更新的值,這就是「不可重複讀」。

有兩個策略可以防止這個問題的發生:

1. 推遲事務2的執行,直至事務1提交或者回退。這種策略在使用鎖時應用。(悲觀鎖機制,比如用select for update為資料行加上乙個排他鎖)

2. 而在多版本並行控制中,事務2可以被先提交。而事務1,繼續執行在舊版本的資料上。當事務1終於嘗試提交時,資料庫會檢驗它的結果是否和事務1、事務2順序執行時一樣。如果是,則事務1提交成功。如果不是,事務1會被回退。(樂觀鎖機制)

髒讀

髒讀發生在乙個事務a讀取了被另乙個事務b修改,但是還未提交的資料。假如b回退,則事務a讀取的是無效的資料。這跟不可重複讀類似,但是第二個事務不需要執行提交。 

事務1事務2

select

* from

users where

id = 1;

update

users set

age = 21

where

id = 1

select

from

users where

id = 1;

commit; /* lock-based dirty read */

記憶體的申請和釋放

常規用法 virtualalloc lpvoid lpaddress,size t dwsize,dword flallocationtype,dword flprotect lpaddress,指定記憶體開始的位址。dwsize,分配記憶體的大小。flallocationtype,分配記憶體的型別...

記憶體的申請和釋放

在c裡,記憶體管理是通過專門的函式來實現。另外,為了相容各種程式語言,作業系統提供的介面通常是c 語言寫成的函式宣告 windows 本身也由c和組合語言寫成 1分配記憶體malloc函式 需要包含標頭檔案 and 函式宣告 函式原型 void malloc int size 說明 malloc 向...

共享記憶體的申請和釋放

1.通過對映來申請記憶體 物理頁可以在多個程序中共享 mapviewoffile是計算機函式,功能是將乙個檔案對映物件對映到當前應用程式的位址空間。mapviewoffileex允許我們指定乙個基本位址來進行對映。需要和 關閉對映 unmapviewoffile g lpbuff 配套使用 1 共享...