離線并發(fā)的來源
在Web項目中,離線并發(fā)顯得尤其嚴重。例如,用戶A和用戶B同時修改數(shù)據(jù)庫中的某張表的R行,加入R行有兩個字段分別是C1,C2。
假如按照如下過程修改:
1 用戶A將數(shù)據(jù)R(C1,C2)讀取到A的瀏覽器中。
2 用戶B將數(shù)據(jù)R(C1,C2)讀取到B的瀏覽器中。
3 用戶A在瀏覽器上將數(shù)據(jù)修改為R(C1’,C2),同時更新到數(shù)據(jù)庫。
4 用戶B在瀏覽器上將數(shù)據(jù)修改為R(C1,C2’),同時更新到數(shù)據(jù)庫。
上述過程存在兩個問題,第一,第4步B在修改數(shù)據(jù)的時候數(shù)據(jù)庫中的數(shù)據(jù)和B的瀏覽器中數(shù)據(jù)已經(jīng)不一致了;第二,如果程序按照哪個字段變化在數(shù)據(jù)庫中更新哪個字段的方式處理的話,那么經(jīng)過上述四步修改,數(shù)據(jù)庫中R行的內(nèi)容是(C1’,C2’),這和A或者B的想法都不同(A認為是(C1’,C2),B認為是(C1,C2’))。
上述過程中A對數(shù)據(jù)庫的修改過程或者B對數(shù)據(jù)庫的修改過程,都是無法根據(jù)數(shù)據(jù)庫的最新內(nèi)容做修改,所以成為離線。A和B同時對記錄R進行就該叫離線。
以上的環(huán)境叫離線并發(fā)。
那么如何解決離線并發(fā)過程中遇到的問題呢?我們引入鎖機制。
鎖機制
鎖機制,就是在需要修改的數(shù)據(jù)上加互斥鎖,通過互斥鎖避免數(shù)據(jù)被同時修改。鎖機制更具其應(yīng)用環(huán)境又分為樂觀鎖和悲觀鎖
樂觀鎖
樂觀鎖,指認為沖突很少發(fā)生,所以只是在數(shù)據(jù)修改的時候比較修改的基礎(chǔ)數(shù)據(jù)和數(shù)據(jù)庫中的數(shù)據(jù)是否相同,相同則修改,否則提示用戶重新裝入數(shù)據(jù)庫中已經(jīng)變化的數(shù)據(jù)。
實現(xiàn)方法1:在進行update的時候使用where條件,在Where標間中比較所有上一步中查詢得到的數(shù)據(jù)。如果數(shù)據(jù)庫中的數(shù)據(jù)沒有變化,則update可以更新到內(nèi)容,否則update語句不能更新到內(nèi)容,可以根據(jù)update的返回值確定更新是否成功。
實現(xiàn)方法2:在每一個表中追加一個特殊字段,類型為timestamp,每次更新的時候比較這個字段的值是否一致,如果一致,則更新,同時將這個字段更新為當前時間,否則,說明數(shù)據(jù)已經(jīng)變更。這也可以使用update加上where實現(xiàn)。
悲觀鎖
悲觀鎖指,需要修改的數(shù)據(jù),在讀取的時候就對數(shù)據(jù)加鎖,其他用戶在準備修改,讀取數(shù)據(jù)的階段判斷數(shù)據(jù)是否上鎖,以此來決定是否進行修改前的讀操作。
實現(xiàn)方法:
通常在數(shù)據(jù)庫中建立一張lock表,該表的字段包括,表明,唯一索引,時間,用戶信息等。
在用戶讀取數(shù)據(jù)準備修改的時候,首先判斷lock表中是否存在自己將要讀取的數(shù)據(jù)。
如果不存在,則在lock表中添加一條記錄,記錄對那張表的哪行數(shù)據(jù)進行修改;如果存在,在判斷時間字段是否超時。
如果超時,則更新lock表中本條記錄的時間字段。(防止死鎖的必要手段)
如果存在,也不超時,說明本條記錄正在被其他用戶修改,則返回并發(fā)信息。
ExtJS教程-
Hibernate教程-
Struts2 教程-
Lucene教程