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