MySQL索引
什么是索引
索引是一種數(shù)據(jù)結(jié)構(gòu)睡腿,可以幫助我們快速查找數(shù)據(jù)
MySQL官方對索引的定義為:索引(index)是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)(有序)语御。在數(shù)據(jù)之外,數(shù)據(jù) 庫系統(tǒng)還維護(hù)者滿足特定查找算法的數(shù)據(jù)結(jié)構(gòu)席怪,這些數(shù)據(jù)結(jié)構(gòu)以某種方式引用(指向)數(shù)據(jù)应闯, 這樣就可以在這些數(shù) 據(jù)結(jié)構(gòu)上實(shí)現(xiàn)高級查找算法,這種數(shù)據(jù)結(jié)構(gòu)就是索引挂捻。
索引都有哪些數(shù)據(jù)結(jié)構(gòu)
索引可能有三種數(shù)據(jù)結(jié)構(gòu)哈希表碉纺、有序數(shù)組和N叉樹。MySQL索引使用的是B+樹(InnoDB存儲引擎)
索引的原理
一般來說细层,索引本身也很大惜辑,不可能全部存儲在內(nèi)存中,因此索引往往以索引文件的形式存儲的磁盤上疫赎。這樣的話盛撑,索引查找過程中就要產(chǎn)生磁盤I/O消耗,相對于內(nèi)存存取捧搞,I/O存取的消耗要高幾個(gè)數(shù)量級抵卫,所以評價(jià)一個(gè)數(shù)據(jù)結(jié)構(gòu)作為索引的優(yōu)劣最重要的指標(biāo)就是在查找過程中磁盤I/O操作次數(shù)的漸進(jìn)復(fù)雜度。
換句話說胎撇,索引的結(jié)構(gòu)組織要盡量減少查找過程中磁盤I/O的存取次數(shù)介粘。
索引底層是怎么實(shí)現(xiàn)的
Hash索引
哈希索引是采用一定的哈希算法,將鍵值換算成新的哈希值晚树,映射到對應(yīng)的槽位上姻采,然后存儲在hash表中。
如果兩個(gè)或多個(gè)鍵值爵憎,映射到一個(gè)相同的槽位上慨亲,他們就會產(chǎn)生Hash沖突婚瓜,也叫Hash碰撞,可以通過鏈表來解決刑棵。
Hash索引特點(diǎn)
優(yōu)點(diǎn):
查詢效率高巴刻,在沒有產(chǎn)生hash沖突的情況下,通常只需要一次檢索就可以了蛉签,效率通常要高于B+樹索引胡陪。
缺點(diǎn):
1.Hash索引只能用于對等比較(=,in)碍舍,不支持范圍查詢(between柠座,>,<,…)乒验,即無法進(jìn)行大小比較
2.無法利用索引完成排序操作(Hash索引是無序排列的)
存儲引擎支持
在MySQL中愚隧,支持hash索引的是Memory引擎,而InnoDB中具有自適應(yīng)hash功能(利用方法將b+樹索引轉(zhuǎn)化為hash索引)锻全,hash索引是存儲引擎根據(jù)B+Tree索引在指定條件下自動構(gòu)建的。
二叉樹索引
二叉樹索引分為左子樹录煤,右子樹鳄厌,根節(jié)點(diǎn),左子樹要比根節(jié)點(diǎn)小妈踊,右子樹要比根節(jié)點(diǎn)大
二叉樹缺點(diǎn):順序插入時(shí)了嚎,會形成一個(gè)鏈表(如右圖),查詢性能大大降低廊营。很多數(shù)據(jù)量的情況下歪泳,層次較深,檢索速度慢露筒。
平衡二叉樹
特點(diǎn):
它的左子樹和右子樹都是平衡二叉樹
左子樹比中間小呐伞,右子樹比中間值大
左子樹和右子樹的深度之差的絕對值不超過1
缺點(diǎn):
a、插入操作需要旋轉(zhuǎn)
b慎式、支持范圍查詢伶氢,但回旋查詢效率較低,比如要查找大于8的瘪吏,會回旋到父節(jié)點(diǎn)7癣防、10。
c掌眠、如果存放幾百條數(shù)據(jù)的情況下蕾盯,樹高度越高,查詢效率會越慢
B樹(多路平衡查找樹)
B樹:葉子節(jié)點(diǎn)和非葉子節(jié)點(diǎn)都存儲數(shù)據(jù)蓝丙,數(shù)據(jù)結(jié)構(gòu)為有序數(shù)組+平衡多叉樹级遭,也叫b-樹望拖。
m為樹的叉數(shù)
每個(gè)節(jié)點(diǎn)最多有m-1個(gè)關(guān)鍵字(可以存有的鍵值對)。
根節(jié)點(diǎn)最少可以只有1個(gè)關(guān)鍵字装畅。
非根節(jié)點(diǎn)至少有m/2個(gè)關(guān)鍵字靠娱。
每個(gè)節(jié)點(diǎn)中的關(guān)鍵字都按照從小到大的順序排列,每個(gè)關(guān)鍵字的左子樹中的所有關(guān)鍵字都小于它掠兄,而右子樹中的所有關(guān)鍵字都大于它像云。
所有葉子節(jié)點(diǎn)都位于同一層,或者說根節(jié)點(diǎn)到每個(gè)葉子節(jié)點(diǎn)的長度都相同蚂夕。每個(gè)節(jié)點(diǎn)都存有索引和數(shù)據(jù)迅诬,也就是對應(yīng)的key和value。
b樹優(yōu)點(diǎn): 二叉平衡樹的基礎(chǔ)上婿牍,使加載一次節(jié)點(diǎn)侈贷,可以加載更多路徑數(shù)據(jù),同時(shí)把查詢范圍縮減到更小
樹的每一個(gè)節(jié)點(diǎn)都包含key和value等脂。
所以俏蛮,經(jīng)常訪問的元素可能離根節(jié)點(diǎn)更近,把頻繁訪問的數(shù)據(jù)放在靠近根節(jié)點(diǎn)的地方將會大大提高熱點(diǎn)數(shù)據(jù)的查詢效率上遥。
缺點(diǎn): 業(yè)務(wù)數(shù)據(jù)的大小可能遠(yuǎn)遠(yuǎn)超過了索引數(shù)據(jù)的大小搏屑,每次為了查找對比計(jì)算,需要把數(shù)據(jù)加載到內(nèi)存以及 CPU 高速緩存中時(shí)粉楚,都要把索引數(shù)據(jù)和無關(guān)的業(yè)務(wù)數(shù)據(jù)全部查出來辣恋。本來一次就可以把所有索引數(shù)據(jù)加載進(jìn)來,現(xiàn)在卻要多次才能加載完模软。如果所對比的節(jié)點(diǎn)不是所查的數(shù)據(jù)伟骨,那么這些加載進(jìn)內(nèi)存的業(yè)務(wù)數(shù)據(jù)就毫無用處,全部拋棄燃异。
B+樹
以m階B+樹為例
一個(gè)m階的B+樹具有如下幾個(gè)特征:
有k個(gè)子樹的中間節(jié)點(diǎn)包含有k個(gè)元素(B樹中是k-1個(gè)元素)携狭,每個(gè)元素不保存數(shù)據(jù),只用來索引特铝,所有數(shù)據(jù)都保存在葉子節(jié)點(diǎn)暑中。
所有的葉子結(jié)點(diǎn)中包含了全部元素的信息,及指向含這些元素記錄的指針鲫剿,且葉子結(jié)點(diǎn)本身依關(guān)鍵字的大小自小而大順序鏈接鳄逾。
所有的中間節(jié)點(diǎn)元素都同時(shí)存在于子節(jié)點(diǎn),在子節(jié)點(diǎn)元素中是最大(或最辛榱)元素雕凹。
B+樹只有葉子節(jié)點(diǎn)存儲數(shù)據(jù)(B+數(shù)中有兩個(gè)頭指針:一個(gè)指向根節(jié)點(diǎn),另一個(gè)指向關(guān)鍵字最小的葉節(jié)點(diǎn)),葉子節(jié)點(diǎn)包含了這棵樹的所有數(shù)據(jù)枚抵,所有的葉子結(jié)點(diǎn)使用鏈表相連线欲,便于區(qū)間查找和遍歷,所有非葉節(jié)點(diǎn)起到索引作用
B+樹優(yōu)于B樹原因
b+樹的中間節(jié)點(diǎn)不保存數(shù)據(jù)汽摹,可以容納更多的節(jié)點(diǎn)元素
所有的葉子結(jié)點(diǎn)使用鏈表相連李丰,有助于區(qū)間查找和遍歷
B+樹的內(nèi)部節(jié)點(diǎn)只存放鍵,不存放值逼泣,因此趴泌,一次讀取,可以在內(nèi)存頁中獲取更多的鍵拉庶,有利于更快地縮小查找范圍嗜憔。 B+樹的葉節(jié)點(diǎn)由一條鏈相連,因此氏仗,當(dāng)需要進(jìn)行一次全數(shù)據(jù)遍歷的時(shí)候吉捶,B+樹只需要使用O(logN)時(shí)間找到最小的一個(gè)節(jié)點(diǎn),然后通過鏈進(jìn)行O(N)的順序遍歷即可皆尔。而B樹則需要對樹的每一層進(jìn)行遍歷呐舔,這會需要更多的內(nèi)存置換次數(shù),因此也就需要花費(fèi)更多的時(shí)間
B樹的話慷蠕,就需要進(jìn)行每一層的遞歸遍歷
相鄰的元素可能在內(nèi)存中不相鄰滋早,所以緩存命中性沒有B+樹好
什么是覆蓋索引
索引是高效找到行的一個(gè)方法,但是一般數(shù)據(jù)庫也能使用索引找到一個(gè)列的數(shù)據(jù)砌们,因此它不必讀取整個(gè)行。b+索引葉子節(jié)點(diǎn)存儲了它們索引的數(shù)據(jù)搁进;當(dāng)能通過讀取索引就可以得到想要的數(shù)據(jù)浪感,那就不需要讀取行了。一個(gè)索引包含了(或覆蓋了)滿足查詢結(jié)果的數(shù)據(jù)就叫做覆蓋索引饼问。
1.覆蓋索引是一種數(shù)據(jù)查詢方式影兽,不是索引類型
2.在索引數(shù)據(jù)結(jié)構(gòu)中,通過索引值可以直接找到要查詢字段的值莱革,而不需要通過主鍵值回表查詢峻堰,那么就叫覆蓋索引
3.查詢的字段被使用到的索引樹全部覆蓋到
舉個(gè)栗子:
在上圖中,id為主鍵索引盅视,name為唯一索引
假如你執(zhí)行命令
select id,name from eclass where id=1;
此時(shí)由于id和name字段都在索引樹中捐名,所以這就是覆蓋索引查詢
什么是聚簇索引
聚簇索引是物理索引,數(shù)據(jù)表就是按順序存儲的闹击,物理上是連續(xù)的镶蹋。
一般情況下主鍵會默認(rèn)創(chuàng)建聚簇索引
將索引與數(shù)據(jù)放在一起,當(dāng)你找到索引后,也就找到對應(yīng)的數(shù)據(jù)了贺归。每張表只能建立一個(gè)聚簇索引淆两,但是該索引可以包含多個(gè)列(一般使用的是主鍵等不經(jīng)常更新的列)
非聚簇索引:數(shù)據(jù)儲存于索引分開,葉節(jié)點(diǎn)指向了對應(yīng)的數(shù)據(jù)行拂酣。輔助索引訪問數(shù)據(jù)時(shí)需要二次查找秋冰。輔助索引存儲的不是行的物理位置,而是主鍵的值婶熬。而通過輔助索引首先找到的就是主鍵的值剑勾,再通過主鍵的值找到數(shù)據(jù)行對應(yīng)的數(shù)據(jù)頁,最后才能找到對應(yīng)行尸诽。
聯(lián)合索引
我們都知道索引的底層是一顆B+樹甥材,那么聯(lián)合索引當(dāng)然還是一顆B+樹,只不過聯(lián)合索引的健值數(shù)量不是一個(gè)性含,而是多個(gè)洲赵。構(gòu)建一顆B+樹只能根據(jù)一個(gè)值來構(gòu)建,因此數(shù)據(jù)庫依據(jù)聯(lián)合索引最左的字段來構(gòu)建B+樹商蕴。使用聯(lián)合索引叠萍,如果想要命中索引,需要按照建立索引時(shí)的字段順序挨個(gè)使用绪商,否則無法命中索引苛谷。。
最左匹配原則
顧名思義:最左優(yōu)先格郁,以最左邊的為起點(diǎn)任何連續(xù)的索引都能匹配上腹殿。同時(shí)遇到范圍查詢(>、<例书、between锣尉、like)就會停?匹配。
mysql創(chuàng)建復(fù)合索引的規(guī)則是?先對復(fù)合索引最左邊的字段的數(shù)據(jù)進(jìn)?排序决采,在此基礎(chǔ)上自沧,再對后?的字段進(jìn)?排序,這樣第?個(gè)字段是絕對有序的树瞭,后?的字段就是?序的了拇厢,?般情況下第?個(gè)字段進(jìn)?條件判斷是?不到索引的,可能出現(xiàn)type是index類型的晒喷,這就是mysql 最左前綴的原因孝偎。
舉個(gè)栗子:假設(shè)創(chuàng)建了順序?yàn)椋╝,b厨埋,c)的索引
1.當(dāng)查詢條件為a=1 and b=1 或b=1 and a=1(查詢優(yōu)化器會調(diào)換a與b的位置)邪媳,這時(shí)候都可以走索引捐顷。
當(dāng)查詢條件為a=1 and b>1 and c=1 時(shí) ,由于是范圍查找雨效,a和b走索引迅涮,c不走索引
創(chuàng)建索引的原則
創(chuàng)建索引,肯定是有利于我們的查詢效率的徽龟,如果無效地創(chuàng)建索引叮姑,只會浪費(fèi)我們的內(nèi)存和執(zhí)行程序的效率,因此創(chuàng)建索引是有原則的
首先應(yīng)考慮對where 和 order by 涉及到的列上建立索引
對一個(gè)存在大量更新操作的表据悔,所建索引的數(shù)目一般不超過3個(gè)传透,最多不超過5個(gè),索引雖說提高了訪問速度极颓,但太多索引會影響數(shù)據(jù)的更新操作,并且索引本身會占用存儲空間朱盐。
建立唯一索引。唯一索引能夠更快速地幫助我們進(jìn)行數(shù)據(jù)定位菠隆;
為經(jīng)常需要進(jìn)行查詢操作的字段建立索引兵琳;
更新頻繁的列不宜設(shè)置索引,索引列不能參與計(jì)算
數(shù)據(jù)量小的表不要使用索引
重復(fù)數(shù)據(jù)多的字段不宜設(shè)置索引骇径,如性別男和女躯肌。
在建立索引的時(shí)候,要考慮索引的最左匹配原則(在使用SQL語句時(shí)破衔,如果where部分的條件不符合最左匹配原則清女,可能導(dǎo)致索引失效,或者不能完全發(fā)揮建立的索引的功效)晰筛;
如果建立的單個(gè)索引查詢數(shù)據(jù)很多嫡丙,查詢得到的數(shù)據(jù)的區(qū)分度不大,則考慮建立合適的聯(lián)合索引读第;
盡量考慮字段值長度較短的字段建立索引迄沫,如果字段值太長,會降低索引的效率
創(chuàng)建索引的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
1.大大加快數(shù)據(jù)的查詢速度
2.使用分組和排序進(jìn)行數(shù)據(jù)查詢時(shí)卦方,可以顯著減少查詢時(shí)分組和排序的時(shí)間
3.創(chuàng)建唯一索引,能夠保證數(shù)據(jù)庫表中每一行數(shù)據(jù)的唯一性
4.在實(shí)現(xiàn)數(shù)據(jù)的參考完整性方面泰佳,可以加速表和表之間的連接
5.通過使用索引盼砍,可以在查詢的過程中,使用優(yōu)化隱藏器逝她,提高系統(tǒng)的性能浇坐。
缺點(diǎn)
1.創(chuàng)建索引和維護(hù)索引需要消耗時(shí)間并且隨著數(shù)據(jù)量的增加,時(shí)間也會增加
索引需要占據(jù)磁盤空間
2.對數(shù)據(jù)表中的數(shù)據(jù)進(jìn)行增加黔宛,修改近刘,刪除時(shí),索引也要?jiǎng)討B(tài)的維護(hù),降低了維護(hù)的速度
MySQL存儲引擎
數(shù)據(jù)庫存儲引擎是數(shù)據(jù)庫底層軟件組織觉渴,數(shù)據(jù)庫管理系統(tǒng)(DBMS)使用數(shù)據(jù)引擎進(jìn)行創(chuàng)建介劫、查詢、更新和刪除數(shù)據(jù)案淋。
不同的存儲引擎提供不同的存儲機(jī)制座韵、索引技巧、鎖定水平等功能√呔現(xiàn)在許多不同的數(shù)據(jù)庫管理系統(tǒng)都支持多種不同的數(shù)據(jù)引擎誉碴。MySQL的核心就是存儲引擎。
用戶可以根據(jù)不同的需求為數(shù)據(jù)表選擇不同的存儲引擎
可以使用 SHOW ENGINES命令 可以查看Mysql的所有執(zhí)行引擎我們 可以到默認(rèn)的執(zhí)行引擎是innoDB支持事務(wù)瓣距,行級鎖定和外鍵黔帕。
MySQL默認(rèn)的存儲引擎是InnoDB。
分類
1.MylSAM:Mysql 5.5之前的默認(rèn)數(shù)據(jù)庫引擎蹈丸,最為常用成黄。擁有較高的插入,查詢速度白华,但不支持事務(wù)
2.InnoDB:事務(wù)型速記的首選引擎慨默,支持ACID事務(wù),支持行級鎖定弧腥,MySQL5.5成為默認(rèn)數(shù)據(jù)庫引擎
3.Memory:所有數(shù)據(jù)置于內(nèi)存的存儲引擎厦取,擁有極高的插入,更新和查詢效率管搪。但是會占用和數(shù)據(jù)量成正比的內(nèi)存空間虾攻。并且其內(nèi)容會在MYSQL重新啟動是會丟失。
4.Archive:非常適合存儲大量的獨(dú)立的更鲁,作為歷史記錄的數(shù)據(jù)霎箍。因?yàn)樗鼈儾唤?jīng)常被讀取。5.Archive擁有高效的插入速度澡为,但其對查詢的支持相對較差
6.Federated:將不同的MySQL服務(wù)器聯(lián)合起來漂坏,邏輯上組成一個(gè)完整的數(shù)據(jù)庫。非常適合分布式應(yīng)用
7.CSV:邏輯上由逗號分割數(shù)據(jù)的存儲引擎媒至。它會在數(shù)據(jù)庫子目錄里為每個(gè)數(shù)據(jù)表創(chuàng)建一個(gè).csv文件顶别。這是一種普通文本文件,每個(gè)數(shù)據(jù)行占用一個(gè)文本行拒啰。CSV存儲引擎不支持索引驯绎。
8.BlackHole:黑洞引擎谋旦,寫入的任何數(shù)據(jù)都會消失脾歧,一般用于記錄 binlog做復(fù)制的中繼
ERFORMANCE_SCHEMA存儲引擎該引擎主要用于收集數(shù)據(jù)庫服務(wù)器性能參數(shù)蚕冬。
9.Mrg_Myisam Merge存儲引擎获三,是一組Mylsam的組合,也就是說,他將Mylsam引擎的多個(gè)表聚合起來,但是他的內(nèi)部沒有數(shù)據(jù)窖贤,真正的數(shù)據(jù)依然是Mylsam引擎的表中,但是可以直接進(jìn)行查詢粤攒、刪除更新等操作。
InnoDB 和 MylSAM存儲引擎區(qū)別
1.InnoDB支持事務(wù)逊拍,MyISAM不支持谴咸,這一點(diǎn)是非常之重要珊随。事務(wù)是一種高級的處理方式驹暑,如在一些列增刪改中只要哪個(gè)出錯(cuò)還可以回滾還原玫恳,而MyISAM就不可以了。
2.MyISAM適合查詢以及插入為主的應(yīng)用优俘,InnoDB適合頻繁修改以及涉及到安全性較高的應(yīng)用
InnoDB支持外鍵京办,MyISAM不支持
3.從MySQL5.5.5以后,InnoDB是默認(rèn)引擎
4.InnoDB不支持FULLTEXT類型的索引
5.InnoDB中不保存表的行數(shù)帆焕,如select count() from table時(shí)惭婿,InnoDB需要掃描一遍整個(gè)表來計(jì)6.算有多少行,但是MyISAM只要簡單的讀出保存好的行數(shù)即可叶雹。注意的是财饥,當(dāng)count()語句包含where條件時(shí)MyISAM也需要掃描整個(gè)表
7.對于自增長的字段,InnoDB中必須包含只有該字段的索引折晦,但是在MyISAM表中可以和其他字段一起建立聯(lián)合索引
8.清空整個(gè)表時(shí)钥星,InnoDB是一行一行的刪除,效率非常慢满着。MyISAM則會重建表
9.InnoDB支持行鎖(某些情況下還是鎖整表)
圖片表示
MySQL事務(wù)
什么是事務(wù)
在MySQL中的事務(wù)Transaction是由存儲引擎實(shí)現(xiàn)的谦炒,在MySQL中贯莺,只有InnoDB存儲引擎才支持事務(wù)。
事務(wù)處理可以用來維護(hù)數(shù)據(jù)庫的完整性宁改,保證成批的SQL語句要么全部執(zhí)行粪摘,要么全部不執(zhí)行屹徘。事務(wù)用來管理DDL淮菠、DML奔滑、DCL操作,比如insert谜喊,update潭兽,delete語句,默認(rèn)是自動提交的锅论。
事務(wù)操作
開啟事務(wù):Start Transaction
任何一條DML語句(insert讼溺、update、delete)執(zhí)行最易,標(biāo)志事務(wù)的開啟命令:BEGIN或 START TRANSACTION
提交事務(wù):Commit Transaction
成功的結(jié)束怒坯,將所有的DML語句操作歷史記錄和底層硬盤數(shù)據(jù)來一次同步命令:COMMIT
回滾事務(wù):Rollback Transaction
失敗的結(jié)束,將所有的DML語句操作歷史記錄全部清空
命令:ROLLBACK
set autocommit =0 禁止自動提交事務(wù)
set autocommit =1 開啟自動提交事務(wù)
事務(wù)的特性
1.原子性(Atomicity):事務(wù)是一個(gè)不可分割的整體藻懒,事務(wù)開始后的所有操作剔猿,要么全部完
成,要么全部不做
2.一致性(Consistency):系統(tǒng)從一個(gè)正確的狀態(tài)嬉荆,遷移到另一個(gè)正確的狀態(tài)
3.隔離性(Isolation):每個(gè)事務(wù)的對象對其他事務(wù)的操作對象互相分離归敬,事務(wù)提交前對其
他事務(wù)不可見
4.持久性(Durability):事務(wù)一旦提交,則其結(jié)果是永久性的
事務(wù)的隔離級別
讀未提交(Read uncommitted)
一個(gè)事務(wù)可以讀取另一個(gè)未提交事務(wù)的數(shù)據(jù)鄙早,最低級別汪茧,任何情況都無法保證,會造成臟讀限番。
讀已提交(Read committed)
一個(gè)事務(wù)要等另一個(gè)事務(wù)提交后才能讀取數(shù)據(jù)舱污,可避免臟讀的發(fā)生,會造成不可重復(fù)讀弥虐。
可重復(fù)讀(Repeatable read) I
就是在開始讀取數(shù)據(jù)(事務(wù)開啟)時(shí)扩灯,不再允許修改操作,可避免臟讀霜瘪、不可重復(fù)讀的發(fā)生珠插,但是會造成幻讀。
串行(Serializable)
是最高的事務(wù)隔離級別颖对,在該級別下捻撑,事務(wù)串行化順序執(zhí)行,可以避免臟讀、不可重復(fù)讀與幻讀顾患。但是這種事務(wù)隔離級別效率低下琳拭,比較耗數(shù)據(jù)庫性能,一般不使用描验。
Mysql的默認(rèn)隔離級別是Repeatable read (可重復(fù)讀)。
1.臟讀:強(qiáng)調(diào)的是第二個(gè)事務(wù)讀到的數(shù)據(jù)不夠新
栗子:假設(shè)老板今天給你發(fā)這個(gè)月的工資坑鱼,本來要給你發(fā)2w元膘流,結(jié)果手一抖發(fā)了20w元,這時(shí)老板還沒有提交事務(wù)鲁沥,而你查詢到你的賬戶里多了20w元呼股,老板總覺得不對勁,總感覺少了些什么画恰,最后發(fā)現(xiàn)后回滾事務(wù)彭谁,給你發(fā)了2w,然后這時(shí)你打開賬戶發(fā)現(xiàn)只有2w塊錢允扇。
2.不可重復(fù)讀:同一事務(wù)缠局,兩次讀取到的數(shù)據(jù)不一樣
栗子:前提同第一個(gè),老板給你發(fā)了2w元工資考润,你看到賬戶里多了2w塊錢狭园,此時(shí)老板覺得你這個(gè)月做的還不錯(cuò),給你加了1w塊錢獎(jiǎng)勵(lì)金并提交了事務(wù)糊治,而此時(shí)你再次查詢時(shí)發(fā)現(xiàn)是3w塊錢唱矛,這就造成了在一個(gè)事務(wù)中讀取到的事務(wù)不一致。
3.幻讀:重點(diǎn)在于新增或刪除井辜,同樣的條件绎谦,第一次和第二次讀出來的記錄數(shù)不一樣
栗子:和你相同薪資的人有10人,此時(shí)讀數(shù)據(jù)讀到的事務(wù)為10人粥脚,此時(shí)突然增加了一條工資和你們一樣的人窃肠,提交事務(wù)后記錄為11人,因此產(chǎn)生了幻讀阿逃。
MySQL 鎖機(jī)制
鎖是計(jì)算機(jī)協(xié)調(diào)多個(gè)進(jìn)程或線程并發(fā)訪問某一資源的機(jī)制(避免爭搶)铭拧。
在數(shù)據(jù)庫中,除傳統(tǒng)的計(jì)算資源(如CPU恃锉、RAM搀菩、I/O等)的爭用以外,數(shù)據(jù)也是一種供許多用戶共享的資如何保證數(shù)據(jù)并發(fā)訪問的一致性破托、有效性是所有數(shù)據(jù)庫必須解決的一個(gè)問題肪跋,鎖沖突也是影響數(shù)據(jù)庫并發(fā)訪問性能的一個(gè)重要因素。從這個(gè)角度來說土砂,鎖對數(shù)據(jù)庫而言顯得尤其重要州既,也更加復(fù)雜谜洽。
從對數(shù)據(jù)操作的粒度分:
1.表鎖:操作時(shí),會鎖定整個(gè)表吴叶。
2.行鎖:操作時(shí)阐虚,會鎖定當(dāng)前操作行。
從對數(shù)據(jù)操作的類型分:
1.讀鎖(共享鎖):針對同一份數(shù)據(jù)蚌卤,多個(gè)讀操作可以同時(shí)進(jìn)行而不會互相影響实束。
2.寫鎖(排它鎖):當(dāng)前操作沒有完成之前,它會阻斷其他寫鎖和讀鎖逊彭。
其中咸灿,InnoDB表鎖和行鎖都支持,而MyISAM只支持表鎖
MySQL鎖的特性
表級鎖 偏向MyISAM存儲引擎侮叮,開銷小避矢,加鎖快不會出現(xiàn)死鎖:鎖定粒度大,發(fā)生鎖沖突的概率最高囊榜,并發(fā)度最低审胸。
行級鎖 偏向InnoDB存儲引擎,開銷大锦聊,加鎖慢歹嘹;會出現(xiàn)死;鎖定粒度最小孔庭,發(fā)生鎖沖突的概率最低尺上,并發(fā)度也最高。
從上述特點(diǎn)可見圆到,很難籠統(tǒng)地說哪種鎖更好怎抛,只能就具體應(yīng)用的特點(diǎn)來說哪種鎖更合適!僅從鎖的角度來說:表級鎖更適合于以查詢?yōu)橹餮康挥猩倭堪此饕龡l件更新數(shù)據(jù)的應(yīng)用马绝,如Web應(yīng)用;
而行級鎖則更適合于有大量按索引條件并發(fā)更新少量不同數(shù)據(jù)挣菲,同時(shí)又有并查詢的應(yīng)用富稻,如一些在線事務(wù)處理(OLTP)系統(tǒng)。
如何加鎖
MyISAM表鎖
MyISAM存儲引擎只支持表鎖
如何加表鎖
MyISAM在執(zhí)行查詢語句(SELECT)前白胀,會自動給涉及的所有表加讀鎖椭赋,在執(zhí)行更新操作(UPDATE、DELETE或杠、INSERT等)前哪怔,會自動給涉及的表加寫鎖,這個(gè)過程并不需要用戶干預(yù),因此认境,用戶一般不需要直接用LOCK TABLE 命令給MyISAM表顯式加鎖胚委。
加讀鎖: lock table table_name read;
加寫鎖:lock table table_name write;
InnoDB行鎖:
行鎖特點(diǎn):偏向InnoDB存儲引擎,開銷大叉信,加鎖慢亩冬;會出現(xiàn)死鎖;鎖定粒度最小硼身,發(fā)生鎖沖突的概率最低鉴未,并發(fā)度也最高。
InnoDB與MyISAM的最大不同有兩點(diǎn):一是支持事務(wù)鸠姨;二是采用了行級鎖。
行鎖模式:
InnoDB 實(shí)現(xiàn)了以下兩種類型的行鎖淹真。
共享鎖(S) 又稱為讀鎖讶迁,簡稱S鎖,共享鎖就是多個(gè)事務(wù)對于同一數(shù)據(jù)可以共享一把鎖核蘸,都能訪問到數(shù)據(jù)巍糯,但是只能讀不能修改。
排他鎖(X) 又稱為寫鎖客扎,簡稱x鎖祟峦,排他鎖就是不能與其他鎖并存,如一個(gè)事務(wù)獲取了一個(gè)數(shù)據(jù)行的排他鎖徙鱼,其他事務(wù)就不能再獲取該行的其他鎖宅楞,包括共享鎖和排他鎖,但是獲取排他鎖的事務(wù)是可以對數(shù)據(jù)就行讀取和修改袱吆。
對于UPDATE厌衙、DELETE和INSERT語句,InnoDB會自動給涉及數(shù)據(jù)集加排他鎖(X)绞绒;
對于普通SELECT語句婶希,InnoDB不會加任何鎖;
共享鎖(S):SELECT ★ FROM table name WHERE ... LOCK IN SHARE MODE
排他鎖(X):SELECT ★ FROM table name WHERE ... FOR UPDATE
死鎖
死鎖是指兩個(gè)或多個(gè)事務(wù)在同一資源上相互占用蓬衡,并請求鎖定對方的資源喻杈,從而導(dǎo)致惡性循環(huán)的現(xiàn)象。
常見的解決死鎖的方法
1.如果不同程序會并發(fā)存取多個(gè)表狰晚,盡量約定以相同的順序訪問表筒饰,可以大大降低死鎖機(jī)會。
2.在同一個(gè)事務(wù)中家肯,盡可能做到一次鎖定所需要的所有資源龄砰,減少死鎖產(chǎn)生概率;
3.對于非常容易產(chǎn)生死鎖的業(yè)務(wù)部分,可以嘗試使用升級鎖定顆粒度换棚,通過表級鎖定來減少死鎖產(chǎn)生的概率式镐;