1.?臟寫购桑、臟讀、不可重復(fù)讀氏淑、幻讀等問題
1)臟寫
2)臟讀
無論是臟寫還是臟讀勃蜘,都是一個事務(wù)去更新或查詢了另一個事務(wù)未提交的數(shù)據(jù),如果另一個事務(wù)回滾假残,
就出現(xiàn)了臟寫缭贡、臟讀的情況
3)不可重復(fù)讀
不可重復(fù)讀不是什么大問題,具體取決于是否允許不可重復(fù)讀辉懒,如果業(yè)務(wù)要求事務(wù)期間每次讀取的
數(shù)據(jù)都是一致的阳惹,這就是問題,需要解決
4)幻讀
2.?MySQL隔離機制
1)read uncommitted
不允許臟寫(不允許兩個未提交的事務(wù)同時更新一條數(shù)據(jù))眶俩,但是會出現(xiàn)臟讀莹汤、不可重復(fù)讀、幻讀問題
2)read committed
不會出現(xiàn)臟寫和臟讀(查詢不到別的事務(wù)未提交的數(shù)據(jù))颠印,但是會出現(xiàn)不可重復(fù)讀纲岭、幻讀
3)repeatable read
不會出現(xiàn)臟寫、臟讀线罕、不可重復(fù)讀問題(事務(wù)一旦開啟止潮,別的事務(wù)提交后的值也不會讀到),但是會出現(xiàn)幻讀钞楼,
這里是mysql比較牛的地方喇闸,RR級別下可以解決幻讀的問題,要借助于下面所講的MVCC
4)serializable ?
串行化執(zhí)行询件,根本就不是并發(fā)燃乍,所以上述問題都不會出現(xiàn)
3.?MVCC
講MVCC之前,我們有必要聊下undo log版本鏈雳殊。
簡單來說,我們每條數(shù)據(jù)都有兩個隱藏的字段trx_id和roll_pointer窗轩,trx_id是最近一次更新數(shù)據(jù)的事務(wù)id夯秃, roll_pointer指向了你更新這個事務(wù)之前生成的undo log
再來看看基于undo log鏈的ReadView機制
簡單說就是執(zhí)行一個事務(wù)的時候,就會生成一個ReadView,里面有4個關(guān)鍵東西
1)m_ids --此時有哪些事務(wù)未提交
2)min_trx_id --m_ids里最小的值
3)max_trx_id --表示下一個事務(wù)生成時分配給它的id
4)creator_trx_id --當(dāng)前事務(wù)id
4.?鎖
1)獨占鎖(X鎖)
臟寫是絕對不允許的仓洼,是靠鎖來實現(xiàn)的介陶,讓多個事務(wù)更新同一行數(shù)據(jù)串行化,避免同時更新
事務(wù)A要更新數(shù)據(jù)色建,一看該數(shù)據(jù)沒有人鎖定哺呜,立馬創(chuàng)建一個鎖,包含了自己的trx_id和等待狀態(tài)箕戳,然后鎖和數(shù)據(jù)
關(guān)聯(lián)起來某残;此時事務(wù)B也想要更新數(shù)據(jù),發(fā)現(xiàn)數(shù)據(jù)已經(jīng)被加鎖了陵吸,然后B也生成一個鎖玻墅,但此時B是等待狀態(tài)的
接著事務(wù)A更新完數(shù)據(jù)提交,會把鎖釋放掉壮虫。一旦鎖釋放澳厢,就會去找還有沒有別的事務(wù)加鎖了,找到B的鎖把等
待狀態(tài)改為false,然后喚醒事務(wù)B繼續(xù)執(zhí)行囚似,此時事務(wù)B就獲取到數(shù)據(jù)了
如果此時別的事務(wù)來讀取這條數(shù)據(jù)會加鎖嘛剩拢?不會,基于MVCC饶唤,避免了頻繁加鎖
2)共享鎖(S鎖)
select * from table lock in share mode會給當(dāng)前數(shù)據(jù)加共享鎖
此時明白了徐伐,獨占鎖和獨占鎖是互斥的,別的事務(wù)不可以更新操作搬素;如果是查詢呵晨,默認(rèn)走MVCC不加鎖,如果手
動加共享鎖熬尺,也是互斥的摸屠;最后共享鎖和共享鎖是不互斥的
3)行鎖(上述兩種鎖講的就是行鎖)
4)表鎖(一般不會這樣操作)
lock table *** read --表級共享鎖
lock table *** write --表級獨占鎖
查詢、更新行數(shù)據(jù)的時候會在表上加意向鎖粱哼;分為意向共享鎖和意向獨占鎖