資料庫併發事務出現的幾種讀現象
當多個客戶端併發訪問資料庫時,若沒有采取必要的隔離措施,存在以下問題,這些問題分為5類,其中3類資料度問題:髒讀、幻讀、不可重複讀,2類資料更新問題:第一類丟失更新、第二類丟失更新。
髒讀:一個事務讀取到另外一個事務未提交的資料
事務A訪問資料庫並對某個資料進行了修改,但是當修改還未提交到資料庫的時候事務B也訪問資料庫中的這個資料,然後事務A由於某種原因撤銷對該值的修改,即事務A進行了回滾,修改後的資料並未提交到資料庫,資料庫中的資料仍然是事務A修改之前的原資料,但是此時B事務讀取的資料是A事務已經修改的資料無效資料,因為這個資料還沒提交,因此這個資料是髒資料,使用髒資料做的操作是不正確的,因此事務B的讀操作屬於髒讀。
時間 | 轉賬事務A | 取款事務B |
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 查詢賬戶餘額為1000元 | |
T4 | 取出500,把餘額改為500元 | |
T5 | 查詢賬戶餘額為500元(髒讀) | |
T6 | 撤銷事務,餘額恢復1000元 | |
T7 | 匯入100元,把餘額改為600元 | |
T8 | 提交事務 |
不可重複讀:同一個事務中,兩次讀取同一資料,得到的內容不同(重點在修改)
事務A訪問資料庫中的某個資料,然後事務B訪問資料庫中的同一資料並對其進行了修改並提交資料,事務A再次訪問資料庫中的這個資料,由於事務B已修改並提交了這個資料,導致事務A在同一個事務中訪問同一資料得到的內容不同,此時事務A的讀現象稱為不可重複讀。
時間 | 轉賬事務A | 查款事務B |
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 查詢賬戶餘額為1000元 | |
T4 | 取出500,把餘額改為500元 | |
T5 | 提交事務 | |
T6 | 查詢賬戶餘額為500元(不可重複讀) | |
T7 | 提交事務 |
幻讀:同一個事務中,同樣的條件讀取兩次,得到的記錄數不相同(重點在新增或刪除)
當事務不是獨立執行時發生的一種現象。事務A按照某種查詢條件讀取表中所有記錄,然後事務B訪問資料庫,並插入一條符合事務A查詢條件的記錄並提交。當事務A再次按照同樣的查詢條件進行查詢時,會查詢到之前沒有的記錄,造成了事務A的幻讀。
時間 | 統計金額事務A | 轉賬事務B |
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 統計總款數為10000元 | |
T4 | 新增一個存款賬戶,存款為100元 | |
T5 | 提交事務 | |
T6 | 再次統計總存款數為10100元(幻讀) |
第一類丟失更新:A事務撤銷時,把已經提交的B事務的更新資料覆蓋了。
時間 | 取款事務A | 轉賬事務B |
T1 | 開始事務A | |
T2 | 開始事務B | |
T3 | 查詢賬戶為1000元 | |
T4 | 查詢賬戶為1000元 | |
T5 | 匯入1000元,把餘額改為2000元 | |
T6 | 提交事務 | |
T7 | 取出100元,把餘額改為900元 | |
T8 | 撤銷事務,餘額恢復為1000元 |
第二類丟失更新:A事務覆蓋B事務已經提交的資料,造成B事務所做的操作丟失
時間 | 轉賬事務A | 取款事務B |
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 查詢賬戶餘額為1000元 | |
T4 | 查詢賬戶餘額為1000元 | |
T5 | 取出100元,把餘額改為900元 | |
T6 | 提交事務 | |
T7 | 匯入100元 | |
T8 | 提交事務 | |
T9 | 把餘額改為1100元(丟失更新) |
為了解決上述問題,資料庫通過鎖機制解決併發訪問的問題。根據鎖物件的不同:分為行級鎖和表級鎖;根據併發事務鎖定的關係上看:分為共享鎖定和獨佔鎖定。但是直接使用鎖機制管理是很複雜的,基於鎖機制,資料庫給使用者提供了不同的事務隔離級別,只要設定了事務的隔離級別,資料庫就會分析事務中的sql語句然後自動選擇合適的鎖。關於事務的隔離級別,見下一篇文章。。。。。。。