[資料庫事務與鎖]詳解二: 資料庫的讀現象淺析

來源:互聯網
上載者:User

標籤:

註明: 本文轉載自http://www.hollischuang.com/archives/900

“讀現象”是多個事務並發執行時,在讀取資料方面可能碰到的狀況。先瞭解它們有助於理解各隔離等級的含義。其中包括髒讀、不可重複讀取和幻讀。

髒讀

髒讀又稱無效資料的讀出,是指在資料庫訪問中,事務T1將某一值修改,然後事務T2讀取該值,此後T1因為某種原因撤銷對該值的修改,這就導致了T2所讀取到的資料是無效的。

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

舉例說明:

在下面的例子中,事務2修改了一行,但是沒有提交,事務1讀了這個沒有提交的資料。現在如果事務2復原了剛才的修改或者做了另外的修改的話,事務1中查到的資料就是不正確的了。

事務一 事務二
/* Query 1 */

SELECT age FROM users WHERE id = 1;

/* will read 20 */
 
 
/* Query 2 */
 
UPDATE users SET age = 21 WHERE id = 1;

/* No commit here */

/* Query 1 */

SELECT age FROM users WHERE id = 1;
/* will read 21 */
 
 
ROLLBACK;

/* lock-based DIRTY READ */

在這個例子中,事務2復原後就沒有id是1,age是21的資料了。所以,事務一讀到了一條髒資料。

不可重複讀取

不可重複讀取,是指在資料庫訪問中,一個事務範圍內兩個相同的查詢卻返回了不同資料。這是由於查詢時系統中其他事務修改的提交而引起的。比如事務T1讀取某一資料,事務T2讀取並修改了該資料,T1為了對讀取值進行檢驗而再次讀取該資料,便得到了不同的結果。

一種更易理解的說法是:在一個事務內,多次讀同一個資料。在這個事務還沒有結束時,另一個事務也訪問該同一資料。那麼,在第一個事務的兩次讀資料之間。由於第二個事務的修改,那麼第一個事務讀到的資料可能不一樣,這樣就發生了在一個事務內兩次讀到的資料是不一樣的,因此稱為不可重複讀取,即原始讀取不可重複。

舉例說明:

在基於鎖的並發控制中“不可重複讀取(non-repeatable read)”現象發生在當執行SELECT 操作時沒有獲得讀鎖(read locks)或者SELECT操作執行完後馬上釋放了讀鎖; 多版本並發控制中當沒有要求一個提交衝突的交易回復也會發生“不可重複讀取(non-repeatable read)”現象。

事務一 事務二
/* Query 1 */

SELECT * FROM users WHERE id = 1;
 
 
/* Query 2 */
 
UPDATE users SET age = 21 WHERE id = 1;

COMMIT;


/* in multiversion concurrency
control, or lock-based READ COMMITTED */

/* Query 1 */

SELECT * FROM users WHERE id = 1;

COMMIT; 

/*lock-based REPEATABLE READ */
 

在這個例子中,事務2提交成功,因此他對id為1的行的修改就對其他事務可見了。但是事務1在此前已經從這行讀到了另外一個“age”的值。

幻讀

幻讀是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的資料進行了修改,比如這種修改涉及到表中的“全部資料行”。同時,第二個事務也修改這個表中的資料,這種修改是向表中插入“一行新資料”。那麼,以後就會發生操作第一個事務的使用者發現表中還有沒有修改的資料行,就好象發生了幻覺一樣.一般解決幻讀的方法是增加範圍鎖RangeS,鎖定檢鎖範圍為唯讀,這樣就避免了幻讀。  

幻讀(phantom read)”是不可重複讀取(Non-repeatable reads)的一種特殊情境:當事務沒有擷取範圍鎖的情況下執行SELECT … WHERE操作可能會發生“幻影讀(phantom read)”。

舉例說明:

當事務1兩次執行SELECT … WHERE檢索一定範圍內資料的操作中間,事務2在這個表中建立了(如INSERT)了一行新資料,這條新資料正好滿足事務1的“WHERE”子句。

事務一 事務二
/* Query 1 */

SELECT * FROM users
WHERE age BETWEEN 10 AND 30;
 
 
/* Query 2 */
 
INSERT INTO users VALUES ( 3, ‘Bob‘, 27 );

COMMIT;

/* Query 1 */

SELECT * FROM users
WHERE age BETWEEN 10 AND 30;
 

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

解決方案

要想解決髒讀、不可重複讀取、幻讀等讀現象,那麼就需要提高事務的隔離等級。但與此同時,事務的隔離等級越高,並發能力也就越低。所以,還需要讀者根據業務需要進行權衡。

參考資料

維基百科

[資料庫事務與鎖]詳解二: 資料庫的讀現象淺析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.