鎖的介紹
1.什么是樂觀鎖捆毫?
? ? ? ?通俗的理解面睛,太樂觀了絮蒿,總是認為我們對數據操作時,不會產生沖突問題叁鉴。也就是說在操作數據時土涝,并不進行任何其他的特殊處理(也就是不加鎖),而在進行更新后幌墓,再去判斷是否有沖突了但壮。一般來說數據庫不實現樂觀鎖,需要我們自己去實現常侣。
? ? ? ?樂觀鎖中常見的實現機制:先給數據表加一個版本(version)字段蜡饵,操作一次,將那條記錄的版本號加1胳施。
2.什么是悲觀鎖溯祸?
? ? ? ?通俗的理解,太悲觀了,總是認為我們對數據操作時焦辅,會產生沖突問題博杖。也就是說每次操作時,都要通過獲取鎖才能進行對相同數據的操作筷登。數據庫本身實現了悲觀鎖剃根。
?有哪些悲觀鎖?
2.1共享鎖:又稱讀鎖仆抵,是讀取操作創(chuàng)建的鎖跟继。其他事務可以并發(fā)讀取數據,但是不能對數據進行修改镣丑,直到釋放鎖。
共享鎖SQL實現機制:SELECT... LOCK IN SHARE MODE;
2.2 排它鎖:又稱寫鎖娱两,如果事務T對數據D加上排他鎖后莺匠,則其他事務不能再對D加任任何類型的鎖。獲準排他鎖的事務既?能讀數據十兢,又能寫數據趣竣。
?排他鎖SQL實現機制:SELECT ... FOR UPDATE;
2.3行鎖:對數據庫中的“讀寫操作的行”加鎖
2.4表鎖:對數據庫中的“讀取操作的表”加鎖
一、共享鎖
1旱物、多個事務的查詢語句可以共用一把共享鎖遥缕;
2、如果只有一個事務拿到了共享鎖宵呛,則該事務可以對數據進行 update单匣、delete等操作;
3宝穗、如果有多個事務拿到了共享鎖户秤,則所有事務都不能對數據進行update、delete等操作逮矛。
二鸡号、排他鎖
排他鎖又稱為寫鎖,簡稱X鎖须鼎,顧名思義鲸伴,排他鎖不能與其他鎖并存,并且只有一個事務能拿到某一數據行的排他鎖晋控,其余事務不能再獲取該數據行的所有鎖汞窗。
結論
1、只有一個事務能獲取該數據的排他鎖糖荒;
2杉辙、一旦有一個事務獲取了該數據的排他鎖之后,其余事務對于該數據的操作將會被阻塞,直到鎖釋放蜘矢。
三狂男、自增鎖
自增鎖是mysql一種特殊的鎖,如果表中存在自增字段品腹,mysql便會自動維護一個自增鎖岖食。
注意:
1、如果上述三次查詢放到一個事務中舞吭,在RR事務隔離級別下泡垃,是不會出現幻讀的情況;
2羡鸥、自增鎖不僅是只對insert
into語句才會出現蔑穴,還對其他的插入語句生效。
記錄鎖惧浴、間隙鎖存和、臨鍵鎖,都屬于排它鎖衷旅;
記錄鎖就是鎖住一行記錄捐腿;
間隙鎖只有在事務隔離級別 RR 中才會產生;
唯一索引只有鎖住多條記錄或者一條不存在的記錄的時候柿顶,才會產生間隙鎖茄袖,指定給某條存在的記錄加鎖的時候,只會加記錄鎖嘁锯,不會產生間隙鎖宪祥;
普通索引不管是鎖住單條,還是多條記錄猪钮,都會產生間隙鎖品山;
間隙鎖會封鎖該條記錄相鄰兩個鍵之間的空白區(qū)域,防止其它事務在這個區(qū)域內插入烤低、修改肘交、刪除數據,這是為了防止出現 幻讀 現象扑馁;
普通索引的間隙涯呻,優(yōu)先以普通索引排序,然后再根據主鍵索引排序(多普通索引情況還未研究)腻要;
事務級別是RC(讀已提交)級別的話复罐,間隙鎖將會失效。
鎖優(yōu)化的建議:
1雄家、盡可能讓所有數據檢索都通過索引來完成效诅,避免無索引行鎖升級為表鎖
2、合理設計索引,盡量縮小鎖的范圍
3乱投、盡可能減少檢索條件范圍咽笼,避免間隙鎖
4、盡量控制事務大小戚炫,減少鎖定資源量和時間長度剑刑,涉及事務加鎖的sql盡量放在事務最后執(zhí)行
5、盡可能低級別事務隔離
什么是事務
事務是訪問數據庫的一個操作序列双肤,數據庫應用系統(tǒng)通過事務集來完成對數據庫的存取施掏。事務的正確執(zhí)行使得數據庫從一種狀態(tài)轉換為另一種狀態(tài)。
事務必須服從ISO/IEC所制定的ACID原則茅糜。ACID是原子性(atomicity)七芭、一致性(consistency)、隔離性(isolation)限匣、持久性(durability)的縮寫抖苦,這四種狀態(tài)的意思是:
1、原子性
即不可分割米死,事務要么全部被執(zhí)行,要么全部不執(zhí)行贮庞。如果事務的所有子事務全部提交成功峦筒,則所有的數據庫操作被提交,數據庫狀態(tài)發(fā)生變化窗慎;如果有子事務失敗物喷,則其他子事務的數據庫操作被回滾,即數據庫回到事務執(zhí)行前的狀態(tài)遮斥,不會發(fā)生狀態(tài)轉換
2峦失、一致性
事務的執(zhí)行使得數據庫從一種正確狀態(tài)轉換成另外一種正確狀態(tài)
3、隔離性
在事務正確提交之前术吗,不允許把事務對該數據的改變提供給任何其他事務尉辑,即在事務正確提交之前,它可能的結果不應該顯示給其他事務
4较屿、持久性
事務正確提交之后隧魄,其結果將永遠保存在數據庫之中,即使在事務提交之后有了其他故障隘蝎,事務的處理結果也會得到保存购啄。
事務安全性問題:
1、臟寫/讀:無論是臟寫還是臟讀嘱么,都是因為一個事務去更新或者查詢了另外一個還沒提交的事務更新過的數據狮含。因為另外一個事務還沒提交,所以它隨時可能會回滾,那么必然導致你更新的數據就沒了几迄,或者你之前查詢到的數據就沒了蔚龙,這就是臟寫和臟讀兩種場景。
2乓旗、不可重復讀:事務A多次讀取同一數據府蛇,事務B在事務A多次讀取的過程中,對數據做了更新并提交屿愚,導致事務A多次讀取同一數據時汇跨,結果不一致;
3妆距、幻讀:事務A在更新數據時穷遂,事務B插入數據,導致事務A執(zhí)行完發(fā)現數據沒有完全更新娱据。
事務隔離級別
事務隔離級別蚪黑,就是為了解決上面幾種問題而誕生的。為什么要有事務隔離級別中剩,因為事務隔離級別越高忌穿,在并發(fā)下會產生的問題就越少,但同時付出的性能消耗也將越大结啼,因此很多時候必須在并發(fā)性和性能之間做一個權衡掠剑。所以設立了幾種事務隔離級別,以便讓不同的項目可以根據自己項目的并發(fā)情況選擇合適的事務隔離級別郊愧,對于在事務隔離級別之外會產生的并發(fā)問題朴译,在代碼中做補償。
? ?數據庫的事務級別我們可以理解為按照鎖來劃分的属铁。主要有3個鎖的要素:鎖的類型眠寿、鎖的釋放、鎖的范圍焦蘑。
? ? ? 1.鎖的類型:共享鎖盯拱、排他鎖。具體介紹看第一部分
? ? ? 2.鎖的釋放:2.1在操作數據上釋放鎖喇肋。對數據的讀寫操作完成后釋放鎖坟乾,此時如果操作數據的這個事務尚未結束,其他事務是可以繼續(xù)操作數據的蝶防。2.2在操作數據的事務上釋放鎖甚侣。對數據的讀寫操作完成后并未釋放鎖,此時要等操作數據的這個事務結束后间学,其他事務才可以操作這個數據殷费。
? ? ? 3.鎖的范圍:3.1對操作的數據上鎖印荔。操作哪一行數據,就對哪一行數據上鎖详羡。3.2對操作的數據的表上鎖仍律。操作那個表的數據,就對那個表上鎖实柠。
一級:未提交讀(Read uncommitted)
原理:鎖的類型:讀取共享鎖
鎖的釋放:讀取數據結束水泉,釋放鎖
鎖的范圍:對讀取的數據上鎖
引發(fā)的安全性:虛讀,不可重復讀窒盐,幻讀
表現:讀取數據未結束時草则,不釋放鎖,誰都可以讀蟹漓,但是不能寫炕横;讀取數據結束,釋放鎖葡粒,但事務尚未結束的時候份殿,其他事務可以隨意讀寫黔牵,因為此時鎖釋放了俏扩,事務卻沒有結束,所以什么安全性問題都可能引發(fā)淀弹。
二級:已提交讀(Read committed)
原理:鎖的類型:讀取共享鎖夫壁,修改排他鎖
鎖的釋放:讀取數據結束腔寡,釋放鎖
修改數據的事務結束,釋放鎖
鎖的范圍:對操作的數據上鎖
引發(fā)的安全性:不可重復讀掌唾,幻讀
表現:讀取操作和一級事務一致,修改數據的事務在沒有結束時忿磅,所有的事務都不可以修改糯彬,因為此時排它鎖還未釋放。因此解決了臟讀葱她。
三級:可重復讀(Repeatable read)
原理:鎖的類型:讀取共享鎖撩扒,修改排他鎖
鎖的釋放:讀取數據的事務結束,釋放鎖
修改數據的事務結束吨些,釋放鎖
鎖的范圍:對操作的數據上鎖
引發(fā)的安全性:幻讀
表現:讀取數據的事務在沒有結束時搓谆,所有的事務都不可以修改數據,因為此時讀取鎖還未釋放豪墅。修改數據的事務在沒有結束時泉手,所有的事務都不可以修改數據,因為此時排他鎖還未釋放偶器。因此解決了不可重讀
四級:序列化(Serializable)
原理:鎖的類型:讀取共享鎖斩萌,修改排他鎖
鎖的釋放:讀取數據的事務結束缝裤,釋放鎖
修改數據的事務結束,釋放鎖
鎖的范圍:對操作的表上鎖
引發(fā)的安全性:無(至少上述三種安全性)
表現:這個比較好理解颊郎,對表上鎖了憋飞,而且都是讀寫的事務結束以后才釋放鎖,所以要寫的前提是姆吭,先拿到鎖榛做。什么時候能拿到鎖?讀寫數據的事務結束以后内狸。所以能解決目前所知的所有安全性問題检眯。但是這樣的話讀寫效率會很低。
再必須強調一遍答倡,不是事務隔離級別設置得越高越好轰传,事務隔離級別設置得越高,意味著勢必要花手段去加鎖用以保證事務的正確性瘪撇,那么效率就要降低获茬,因此實際開發(fā)中往往要在效率和并發(fā)正確性之間做一個取舍,一般情況下會設置為READ_COMMITED倔既,此時避免了臟讀恕曲,并發(fā)性也還不錯,之后再通過一些別的手段去解決不可重復讀和幻讀的問題就好了渤涌。