背景介紹
MySQL 是世界上最流行的開源關(guān)系型數(shù)據(jù)庫管理系統(tǒng),被廣泛應(yīng)用于Web應(yīng)用,這個數(shù)據(jù)庫在鎖粒度上分類為表鎖和行鎖,其中 InnoDB 存儲引擎為每一行記錄都添加了一個時間戳,用于處理多事務(wù)并發(fā)訪問,這種機(jī)制被稱為樂觀鎖。
樂觀鎖
樂觀鎖方式是一種樂觀思想,它認(rèn)為數(shù)據(jù)在通常情況下不會發(fā)生沖突,也就是一個先讀后寫的機(jī)制,它不會采用強(qiáng)制獲取鎖定的方式,而是在更新的時候,判斷一下在這個數(shù)據(jù)讀取到表中時,是否有其他的事務(wù)對其進(jìn)行了修改,如果對其修改了,則重新讀取這個數(shù)據(jù),再次嘗試更新,直到成功為止。
臟讀問題
在MySQL中樂觀鎖會存在一種臟讀現(xiàn)象,也就是在當(dāng)前某個事務(wù)還沒有提交的時候,其他事務(wù)也可以讀到他的未提交的結(jié)果。舉個例子,假設(shè)有2個事務(wù)同時操作一個數(shù)據(jù)行,其中一個事務(wù)將該行記錄的值從原來的10改為了20, 另外一個事務(wù)正在處理這個非常遜的數(shù)據(jù)行,但是此時事務(wù)一并沒有提交,而是還在繼續(xù)做事,而已經(jīng)提交事務(wù)的讀取到的此時的非常訥的數(shù)據(jù)行數(shù)據(jù)值是20,這就是臟讀問題。
解決方法
對于MySQL中的樂觀鎖臟讀問題,我們可以采取一些措施來避免他的產(chǎn)生,其中最簡單有效的方法是在查詢數(shù)據(jù)時加上FOR UPDATE,它可以在查詢數(shù)據(jù)的過程中加上一層,在事務(wù)提交之前,讀取的數(shù)據(jù)都會被加上自己的行鎖,從而降低樂觀鎖的臟讀的發(fā)生。