資料庫讀現象

2022-06-08 22:15:11 字數 3179 閱讀 2423

資料庫管理軟體的 "讀現象" 指的是當多個事務併發執行時,在讀取資料方面可能碰到的問題,包括又髒讀,不可重複讀和幻讀.

ps: 對於一些資料庫軟體會自帶相應的機制去解決髒讀,不可重複讀,幻讀等問題, 因為這些自帶的機制,下述的一些實驗可能在某一資料庫管理軟體 的預設機制下並不成立,即我們並不能在所有資料庫管理軟體中看到所有的讀現象。所以此處我們暫且拋開具體的某個資料庫管理軟體的預設機制的干擾,暫時假設沒有附加任何機制為前提,單純地去理解資料庫的讀現象。

事務t2更新了一行記錄的內容,但是並沒有提交所做的修改。

事務t1讀取更新後的行,然後t1執行回滾操作,取消了剛才所做的修改。此時t1所讀取的行就無效了,稱之為髒資料。

舉例

事務一事務二

步驟1select age from users where id = 1;/* will read 20 */

步驟2update users set age = 21 where id = 1;/* no commit here */

/* 步驟3 */select age from users where id = 1;/* will read 21 */

rollback;/* lock-based dirty read */

在這個例子中,事務2回滾後就沒有id是1,age是21的資料了。那麼事務1在步驟3的時候讀取的是乙個髒資料,即不準確的資料

事務t1讀取一行記錄,緊接著事務t2修改了t1剛才讀取的那一行記錄並且提交了。

然後t1又再次讀取這行記錄,發現與剛才讀取的結果不同。這就稱為「不可重複」讀,因為t1原來讀取的那行記錄已經發生了變化。

舉例

在基於鎖的併發控制中「不可重複讀(non-repeatable read)」現象發生在當執行select 操作時沒有獲得讀鎖(read locks)或者select操作執行完後馬上釋放了讀鎖; 多版本併發控制中當沒有要求乙個提交衝突的事務回滾也會發生「不可重複讀(non-repeatable read)」現象。

事務一事務二

/* 步驟1 */select * from users where id = 1;

/* 步驟2 */update users set age = 21 where id = 1;commit;/* in multiversion concurrencycontrol, or lock-based read committed */

/* 步驟3 */select * from users where id = 1;commit;/*lock-based repeatable read */

在這個例子中,事務2在步驟2中更新可id=1的資料並提交成功,因此他對id為1的行的修改就對其他事務可見了。但是事務1在此前已經從這行讀到了另外乙個「age」的值。倆次相同的sql語句返回資料確實不一樣的,即為不可重複讀.

幻讀(phantom read)」是不可重複讀(non-repeatable reads)的一種特殊場景:

當事務沒有獲取範圍鎖的情況下執行select … where操作有可能會發生「幻影讀(phantom read)」。

事務t1讀取或修改了指定的where子句所返回的結果集。

然後事務t2新插入一行記錄,這行記錄恰好可以滿足t1所使用的查詢條件中的where 子句的條件。

然後t1又使用相同的查詢再次對錶進行檢索,但是此時卻看到了事務t2剛才插入的新行或者發現了處於whre子句範圍內,但卻未曾修改過的記錄。就好像「幻覺」一樣,因為對t1來說這一行就像突然出現的一樣。

一般解決幻讀的方法是增加範圍鎖ranges,鎖定檢鎖範圍為唯讀,這樣就避免了幻讀。

舉例當事務1兩次執行select … where檢索一定範圍內資料的操作中間,事務2在這個表中建立了(如insert)了一行新資料,這條新資料正好滿足事務1的「where」子句。

事務一事務二

/* 步驟1 */select * from userswhere age between 10 and 30;

/* 步驟2 */insert into users values ( 3, 'bob', 27 );commit;

/* 步驟 3 */select * from userswhere age between 10 and 30;

在這個例子中,事務一執行了兩次相同的查詢操作。但是兩次操作中間事務二向資料庫中增加了一條符合事務一的查詢條件的資料,導致幻讀。

總結:

-- 髒讀就是多個事務併發執行時,事務1多次檢視的資料的中間,別的事務修改了它查詢的資料,但是未提交,導致事務1檢視的資料不準確,這時候別的事務回滾了,就導致事務1檢視了一條髒資料

-- 不可重複讀是多個事務併發執行時,事務1第一次檢視的是資料是一種狀態,期間別的事務對這個資料進行了修改,並提交了.那麼就導致了事務1第二次檢視的資料和第一次檢視的資料狀態不一樣.相同的sql語句產生了倆種狀態.

-- 幻讀,就是不可重複讀的一種特殊狀態,事務1第一次檢視的表的資料是一種狀態,期間別的事務往這個表中插入了一條新資料,並且提交了.那麼事務1再次查詢發現和第一次的id和別的資料對不上了.以為幻讀了.

其實,髒寫、髒讀、不可重複讀、幻讀,都是因為業務系統會多執行緒併發執行,每個執行緒可能都會開啟乙個事務,每個事務都會執行增刪改查操作。然後資料庫會併發執行多個事務,多個事務可能會併發地對快取頁裡的同一批資料進行增刪改查操作,於是這個併發增刪改查同一批資料的問題,可能就會導致我們說的髒寫、髒讀、不可重複讀、幻讀這些問題。

所以這些問題的本質,都是資料庫的多事務併發問題,那麼為了解決多事務併發帶來的髒讀、不可重複讀、幻讀等讀等問題,資料庫才設計了鎖機制、事務隔離機制、mvcc 多版本隔離機制,用一整套機制來解決多事務併發問題,下面我們來分別介紹一下它們

資料庫的讀現象

讀現象 是多個事務併發執行時,在讀取資料方面可能碰到的狀況。先了解它們有助於理解各隔離級別的含義。其中包括髒讀 不可重複讀和幻讀。資料庫帶來的併發問題包括 當第二個事務選擇其它事務正在更新的行時,會發生未確認的相關性問題。第二個事務正在讀取的資料還沒有確認並且可能由更新此行的事務所更改。舉例1 e....

資料庫系統之幻影讀現象專案練習

關於幻影讀現象的介紹可以看我的這篇文章 在pl sql中實現兩個處理資料庫的stored procedures並通過這兩個stored procedures觸發乙個幻影現象。要模擬資料庫事務的併發處理,請使用標準pl sql包dbms lock中的pl sql procedure sleep。使用s...

資料庫避免髒讀,幻讀

一 髒讀 乙個事務讀取到了另外乙個事務沒有提交的資料 詳細解釋 髒讀就是指 當乙個事務正在訪問資料,並且對資料進行了修改,而這種修改還沒有提交到資料庫中,這時,另外乙個事務也訪問這個資料,然後使用了這個資料。因為這個資料是還沒有提交的資料,那麼另外乙個事務讀到的這個資料是髒資料,依據髒資料所做的操作...