MSQL常见面试问题
Mysql
一、數(shù)據(jù)庫(kù)基礎(chǔ)
1.1 sql 語(yǔ)句
1.2 數(shù)據(jù)庫(kù)優(yōu)化
SQL 優(yōu)化
1、我們?cè)谶M(jìn)行數(shù)據(jù)庫(kù)查詢時(shí)首先應(yīng)該避免的是全表掃描,限定數(shù)據(jù)的范圍。比如查詢某一段時(shí)間的數(shù)據(jù)。 ? 2、對(duì)于使用where 或者 order by 的列,我們應(yīng)該建立索引。 ? 3、通過(guò)explain顯示了mysql如何使用索引來(lái)處理select語(yǔ)句以及連接表,可以幫助選擇更好的索引和寫(xiě)出更優(yōu)化的查詢語(yǔ)句。 ? 4、同時(shí)也應(yīng)該避免一些索引失效的問(wèn)題。 ? 5、更多的時(shí)候是需要用到一系列的語(yǔ)句來(lái)完成某種工作。在這種情況下,當(dāng)這個(gè)語(yǔ)句塊中的某一條語(yǔ)句運(yùn)行出錯(cuò)的時(shí)候,整個(gè)語(yǔ)句塊的操作就會(huì)變得不確定起來(lái)。要避免這種情況,就應(yīng)該使用事務(wù)。 ?數(shù)據(jù)庫(kù)優(yōu)化
當(dāng)MySQL單表記錄數(shù)過(guò)大時(shí),數(shù)據(jù)庫(kù)的CRUD性能會(huì)明顯下降,一些常見(jiàn)的優(yōu)化措施如下:1、讀/寫(xiě)分離:通過(guò)主從復(fù)制實(shí)現(xiàn)讀寫(xiě)分離,主庫(kù)負(fù)責(zé)寫(xiě),從庫(kù)負(fù)責(zé)讀;2、緩存:使用MySQL的緩存,另外對(duì)重量級(jí)、更新少的數(shù)據(jù)可以考慮使用應(yīng)用級(jí)別的緩存;3、通過(guò)分庫(kù)分表的方式進(jìn)行優(yōu)化,主要有垂直分表和水平分表1.3 數(shù)據(jù)庫(kù)范式
1、第一范式:屬性不可分割,每個(gè)字段都應(yīng)該是不可再拆分的。比如一個(gè)字段是姓名(NAME)。 ? 2、第二范式:在第一范式的基礎(chǔ)之上更進(jìn)一層。第二范式需要確保數(shù)據(jù)庫(kù)表中的每一列都和主鍵相關(guān),而不能只與主鍵的某一部分相關(guān)(主要針對(duì)聯(lián)合主鍵而言)記住主鍵約束 3、第三范式:第三范式需要確保數(shù)據(jù)表中的每一列數(shù)據(jù)都和主鍵直接相關(guān),而不能間接相關(guān)。外鍵約束比如在設(shè)計(jì)一個(gè)訂單數(shù)據(jù)表的時(shí)候,可以將客戶編號(hào)作為一個(gè)外鍵和訂單表建立相應(yīng)的關(guān)系。而不可以在訂單表中添加關(guān)于客戶其它信息(比如姓名、所屬公司等)的字段。如下面這兩個(gè)表所示的設(shè)計(jì)就是一個(gè)滿足第三范式的數(shù)據(jù)庫(kù)表。1.4 分庫(kù)分表
垂直拆分 垂直分表:也就是“大表拆小表”,基于列字段進(jìn)行的。一般是表中的字段較多,將不常用的,數(shù)據(jù)較大,長(zhǎng)度較長(zhǎng)的拆分到“擴(kuò)展表“。一般是針對(duì)那種幾百列的大表,也避免查詢時(shí),數(shù)據(jù)量太大造成的“跨頁(yè)”問(wèn)題。 ?垂直分庫(kù):針對(duì)的是一個(gè)系統(tǒng)中的不同業(yè)務(wù)進(jìn)行拆分,比如用戶User一個(gè)庫(kù),商品Producet一個(gè)庫(kù),訂單Order一個(gè)庫(kù)。 切分后,要放在多個(gè)服務(wù)器上,而不是一個(gè)服務(wù)器上。 為什么?我們想象一下,一個(gè)購(gòu)物網(wǎng)站對(duì)外提供服務(wù),會(huì)有用戶,商品,訂單等的CRUD。沒(méi)拆分之前,全部都是落到單一的庫(kù)上的,這會(huì)讓數(shù)據(jù)庫(kù)的單庫(kù)處理能力成為瓶頸。按垂直分庫(kù)后,如果還是放在一個(gè)數(shù)據(jù)庫(kù)服務(wù)器上,隨著用戶量增大,這會(huì)讓單個(gè)數(shù)據(jù)庫(kù)的處理能力成為瓶頸,還有單個(gè)服務(wù)器的磁盤(pán)空間,內(nèi)存,tps等非常吃緊。所以我們要拆分到多個(gè)服務(wù)器上,這樣上面的問(wèn)題都解決了,以后也不會(huì)面對(duì)單機(jī)資源問(wèn)題。 ? 水平拆分水平分表:針對(duì)數(shù)據(jù)量巨大的單張表(比如訂單表),按照某種規(guī)則(RANGE,HASH取模等),切分到多張表里面去。但是這些表還是在同一個(gè)庫(kù)中,所以庫(kù)級(jí)別的數(shù)據(jù)庫(kù)操作還是有IO瓶頸。不建議采用。 ?水平分庫(kù):將單張表的數(shù)據(jù)切分到多個(gè)服務(wù)器上去,每個(gè)服務(wù)器具有相應(yīng)的庫(kù)與表,只是表中數(shù)據(jù)集合不同。水平分庫(kù)分表能夠有效的緩解單機(jī)和單庫(kù)的性能瓶頸和壓力,突破IO、連接數(shù)、硬件資源等的瓶頸。 ? 水平分庫(kù)分表切分規(guī)則 ? 1、RANGE:從0到10000一個(gè)表,10001到20000一個(gè)表; 2、HASH取模:一個(gè)商場(chǎng)系統(tǒng),一般都是將用戶,訂單作為主表,然后將和它們相關(guān)的作為附表,這樣不會(huì)造成跨庫(kù)事務(wù)之類的問(wèn)題。 取用戶id,然后hash取模,分配到不同的數(shù)據(jù)庫(kù)上。 3、地理區(qū)域:比如按照華東,華南,華北這樣來(lái)區(qū)分業(yè)務(wù),七牛云應(yīng)該就是如此。 4、時(shí)間:按照時(shí)間切分,就是將6個(gè)月前,甚至一年前的數(shù)據(jù)切出去放到另外的一張表,因?yàn)殡S著時(shí)間流逝,這些表的數(shù)據(jù) 被查詢的概率變小,所以沒(méi)必要和“熱數(shù)據(jù)”放在一起,這個(gè)也是“冷熱數(shù)據(jù)分離”。 ? ? ? 分庫(kù)分表后引入的問(wèn)題: 1、分布式事務(wù)問(wèn)題 ? 如果我們做了垂直分庫(kù)或者水平分庫(kù)以后,就必然會(huì)涉及到跨庫(kù)執(zhí)行SQL的問(wèn)題,這樣就引發(fā)了互聯(lián)網(wǎng)界的老大難問(wèn)題-"分布式事務(wù)"。 ? 2、跨庫(kù)join的問(wèn)題 ?分庫(kù)分表后表之間的關(guān)聯(lián)操作將受到限制,我們無(wú)法join位于不同分庫(kù)的表,也無(wú)法join分表粒度不同的表, 結(jié)果原本一次查詢能夠完成的業(yè)務(wù),可能需要多次查詢才能完成。 ? 3、橫向擴(kuò)容與數(shù)據(jù)遷移的問(wèn)題 ?當(dāng)我們使用HASH取模做分表的時(shí)候,針對(duì)數(shù)據(jù)量的遞增,可能需要?jiǎng)討B(tài)的增加表,此時(shí)就需要考慮因?yàn)閞eHash導(dǎo)致數(shù)據(jù)遷移的問(wèn)題。 ? 4、結(jié)果集合并、排序的問(wèn)題因?yàn)槲覀兪菍?shù)據(jù)分散存儲(chǔ)到不同的庫(kù)、表里的,當(dāng)我們查詢指定數(shù)據(jù)列表時(shí),數(shù)據(jù)來(lái)源于不同的子庫(kù)或者子表,就必然會(huì)引發(fā)結(jié)果集合并、排序的問(wèn)題。 ? ?1.5 主從復(fù)制
什么是主從復(fù)制:是用來(lái)建立一個(gè)和主數(shù)據(jù)庫(kù)完全一樣的數(shù)據(jù)庫(kù)環(huán)境,稱為從數(shù)據(jù)庫(kù),主數(shù)據(jù)庫(kù)一般是準(zhǔn)實(shí)時(shí)的業(yè)務(wù)數(shù)據(jù)庫(kù)。 主從復(fù)制的作用:1、做數(shù)據(jù)的熱備:作為后備數(shù)據(jù)庫(kù),主數(shù)據(jù)庫(kù)服務(wù)器故障后,可切換到從數(shù)據(jù)庫(kù)繼續(xù)工作,避免數(shù)據(jù)丟失。2、架構(gòu)的擴(kuò)展:業(yè)務(wù)量越來(lái)越大,I/O訪問(wèn)頻率過(guò)高,單機(jī)無(wú)法滿足,此時(shí)做多庫(kù)的存儲(chǔ),降低磁盤(pán)I/O訪問(wèn)的頻率,提高單個(gè)機(jī)器的I/O性能。3、讀寫(xiě)分離:使數(shù)據(jù)庫(kù)能支撐更大的并發(fā)。在報(bào)表中尤其重要。由于部分報(bào)表sql語(yǔ)句非常的慢,導(dǎo)致鎖表,影響前臺(tái)服務(wù)。如果前臺(tái)使用master,報(bào)表使用slave,那么報(bào)表sql將不會(huì)造成前臺(tái)鎖,保證了前臺(tái)速度。 主從復(fù)制的原理:分為四步走:1、主庫(kù)對(duì)所有DDL和DML產(chǎn)生的日志寫(xiě)進(jìn)binlog;2、主庫(kù)生成一個(gè) log dump 線程,用來(lái)給從庫(kù)I/O線程讀取binlog;3、從庫(kù)的I/O Thread去請(qǐng)求主庫(kù)的binlog,并將得到的binlog日志寫(xiě)到relay log文件中;4、從庫(kù)的SQL Thread會(huì)讀取relay log文件中的日志解析成具體操作,將主庫(kù)的DDL和DML操作事件重放。 DML(Data ManipulationLanguage)語(yǔ)句:即數(shù)據(jù)操縱語(yǔ)句,用來(lái)查詢、添加、更新、刪除等 DDL(Data Definition Languages)語(yǔ)句:即數(shù)據(jù)庫(kù)定義語(yǔ)句,用來(lái)創(chuàng)建數(shù)據(jù)庫(kù)中的表、索引、視圖、存儲(chǔ)過(guò)程、觸發(fā)器等 ? ? ? ?1.6 讀寫(xiě)分離
數(shù)據(jù)庫(kù)寫(xiě)入效率要低于讀取效率,一般系統(tǒng)中數(shù)據(jù)讀取頻率高于寫(xiě)入頻率,單個(gè)數(shù)據(jù)庫(kù)實(shí)例在寫(xiě)入的時(shí)候會(huì)影響讀取性能,這是做讀寫(xiě)分離的原因。實(shí)現(xiàn)方式主要基于mysql的主從復(fù)制,通過(guò)路由的方式使應(yīng)用對(duì)數(shù)據(jù)庫(kù)的寫(xiě)請(qǐng)求只在master上進(jìn)行,讀請(qǐng)求在slave上進(jìn)行。 在應(yīng)用和數(shù)據(jù)庫(kù)之間增加代理層,代理層接收應(yīng)用對(duì)數(shù)據(jù)庫(kù)的請(qǐng)求,根據(jù)不同請(qǐng)求類型轉(zhuǎn)發(fā)到不同的實(shí)例,在實(shí)現(xiàn)讀寫(xiě)分離的同時(shí)可以實(shí)現(xiàn)負(fù)載均衡。 ? ?二、索引
2.1 什么是索引
索引是一種數(shù)據(jù)結(jié)構(gòu)。數(shù)據(jù)庫(kù)索引,是數(shù)據(jù)庫(kù)管理系統(tǒng)中一個(gè)排序的數(shù)據(jù)結(jié)構(gòu),以協(xié)助快速查詢、更新數(shù)據(jù)庫(kù)表中數(shù)據(jù),是要占據(jù)物理空間的。 索引的實(shí)現(xiàn)通常使用B樹(shù)及其變種B+樹(shù)。2.2 索引的優(yōu)缺點(diǎn)
索引的優(yōu)點(diǎn):可以大大加快數(shù)據(jù)的檢索速度,這也是創(chuàng)建索引的最主要的原因。 索引的缺點(diǎn)時(shí)間方面:創(chuàng)建索引和維護(hù)索引要耗費(fèi)時(shí)間。具體地,當(dāng)對(duì)表中的數(shù)據(jù)進(jìn)行增加、刪除和修改的時(shí)候,索引也要?jiǎng)討B(tài)的維護(hù),會(huì)降低增/改/刪的執(zhí)行效率;空間方面:索引需要占物理空間。2.3 索引的類型
唯一索引:唯一索引是不允許其中任何兩行具有相同索引值的索引;一般要求列值唯一(可以有null)。 主鍵索引:在我們給一個(gè)字段設(shè)置主鍵的時(shí)候,它就會(huì)自動(dòng)創(chuàng)建主鍵索引,用來(lái)確保每一個(gè)值都是唯一的,且不能為空。 組合索引:多列值組成一個(gè)索引,專門(mén)用于組合搜索 全文索引:有點(diǎn)像是一個(gè)搜索引擎提供模糊查詢,通過(guò)對(duì)文章中關(guān)鍵字建立索引,不是直接與索引中的值相比較。(http://www.360doc.com/content/17/1211/13/33260087_712076317.shtml) 非聚集索引將數(shù)據(jù)存儲(chǔ)于索引分開(kāi)結(jié)構(gòu),索引結(jié)構(gòu)的葉子節(jié)點(diǎn)指向了數(shù)據(jù)的對(duì)應(yīng)行。當(dāng)定位到索引之后還需要通過(guò)索引找到磁盤(pán)相應(yīng)數(shù)據(jù)。 聚簇索引:將數(shù)據(jù)存儲(chǔ)與索引放到了一塊,找到索引也就找到了數(shù)據(jù)。2.4 索引的創(chuàng)建原則
建立索引: 1、查詢比較頻繁:較頻繁作為查詢條件的字段才去創(chuàng)建索引 2、有外鍵的列:定義有外鍵的數(shù)據(jù)列一定要建立索引。不建立索引 1、頻繁更改:更新頻繁字段不適合創(chuàng)建索引 2、查詢較少:對(duì)于那些查詢中很少涉及的列,重復(fù)值比較多的列不要建立索引。 3、區(qū)分度比較低:若是不能有效區(qū)分?jǐn)?shù)據(jù)的列不適合做索引列(如性別,男女未知,最多也就三種,區(qū)分度實(shí)在太低) 4、對(duì)于定義為text、image和bit的數(shù)據(jù)類型的列不要建立索引。擴(kuò)展索引 盡量的擴(kuò)展索引,不要新建索引。比如表中已經(jīng)有a的索引,現(xiàn)在要加(a,b)的索引,那么只需要修改原來(lái)的索引即可。2.5 索引失效條件
1、如果條件中有or,即使其中有部分條件帶索引也不會(huì)使用 2、like以%開(kāi)頭 3、對(duì)于復(fù)合索引,如果不使用前列,后續(xù)列也將無(wú)法使用 4、存在索引列的數(shù)據(jù)類型隱形轉(zhuǎn)換,則用不上索引,比如列類型是字符串,那一定要在條件中將數(shù)據(jù)使用引號(hào)引用起來(lái),否則不使用索引 5、where 子句里對(duì)索引列上有數(shù)學(xué)運(yùn)算,用不上索引 6、where 子句里對(duì)有索引列使用函數(shù),用不上索引 7、"如果mysql估計(jì)使用全表掃描要比使用索引快,則不使用索引" https://www.cnblogs.com/liehen2046/p/11052666.html2.6 B樹(shù)索引和Hash 索引的區(qū)別
B+樹(shù)索引:是通過(guò)B+樹(shù)實(shí)現(xiàn)的;B+樹(shù)是一個(gè)多路平衡查找樹(shù),從根節(jié)點(diǎn)到每個(gè)葉子節(jié)點(diǎn)的高度差值不超過(guò)1,而且葉子的節(jié)點(diǎn)之按照大小順序從左往右排序并通過(guò)指針相連。在B+樹(shù)上的常規(guī)檢索,"從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的搜索效率基本相當(dāng),不會(huì)出現(xiàn)大幅波動(dòng)。而且基于索引的順序掃描時(shí),效率非常高"。因此,B+樹(shù)索引被廣泛應(yīng)用于數(shù)據(jù)庫(kù)、文件系統(tǒng)等場(chǎng)景。 Hash 索引:哈希索引就是采用一定的哈希算法,把鍵值換算成新的哈希值,檢索時(shí)不需要類似B+樹(shù)那樣從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)逐級(jí)查找,只需一次哈希算法即可立刻定位到相應(yīng)的位置,速度非常快。 B+樹(shù)索引和哈希索引的明顯區(qū)別是: (1) 如果是等值查詢,那么哈希索引明顯有絕對(duì)優(yōu)勢(shì),因?yàn)橹恍枰?jīng)過(guò)一次算法即可找到相應(yīng)的鍵值;當(dāng)然了,這個(gè)前提是,鍵值都是唯一的。如果鍵值不是唯一的,就需要先找到該鍵所在位置,然后再根據(jù)鏈表往后掃描,直到找到相應(yīng)的數(shù)據(jù); (2)如果是范圍查詢檢索,這時(shí)候哈希索引就毫無(wú)用武之地了,因?yàn)?#34;原先是有序的鍵值,經(jīng)過(guò)哈希算法后,有可能變成不連續(xù)的了"(3)同理,哈希索引也沒(méi)辦法利用索引完成排序,以及l(fā)ike `xxx%`這樣的模糊查詢(范圍查詢)(4)hash索引不?持多了聯(lián)合索引的最左匹配規(guī)則,原理也是因?yàn)閔ash函數(shù)的不可預(yù)測(cè)。AAAA和AAAAB的索引沒(méi)有相關(guān)性。(5)hash索引雖然在"等值查詢上較快,但是不穩(wěn)定。性能不可預(yù)測(cè),當(dāng)某個(gè)鍵值存在大量重復(fù)的時(shí)候,發(fā)生hash碰撞,此時(shí)效率可能極差”。而B(niǎo)+樹(shù)的查詢效率比較穩(wěn)定,對(duì)于所有的查詢都是從根節(jié)點(diǎn)到葉子節(jié)點(diǎn),且樹(shù)的高度較低。 因此,在大多數(shù)情況下,直接選擇B+樹(shù)索引可以獲得穩(wěn)定且較好的查詢速度。而不需要使用hash索引。2.7 介紹一下B 樹(shù)、B + 樹(shù)
B樹(shù)是一種平衡的多叉查找樹(shù),通常我們說(shuō)m階的B樹(shù),它必須滿足如下條件: 1、每個(gè)節(jié)點(diǎn)最多只有m個(gè)子節(jié)點(diǎn)。 2、若根節(jié)點(diǎn)不是非終端節(jié)點(diǎn),至少有兩個(gè)孩子3、除根結(jié)點(diǎn)和葉子結(jié)點(diǎn)外,其它每個(gè)結(jié)點(diǎn)至少有[ceil(m / 2)]個(gè)孩子(向上取整) 4、中間的節(jié)點(diǎn)有k-1個(gè)元素和k個(gè)孩子5、所有葉子結(jié)點(diǎn)都出現(xiàn)在同一層 6、每個(gè)節(jié)點(diǎn)中元素從小到大排列 B+樹(shù)是應(yīng)文件系統(tǒng)所需而產(chǎn)生的B樹(shù)的變形樹(shù),其特征在于1、有m個(gè)子樹(shù)的中間節(jié)點(diǎn)包含有m個(gè)元素(B樹(shù)中是k-1個(gè)元素),每個(gè)元素不保存數(shù)據(jù),只用來(lái)索引;2、葉子節(jié)點(diǎn)包含信息,非葉子節(jié)點(diǎn)僅起到索引作用。3、葉子節(jié)點(diǎn)包含全部的關(guān)鍵子信息,且葉子結(jié)點(diǎn)本身依關(guān)鍵字的大小自小而大的順序鏈接。2.8 為什么說(shuō)B+樹(shù)比B樹(shù)更適合數(shù)據(jù)庫(kù)索引?
1)B+樹(shù)的磁盤(pán)讀寫(xiě)代價(jià)更低B+樹(shù)的內(nèi)部結(jié)點(diǎn)并沒(méi)有指向關(guān)鍵字具體信息的指針。因此其內(nèi)部結(jié)點(diǎn)相對(duì)B 樹(shù)更小。那么一個(gè)盤(pán)塊所能容納的關(guān)鍵字?jǐn)?shù)量也越多。一次性讀入內(nèi)存中的需要查找的關(guān)鍵字也就越多。相對(duì)來(lái)說(shuō)IO讀寫(xiě)次數(shù)也就降低了;2)B+樹(shù)查詢效率更加穩(wěn)定由于非終結(jié)點(diǎn)并不是最終指向文件內(nèi)容的結(jié)點(diǎn),而只是葉子結(jié)點(diǎn)中關(guān)鍵字的索引。所以任何關(guān)鍵字的查找必須走一條從根結(jié)點(diǎn)到葉子結(jié)點(diǎn)的路。所有關(guān)鍵字查詢的路徑長(zhǎng)度相同,導(dǎo)致每一個(gè)數(shù)據(jù)的查詢效率相當(dāng); 3)B+樹(shù)便于范圍查詢(最重要的原因,范圍查找是數(shù)據(jù)庫(kù)的常態(tài))B樹(shù)在提高了IO性能的同時(shí)并沒(méi)有解決元素遍歷的效率低下的問(wèn)題,正是為了解決這個(gè)問(wèn)題,B+樹(shù)應(yīng)用而生。B+樹(shù)只需要去遍歷葉子節(jié)點(diǎn)就可以實(shí)現(xiàn)整棵樹(shù)的遍歷。而且在數(shù)據(jù)庫(kù)中基于范圍的查詢是非常頻繁的,而B(niǎo)樹(shù)不支持這樣的操作或者說(shuō)效率太低2.9 最左前綴原則是什么?
在進(jìn)行組合搜索的時(shí)候,我們通常會(huì)將建立組合索引。 MySQL中的索引可以按照一定順序引用多列,這種索引叫作聯(lián)合索引。如User表的name和city加聯(lián)合索引就是(name,city) 而最左前綴原則指的是,如果查詢的時(shí)候查詢條件精確匹配索引的左邊連續(xù)一列或幾列,則此索引列就可以被用到。如下: select * from user where name=xx and city=xx ; //可以命中索引 select * from user where name=xx ; // 可以命中索引 select * from user where city=xx ; // 無(wú)法命中索引 這里需要注意的是,查詢的時(shí)候如果兩個(gè)條件都用上了,但是順序不同,如 city= xx and name =xx,那么現(xiàn)在的查詢引擎會(huì)自動(dòng)優(yōu)化為匹配聯(lián)合索引的順序,這樣是能夠命中索引的。三、事務(wù)
3.1 簡(jiǎn)單介紹一下事務(wù)
事務(wù)是一個(gè)不可分割的數(shù)據(jù)庫(kù)操作序列,也是數(shù)據(jù)庫(kù)并發(fā)控制的基本單位。 事務(wù)執(zhí)行的結(jié)果必須使數(shù)據(jù)庫(kù)從一種一致性狀態(tài)變到另一種一致性狀態(tài)。 事務(wù)中包含的這組操作,要么都執(zhí)行,要么都不執(zhí)行。3.2 事務(wù)的四大特性
原子性(Atomicity):原子性是指事務(wù)包含的所有操作要么全部成功,要么全部失敗回滾. 一致性(Consistency):事務(wù)開(kāi)始前和結(jié)束后,數(shù)據(jù)庫(kù)的完整性約束沒(méi)有被破壞。比如A向B轉(zhuǎn)賬,不可能A扣了錢(qián),B卻沒(méi)收到。 隔離性(Isolation): 多個(gè)事務(wù)并發(fā)訪問(wèn)時(shí),事務(wù)之間是隔離的,一個(gè)事務(wù)不應(yīng)該影響其它事務(wù)運(yùn)行效果。 持久性(Durability):持久性是指一個(gè)事務(wù)一旦被提交了,那么對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)的改變就是永久性的3.3 事務(wù)之間的相互影響(事務(wù)并發(fā))
臟讀:事務(wù)A讀取了事務(wù)B更新的數(shù)據(jù),然后B回滾操作,那么A讀取到的數(shù)據(jù)是臟數(shù)據(jù).不可重復(fù)讀:事務(wù)A多次讀取同一數(shù)據(jù),事務(wù)B在事務(wù)A多次讀取的過(guò)程中,對(duì)數(shù)據(jù)作了更新并提交,導(dǎo)致事務(wù)A多次讀取同一數(shù)據(jù)時(shí),結(jié)果事務(wù)先后兩次讀到的數(shù)據(jù)結(jié)果會(huì)不一致。幻讀:幻讀,是指當(dāng)事務(wù)不是獨(dú)立執(zhí)行時(shí)發(fā)生的一種現(xiàn)象,例如第一個(gè)事務(wù)對(duì)一個(gè)表中的數(shù)據(jù)進(jìn)行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時(shí),第二個(gè)事務(wù)也修改這個(gè)表中的數(shù)據(jù),這種修改是向表中插入一行新數(shù)據(jù)。那么,以后就會(huì)發(fā)生操作第一個(gè)事務(wù)的用戶發(fā)現(xiàn)表中還有沒(méi)有修改的數(shù)據(jù)行,就好象發(fā)生了幻覺(jué)一樣.3.4 事務(wù)的隔離級(jí)別
隔離級(jí)別共4種 1、讀未提交:即能夠讀取到?jīng)]有被提交的數(shù)據(jù),所以很明顯這個(gè)級(jí)別的隔離機(jī)制無(wú)法解決臟讀、不可重復(fù)讀、幻讀中的任何一種 2、讀已提交:即能夠讀到那些已經(jīng)提交的數(shù)據(jù),自然能夠防止臟讀,但是無(wú)法限制不可重復(fù)讀和幻讀 3、重復(fù)讀取:即在數(shù)據(jù)讀出來(lái)之后加鎖。這樣就解決了臟讀、不可重復(fù)讀的問(wèn)題,但是幻讀的問(wèn)題還是無(wú)法解決。 4、串行化:最高的事務(wù)隔離級(jí)別,不管多少事務(wù),挨個(gè)運(yùn)行完一個(gè)事務(wù)的所有子事務(wù)之后才可以執(zhí)行另外一個(gè)事務(wù)里面的所有子事務(wù),這樣就解決了臟讀、不可重復(fù)讀和幻讀的問(wèn)題。MySQL 支持4種事務(wù)隔離級(jí)別;MySQL默認(rèn)的事務(wù)隔離級(jí)別為可重復(fù)讀。事務(wù)隔離機(jī)制的實(shí)現(xiàn)基于鎖機(jī)制和并發(fā)調(diào)度。3.5 事務(wù)的傳播行為
事務(wù)傳播行為:指的就是當(dāng)一個(gè)事務(wù)方法被另一個(gè)事務(wù)方法調(diào)用時(shí),這個(gè)事務(wù)方法應(yīng)該如何運(yùn)行。 事務(wù)的7種傳播行為: mandatory強(qiáng)制性,有事務(wù)則加入,沒(méi)有異常; supports支持,有則加入,沒(méi)有就不管了,非事務(wù)運(yùn)行; required需要,沒(méi)有新建,有加入 requires_new需要新的,不管有沒(méi)有,直接創(chuàng)建新事務(wù) not supported不支持事務(wù),存在就掛起 never不支持事務(wù),存在就異常 nested:存在就在嵌套的執(zhí)行,沒(méi)有就找是否存在外面的事務(wù),有則加入,沒(méi)有則新建 對(duì)事務(wù)的要求程度可以從大到小排序:mandatory / supports / required / requires_new / nested / not supported / never3.6 事務(wù)的隔離級(jí)別和鎖之間的關(guān)系
在Read Uncommitted級(jí)別下,讀取數(shù)據(jù)不需要加共享鎖,這樣就不會(huì)跟被修改的數(shù)據(jù)上的排他鎖沖突在Read Committed級(jí)別下,讀操作需要加共享鎖,但是在語(yǔ)句執(zhí)行完以后釋放共享鎖;在Repeatable Read級(jí)別下,讀操作需要加共享鎖,必須等待事務(wù)執(zhí)行完畢以后才釋放共享鎖。SERIALIZABLE 是限制性最強(qiáng)的隔離級(jí)別,因?yàn)樵摷?jí)別鎖定整個(gè)范圍的鍵,并一直持有鎖,直到事務(wù)完成。四、數(shù)據(jù)庫(kù)存儲(chǔ)引擎
4.1 Mysql 最常用的存儲(chǔ)引擎
Innodb引擎:Innodb引擎提供了對(duì)數(shù)據(jù)庫(kù)事務(wù)的支持。并且還提供了行級(jí)鎖和外鍵的約束。它的設(shè)計(jì)的目標(biāo)就是處理大數(shù)據(jù)容量的數(shù)據(jù)庫(kù)系統(tǒng)。 MyIASM引擎(原本Mysql的默認(rèn)引擎):不提供事務(wù)的支持,也不支持行級(jí)鎖和外鍵。 MEMORY引擎:所有的數(shù)據(jù)都在內(nèi)存中,數(shù)據(jù)的處理速度快,但是安全性不高。4.2 MyISAM與InnoDB區(qū)別
1.事務(wù):InnoDB支持事務(wù),MyISAM不支持, 這一點(diǎn)是非常之重要。事務(wù)是一種高級(jí)的處理方式,如在一些列增刪改中只要哪個(gè)出錯(cuò)還可以回滾還原,而MyISAM就不可以了。 2.外鍵:InnoDB支持外鍵,MyISAM不支持。 3.鎖:鎖是避免資源爭(zhēng)用的機(jī)制,MYIASM只支持表級(jí)鎖,InnoDB支持行級(jí)鎖,鎖定力度小并發(fā)能力高 。4.增刪改查:MyISAM適合查詢以及插入為主的應(yīng)用,InnoDB適合頻繁修改以及涉及到安全性較高的應(yīng)用。 5.存儲(chǔ)結(jié)構(gòu):MYIASM每張表被存放在3個(gè)文件中(表格定義,數(shù)據(jù)文件,索引文件);InnoDB所有的表都存放在同一個(gè)文件中6.存儲(chǔ)空間:MYIASM可被壓縮,存儲(chǔ)空間小;InnoDB需要更多的內(nèi)存和存儲(chǔ)。 7.索引:兩者都是使用B+樹(shù)作為存儲(chǔ)結(jié)構(gòu),但是在實(shí)現(xiàn)方式上面差別很大。 MyIASM:索引結(jié)構(gòu)為非聚簇索引,索引和數(shù)據(jù)文件是分離的,索引保存的是數(shù)據(jù)文件的指針。 InnoDB:索引結(jié)構(gòu)為聚簇索引,數(shù)據(jù)文件是和(主鍵)索引綁在一起的,必須要有主鍵,通過(guò)主鍵索引效率很高。Innodb不支持全文索引,而MyISAM支持全文索引。 Innodb支持HASh索引,而MyISAM不支持HASH索引。4.3 InnoDB引擎的4大特性
插入緩沖(insert buffer)、二次寫(xiě)(double write)、自適應(yīng)哈希索引(ahi)、預(yù)讀(read ahead) https://www.jianshu.com/p/dcc0dc450a2c4.4 存儲(chǔ)引擎選擇
如果沒(méi)有特別的需求,使用默認(rèn)的Innodb即可。 MyISAM:以讀寫(xiě)插入為主的應(yīng)用程序,比如博客系統(tǒng)、新聞門(mén)戶網(wǎng)站。 Innodb:更新操作頻率也高,或者要保證數(shù)據(jù)的完整性;并發(fā)量高,支持事務(wù)和外鍵。比如OA自動(dòng)化辦公系統(tǒng)。五、數(shù)據(jù)庫(kù)的鎖
5.1、談一下對(duì)于MySQL鎖的了解
當(dāng)數(shù)據(jù)庫(kù)有并發(fā)事務(wù)的時(shí)候,可能會(huì)產(chǎn)生數(shù)據(jù)的不一致,這時(shí)候需要一些機(jī)制來(lái)保證訪問(wèn)的次序,鎖機(jī)制就是這樣的一個(gè)機(jī)制。就像酒店的房間,如果大家隨意進(jìn)出,就會(huì)出現(xiàn)多人搶奪同一個(gè)房間的情況,而在房間上裝上鎖,申請(qǐng)到鑰匙的人才可以入住并且將房間鎖起來(lái),其他人只有等他使用完畢才可以再次使用。5.2、按照鎖的粒度劃分?jǐn)?shù)據(jù)庫(kù)鎖有哪些?
在關(guān)系型數(shù)據(jù)庫(kù)中,可以按照鎖的粒度把數(shù)據(jù)庫(kù)鎖分為行級(jí)鎖(INNODB引擎)、表級(jí)鎖(MYISAM引擎)和頁(yè)級(jí)鎖(BDB引擎 )。 行級(jí)鎖,表級(jí)鎖和頁(yè)級(jí)鎖對(duì)比1、行級(jí)鎖:行級(jí)鎖是Mysql中鎖定粒度最細(xì)的一種鎖,表示只針對(duì)當(dāng)前操作的行進(jìn)行加鎖。行級(jí)鎖分為共享鎖 和 排他鎖。 特點(diǎn):鎖定粒度最小,加鎖慢,開(kāi)銷大,會(huì)出現(xiàn)死鎖;發(fā)生鎖沖突的概率最低,并發(fā)度也最高。 2、表級(jí)鎖:表級(jí)鎖是MySQL中鎖定粒度最大的一種鎖,表示對(duì)當(dāng)前操作的整張表加鎖。它實(shí)現(xiàn)簡(jiǎn)單,資源消耗較少,被大部分MySQL引擎支持。最常使用的MYISAM與INNODB都支持表級(jí)鎖定。表級(jí)鎖定分為表共享讀鎖(共享鎖)與表獨(dú)占寫(xiě)鎖(排他鎖)。 特點(diǎn):鎖定粒度最大,加鎖快,開(kāi)銷小,不會(huì)出現(xiàn)死鎖;發(fā)出鎖沖突的概率最高,并發(fā)度最低。3、頁(yè)級(jí)鎖:頁(yè)級(jí)鎖是MySQL中鎖定粒度介于行級(jí)鎖和表級(jí)鎖中間的一種鎖,一次鎖定相鄰的一組記錄。特點(diǎn):鎖定粒度界于表鎖和行鎖之間,開(kāi)銷和加鎖時(shí)間界于表鎖和行鎖之間,會(huì)出現(xiàn)死鎖;并發(fā)度一般 MyISAM和InnoDB存儲(chǔ)引擎使用的鎖:MyISAM采用表級(jí)鎖(table-level locking)。InnoDB支持行級(jí)鎖(row-level locking)和表級(jí)鎖,默認(rèn)為行級(jí)鎖5.3、從鎖的類別上分MySQL都有哪些鎖呢?
在關(guān)系型數(shù)據(jù)庫(kù)中,可以按照鎖的的類別分為:有共享鎖和排他鎖。 共享鎖: 又叫做讀鎖。當(dāng)用戶要進(jìn)行數(shù)據(jù)的讀取時(shí),對(duì)數(shù)據(jù)加上共享鎖。共享鎖可以同時(shí)加上多個(gè)。 排他鎖: 又叫做寫(xiě)鎖。當(dāng)用戶要進(jìn)行數(shù)據(jù)的寫(xiě)入時(shí),對(duì)數(shù)據(jù)加上排他鎖。排他鎖只可以加一個(gè),他和其他的排他鎖,共享鎖都相斥。5.4 、InnoDB引擎的行鎖是怎么實(shí)現(xiàn)的?
答:InnoDB是基于索引來(lái)完成行鎖 例: select * from tab_with_index where id = 1 for update; for update 可以根據(jù)條件來(lái)完成行鎖鎖定,并且 id 是有索引鍵的列,如果 id 不是索引鍵那么InnoDB將完成表鎖,并發(fā)將無(wú)從談起5.5、 InnoDB存儲(chǔ)引擎的鎖的算法有三種
Record lock:單個(gè)行記錄上的鎖 Gap lock:間隙鎖,鎖定一個(gè)范圍,不包括記錄本身 Next-key lock:record+gap 鎖定一個(gè)范圍,包含記錄本身5.6 什么是死鎖?怎樣解決?
死鎖是指兩個(gè)或多個(gè)事務(wù)在同一資源上相互占用,并請(qǐng)求鎖定對(duì)方的資源,從而導(dǎo)致惡性循環(huán)的現(xiàn)象。 常見(jiàn)的解決死鎖的方法: 1、 2、如果不同程序會(huì)并發(fā)存取多個(gè)表,盡量約定以相同的順序訪問(wèn)表,可以大大降低死鎖機(jī)會(huì)。 3、對(duì)于非常容易產(chǎn)生死鎖的業(yè)務(wù)部分,可以嘗試使用升級(jí)鎖定顆粒度,通過(guò)表級(jí)鎖定來(lái)減少死鎖產(chǎn)生的概率;5.7、數(shù)據(jù)庫(kù)的樂(lè)觀鎖和悲觀鎖是什么?怎么實(shí)現(xiàn)的?
數(shù)據(jù)庫(kù)管理系統(tǒng)中的并發(fā)控制的任務(wù):是確保在多個(gè)事務(wù)同時(shí)存取數(shù)據(jù)庫(kù)中同一數(shù)據(jù)時(shí)不破壞事務(wù)的隔離性和一致性以及數(shù)據(jù)庫(kù)的統(tǒng)一性。 樂(lè)觀并發(fā)控制(樂(lè)觀鎖)和悲觀并發(fā)控制(悲觀鎖)是并發(fā)控制主要采用的技術(shù)手段。 悲觀鎖:當(dāng)我們要對(duì)一個(gè)數(shù)據(jù)庫(kù)中的一條數(shù)據(jù)進(jìn)行修改的時(shí)候,假設(shè)數(shù)據(jù)會(huì)造成沖突,最好的辦法就是直接對(duì)該數(shù)據(jù)進(jìn)行加鎖以防止并發(fā)。這種借助數(shù)據(jù)庫(kù)鎖機(jī)制,在修改數(shù)據(jù)之前先鎖定,再修改的方式被稱之為悲觀并發(fā)控制 悲觀鎖的實(shí)現(xiàn)方式:借助數(shù)據(jù)庫(kù)鎖機(jī)制 樂(lè)觀鎖:當(dāng)我們要對(duì)一個(gè)數(shù)據(jù)庫(kù)中的一條數(shù)據(jù)進(jìn)行修改的時(shí)候,假設(shè)數(shù)據(jù)不會(huì)造成沖突,在對(duì)數(shù)據(jù)進(jìn)行提交更新的時(shí)候,才會(huì)正式對(duì)數(shù)據(jù)的沖突與否進(jìn)行檢測(cè),如果發(fā)現(xiàn)沖突了,則返回給用戶錯(cuò)誤的信息,讓用戶決定如何去做。 樂(lè)觀鎖的實(shí)現(xiàn)方式:一般會(huì)使用版本號(hào)機(jī)制或CAS算法實(shí)現(xiàn)。 兩種鎖的使用場(chǎng)景 我們知道兩種鎖各有優(yōu)缺點(diǎn),不可認(rèn)為一種好于另一種。 樂(lè)觀鎖適用于寫(xiě)比較少的情況下(多讀場(chǎng)景),即沖突真的很少發(fā)生的時(shí)候,這樣可以省去了鎖的開(kāi)銷,加大了系統(tǒng)的整個(gè)吞吐量。 悲觀鎖適用于寫(xiě)比較多的情況下(多寫(xiě)場(chǎng)景),即沖突經(jīng)常發(fā)生的時(shí)候。這就會(huì)導(dǎo)致上層應(yīng)用會(huì)不斷的進(jìn)行retry,這樣反倒是降低了性能,六、視圖& 觸發(fā)器
6.1 為什么要使用視圖?什么是視圖?
為了提高"復(fù)雜SQL語(yǔ)句的復(fù)用性"和"表操作的安全性",MySQL數(shù)據(jù)庫(kù)管理系統(tǒng)提供了視圖特性。 1、視圖是由基本表產(chǎn)生的虛表。 2、視圖的列可以來(lái)自不同的表。 3、視圖的建立和刪除不影響基本表。 4、對(duì)視圖內(nèi)容的增刪改直接影響基本表。6.2 視圖的使用場(chǎng)景有哪些?
1、重用SQL語(yǔ)句 2、簡(jiǎn)化復(fù)雜的SQL操作。在編寫(xiě)查詢后,可以方便的重用它而不必知道它的基本查詢細(xì)節(jié); 3、使用表的組成部分而不是整個(gè)表; 4、保護(hù)數(shù)據(jù)。可以給用戶授予表的特定部分的訪問(wèn)權(quán)限而不是整個(gè)表的訪問(wèn)權(quán)限;6.3 觸發(fā)器
觸發(fā)器是定義在關(guān)系表上的"一類由事件驅(qū)動(dòng)"的特殊的存儲(chǔ)過(guò)程。 使用場(chǎng)景:1、實(shí)時(shí)監(jiān)控某張表中的某個(gè)字段的更改而需要做出相應(yīng)的處理。2、可以通過(guò)數(shù)據(jù)庫(kù)中的相關(guān)表實(shí)現(xiàn)級(jí)聯(lián)更改。總結(jié)
以上是生活随笔為你收集整理的MSQL常见面试问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【手把手】JavaWeb 入门级项目实战
- 下一篇: 初一知识用计算机进行运算,【初一数学】必