在read uncommitted級別,事務中的修改,即使沒有提交,對其他的事務也是可見的.
事務可以讀取未提交的資料,這也被稱為髒讀(dirty read). 這個級別會導致很多的問題,從效能上來說,read uncommitted不會比其他的級別好很多,但缺乏其他級別的好處,除非真的非常必要的理由,在實際應用中一般很少使用.
大多數資料庫的預設隔離級別都是read committed(但mysql不是). read committed滿足前面提到的隔離性的簡單定義:乙個事務開始時,只能"看見"已經提交的事務所作的修改.換句話,乙個事務從開始到提交之前,所作的任何修改對其他事務都是不可見的.這個級別有時候也叫做不可重複讀(nonrepeatable read),因為2次執行同樣的查詢,可能得到不同的結果.
讀已提交的不可重複讀再現和疑問
時間事務a
事務b設定隔離級別
set session transaction isolation level repeatable read;
set session transaction isolation level repeatable read;
t1開始事務(start transaction;)
t2開始事務(start transaction;)
t3查詢賬戶餘額100元
t4查詢賬戶餘額100元
t5取出10元,將餘額改為90元
t6提交事務
t7查詢賬戶餘額90元(和t4讀取的不一致)
如果需要手動實現一遍的話,可以參考這篇部落格
突然在想"讀到 90 不是挺好的麼,實際就是 90 了啊…"
begin transaction
update 表 1 select from ....
// 不可重複讀
update 表 2 select from ...
commit
表 1 和 表 2 不一致了
repeatable read解決了髒讀的問題.該級別保證了在同乙個事務***多次***讀取同樣的記錄的結果是一致的. 但是理論上,可重複讀隔離級別還是無法解決裡另乙個幻讀(phantom read)的問題,
所謂幻讀,指的是在當前事務在讀取某個範圍內的記錄時,另乙個事務又在該範圍內查詢一條新的記錄,當之前的事務再次讀取該範圍的記錄時,會產生幻行(phantom row)innodb和xtradb儲存引擎通過多版本併發控制(mvcc,multiversion concurrency control)
解決了幻讀的問題
可重複讀 如果按照上面的**再執行一遍會怎樣?
時間事務a
事務b設定隔離級別
set session transaction isolation level repeatable read;
set session transaction isolation level repeatable read;
t1開始事務(start transaction;)
t2開始事務(start transaction;)
t3查詢賬戶餘額100元
t4查詢賬戶餘額100元
t5取出10元,將餘額改為90元
t6提交事務
t7查詢賬戶餘額還是100元
t8如果此時事務a執行修改操作卻能正確修改資料庫,比如update x表 set money=money-10 where id=x;
此時的餘額會變成80元,好神奇哦
臥槽,居然還是100元,雖然解決了多次讀取到的資料不一致的問題, 但是你這讀取到的是舊的值啊. 如果用來
begin transaction
update 表 1 select from ....
// 不可重複讀
update 表 2 select from ...
commit
表 1 和 表 2 不一致了
豈不是翻車了??? 所以有時候感覺如果不是同乙個
事務\color
同乙個事
務多次讀取的話,用read committed隔離級別就夠了,反正這個級別也能實現行級鎖,oracle就是預設read committed隔離級別
serializable是最高的隔離級別.它通過強制事務序列化執行,避免了前面說的幻讀的問題,簡單來說,serializable會在讀取的每一行
資料上都加鎖,所以可能導致大的超時和鎖的爭用的問題.實際應用中也很少用到這個隔離級別,只有在非常需要確保資料的一致性而且可以接受沒有併發的情況下,才考慮採用該級別.
隔離級別
髒讀可能性
不可重複讀可能性
幻讀可能性
加鎖讀read uncommitted
yesyes
yesno
read committed
noyes
yesno
repeatable read
nono
yesno
serializable
nono
noyes
從《高效能mysql>>抄寫的補充知識點
隱式和顯式鎖定
innodb採用的是兩階段鎖定協議(two-phase locking protocol). 在事務執行過程中,隨時都可以執行鎖定,鎖只有在commit和rollback的時候才會釋放,並且所有的鎖是同一時刻被釋放.前面描述的鎖定是隱式鎖定,innodb會根據隔離級別在需要的時候進行加鎖.
另外,innodb也支援通過特定的語句進行顯式鎖定,這些語句是不屬於sql規範的
mysqlye 也支援lock tables和unlock tables語句,這些是在伺服器層
實現的,和儲存引擎無關.他們有自己的用途,但並不能替代事務處理.如果應用需要用到的事務,還是應該選擇事務性儲存引擎.
經常可以發現,應用已經將表從myisam轉換到innodb,但還是顯式地使用lock tables語句.但不但沒有必要,還會影響效能,實際上innodb的行級鎖工作得更好.
多版本併發控制(上班時間寫的部落格來不及手打了 貼上個圖,後期再手打)
MySQL事務隔離級別介紹
sql標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低階別的隔離級一般支援更高的併發處理,並擁有更低的系統開銷。read uncommitted 讀取未提交內容 在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用於實際應用,因...
MySQL資料庫事務的隔離級別介紹
在大學學習資料庫的時候就接觸到了事務,但在現在的工作中也沒有使用過,因為平台不支援,在需要保證資料一致性的時候就要自己做,比如有兩條delete語句,當第一條執行成功第二條失敗的時候,就要把第一條刪除的記錄再新增上,非常麻煩。也致使自己對事務沒有真正理解和掌握。使用事務是保證資料的正確性,n條sql...
MySQL表鎖,行鎖,事務隔離級別介紹
myisam支援表鎖,不支援事務,支援全文索引,預設表型別.innodb支援行鎖,支援事務,不支援全文索引 但可以用sphinx分詞索引 行鎖級 share lock 別名 讀鎖,共享鎖,意向鎖 exclusivelock 別名 寫鎖,排他鎖 表鎖級 myisam 表共享讀鎖 table read ...