1.MYSQL(一)---基礎(chǔ)架構(gòu)(查詢)
2.MYSQL(二)---日志系統(tǒng)(更新)
3.MYSQL(三)---事務(wù)隔離
事務(wù),和數(shù)據(jù)庫(kù)打交道事務(wù)是不可缺少的抵拘,為什么要用事務(wù),最簡(jiǎn)單的案列就是轉(zhuǎn)賬的案例怠惶,A向B轉(zhuǎn)賬100元回季,這個(gè)過(guò)程需要查詢、加減秕重、更新等不同,這個(gè)過(guò)程需要保證是一起的,如果中間出現(xiàn)錯(cuò)誤溶耘,A的100轉(zhuǎn)給了多個(gè)人二拐,這就是不能發(fā)生的事情。而事務(wù)就是要保證這個(gè)過(guò)程凳兵,要么完成百新,就全部完成,否則就全部失敗庐扫。保證數(shù)據(jù)的完整性
在MySQL中饭望,自帶的MyISAM是不支持事務(wù)的,所以我們學(xué)習(xí)都是一INnoDB為準(zhǔn)形庭。
事務(wù)的四大特性ACID
原子性(Atomicity):事務(wù)中的所有操作作為一個(gè)整體像原子一樣不可分割铅辞,要么全部成功,要么全部失敗。
一致性(Consistency):事務(wù)的執(zhí)行結(jié)果必須使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)到另一個(gè)一致性狀態(tài)萨醒。一致性狀態(tài)是指:1.系統(tǒng)的狀態(tài)滿足數(shù)據(jù)的完整性約束(主碼,參照完整性,check約束等) 2.系統(tǒng)的狀態(tài)反應(yīng)數(shù)據(jù)庫(kù)本應(yīng)描述的現(xiàn)實(shí)世界的真實(shí)狀態(tài),比如轉(zhuǎn)賬前后兩個(gè)賬戶的金額總和應(yīng)該保持不變斟珊。
隔離性(Isolation):并發(fā)執(zhí)行的事務(wù)不會(huì)相互影響,其對(duì)數(shù)據(jù)庫(kù)的影響和它們串行執(zhí)行時(shí)一樣。比如多個(gè)用戶同時(shí)往一個(gè)賬戶轉(zhuǎn)賬,最后賬戶的結(jié)果應(yīng)該和他們按先后次序轉(zhuǎn)賬的結(jié)果一樣富纸。
持久性(Durability):事務(wù)一旦提交,其對(duì)數(shù)據(jù)庫(kù)的更新就是持久的囤踩。任何事務(wù)或系統(tǒng)故障都不會(huì)導(dǎo)致數(shù)據(jù)丟失。
其中在開(kāi)始舉例中胜嗓,就是展示數(shù)據(jù)的原子性高职。
我們?cè)谑褂脭?shù)據(jù)庫(kù)的過(guò)程中,導(dǎo)致數(shù)據(jù)出錯(cuò)主要來(lái)自兩個(gè)方面:1.并發(fā)控制2.數(shù)據(jù)庫(kù)故障
其中ACID中辞州,ACI是為了并發(fā)控制怔锌,CID則是為了保證數(shù)據(jù)庫(kù)故障時(shí)候數(shù)據(jù)的不丟失(這就需要上文中的binlog恢復(fù)數(shù)據(jù))。
并發(fā)問(wèn)題導(dǎo)致:臟讀(dirty read)变过、不可重復(fù)讀(non-repeatable read)埃元、幻讀(phantom read)這就需要從隔離級(jí)別來(lái)講。
事務(wù)的隔離和隔離級(jí)別
我們需要知道媚狰,在實(shí)現(xiàn)功能的時(shí)候岛杀,我們控制的越嚴(yán)密,那么效率就會(huì)相對(duì)下降崭孤。這是不可避免的类嗤,所以在事務(wù)的隔離中糊肠,提供了幾種,需要我們自己去選擇遗锣,平衡數(shù)據(jù)和效率之間的關(guān)系货裹。
SQL標(biāo)準(zhǔn)的事務(wù)隔離級(jí)別包括:讀未提交(read uncommitted)、讀已提交(read committed)精偿、可重復(fù)讀(repeatable read)和串行化(serializable )弧圆。
- 讀未提交:在事務(wù)沒(méi)有提交的時(shí)候,它的數(shù)據(jù)更改其能被其他看到
- 讀已提交:在事務(wù)進(jìn)行提交后笔咽,它的變更才能被其他看到
- 可重復(fù)讀:在這個(gè)事務(wù)進(jìn)行的過(guò)程中搔预,所看到的數(shù)據(jù)和事務(wù)啟動(dòng)得時(shí)候是一致的。(這個(gè)過(guò)程叶组,讀未提交也看不到)
-
串行化:對(duì)于一條數(shù)據(jù)拯田,讀寫(xiě)會(huì)分別加“讀鎖”和“寫(xiě)鎖”,當(dāng)出現(xiàn)讀寫(xiě)鎖沖突時(shí)甩十,會(huì)等待一個(gè)事務(wù)執(zhí)行完勿锅,再執(zhí)行另一個(gè)。
這個(gè)過(guò)程可以通過(guò)例子進(jìn)行簡(jiǎn)單實(shí)現(xiàn):
圖片.png
在這個(gè)過(guò)程中枣氧,數(shù)據(jù)庫(kù)里面會(huì)創(chuàng)建一個(gè)視圖,訪問(wèn)的時(shí)候已視圖得邏輯為準(zhǔn)垮刹。 讀未提交直接返回記錄得最新值达吞,沒(méi)有視圖得概念,讀已提交是在開(kāi)始執(zhí)行SQL時(shí)候創(chuàng)建得荒典±医伲可重復(fù)讀是在事務(wù)啟動(dòng)得時(shí)候創(chuàng)建,整個(gè)事務(wù)存在期間都在用這個(gè)視圖寺董,串行化是用鎖機(jī)制來(lái)進(jìn)行隔離的覆糟。
事務(wù)的咖喱級(jí)別必定是和性能息息相關(guān),具體使用哪個(gè)視圖遮咖,肯定是由自己進(jìn)行選擇滩字。
可重復(fù)讀場(chǎng)景:假設(shè)你在管理一個(gè)個(gè)人銀行賬戶表。一個(gè)表存了每個(gè)月月底的余額御吞,一個(gè)表存了賬單明細(xì)麦箍。這時(shí)候你要做數(shù)據(jù)校對(duì),也就是判斷上個(gè)月的余額和當(dāng)前余額的差額陶珠,是否與本月的賬單明細(xì)一致挟裂。你一定希望在校對(duì)過(guò)程中,即使有用戶發(fā)生了一筆新的交易揍诽,也不影響你的校對(duì)結(jié)果诀蓉。
事務(wù)隔離的實(shí)現(xiàn)
以“可重復(fù)讀”為例
在MySQL中栗竖,實(shí)際上每個(gè)記錄在更新的時(shí)候都會(huì)記錄一條回滾操作,記錄上的最新值渠啤,都樂(lè)意通過(guò)回滾操作狐肢,得到前一個(gè)狀態(tài)的值。
系統(tǒng)在記錄值得空間會(huì)不會(huì)一直變大埃篓?答案是处坪,系統(tǒng)會(huì)自動(dòng)在不需要的時(shí)候進(jìn)行刪除。
同時(shí)架专,我們?cè)谑褂玫倪^(guò)程中同窘,盡量避免長(zhǎng)事務(wù)。
長(zhǎng)事務(wù)意味著系統(tǒng)里面會(huì)存在著很老的事務(wù)視圖部脚,由于這些事務(wù)隨時(shí)可能訪問(wèn)數(shù)據(jù)庫(kù)中得任何數(shù)據(jù)想邦,所以在事務(wù)提交之前,數(shù)據(jù)庫(kù)里面它可能用到的會(huì)館記錄都必須保留委刘,就會(huì)導(dǎo)致大量存儲(chǔ)空間丧没。
事務(wù)的啟動(dòng)方式
如上所述,長(zhǎng)事務(wù)會(huì)存在著一些風(fēng)險(xiǎn)锡移,使用的過(guò)程中是盡量避免呕童,但是有時(shí)我們無(wú)意使用到這些長(zhǎng)事務(wù)。MySQL事務(wù)啟動(dòng)有如下:
1.顯式啟動(dòng)事務(wù)語(yǔ)句淆珊,begin或者start transation夺饲。配套的提交語(yǔ)句是commit,回滾語(yǔ)句是rollback。
2.set autocommit=0.這個(gè)命令會(huì)將這個(gè)線程自動(dòng)提交關(guān)閉施符,以為之執(zhí)行select語(yǔ)句就會(huì)啟動(dòng)事務(wù)了往声,而且不會(huì)自動(dòng)提交。這個(gè)事務(wù)會(huì)持續(xù)到主動(dòng)執(zhí)行commit或者rollback戳吝,或者斷開(kāi)鏈接浩销。
有些客戶端在連接的過(guò)程中會(huì)自動(dòng)執(zhí)行 set autocommit=0的命令,這就導(dǎo)致在以后的查詢都在事務(wù)中听哭,如果是長(zhǎng)連接慢洋,就會(huì)導(dǎo)致長(zhǎng)事務(wù)。
但是有時(shí)候就會(huì)擔(dān)心欢唾,主動(dòng)提交的話就會(huì)多一次交互且警,對(duì)于頻繁使用的業(yè)務(wù),第二種方式在開(kāi)始不會(huì)主動(dòng)執(zhí)行一次'begin'礁遣,減少了交互次數(shù)斑芜。如果有這個(gè)顧慮,還是使用commit work and chain語(yǔ)法祟霍。
在autocomit=1的情況下杏头,用begin顯示啟動(dòng)事務(wù)盈包,如果執(zhí)行commit則提交事務(wù)。如果執(zhí)行commit work and chain,則是提交事務(wù)并主動(dòng)啟動(dòng)下一個(gè)事務(wù)醇王,這樣省去可再次執(zhí)行begin的開(kāi)銷呢燥。同時(shí)帶來(lái)的好處就是從程序開(kāi)發(fā)的角度明確的知道每個(gè)語(yǔ)句是否處在事務(wù)中。
可以在informaion_schema庫(kù)中得innodb_trx表中查詢長(zhǎng)事務(wù)寓娩,
比如下面這個(gè)語(yǔ)句叛氨,用于查找持續(xù)時(shí)間超過(guò)60s的事務(wù)。
select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60