MySQL
索引
1.什么是索引
索引是一種數(shù)據(jù)結(jié)構(gòu),用于幫助我們在大量數(shù)據(jù)中快速定位到我們想要查找的數(shù)據(jù)。
 索引最形象的比喻就是圖書的目錄了。注意這里的大量,數(shù)據(jù)量大了索引才顯得有意義,如果我想要在 [1,2,3,4] 中找到 4 這個數(shù)據(jù),直接對全數(shù)據(jù)檢索也很快,沒有必要費力氣建索引再去查找。
25.為什么引入索引?
為了提高數(shù)據(jù)查詢的效率。索引對數(shù)據(jù)庫查詢良好的性能非常關(guān)鍵,當(dāng)表中數(shù)據(jù)量越來越大,索引對性能的影響越重要。
26.Mysql有哪些常見索引類型?
- 數(shù)據(jù)結(jié)構(gòu)角度
 B-Tree索引 哈希索引 R-Tree索引 全文索引
- 物理存儲角度
 主鍵索引(聚簇索引):葉子節(jié)點存的是整行的數(shù)據(jù) 非主鍵索引(二級索引):葉子節(jié)點存的主鍵的值
Mysql索引使用的數(shù)據(jù)結(jié)構(gòu)主要有BTree索引 和 哈希索引 。對于哈希索引來說,底層的數(shù)據(jù)結(jié)構(gòu)就是哈希表,因此在絕大多數(shù)需求為單條記錄查詢的時候,可以選擇哈希索引,查詢性能最快;其余大部分場景,建議選擇BTree索引。
Mysql的BTree索引使用的是B數(shù)中的B+Tree,但對于主要的兩種存儲引擎的實現(xiàn)方式是不同的。
MyISAM: B+Tree葉節(jié)點的data域存放的是數(shù)據(jù)記錄的地址。在索引檢索的時候,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其data域的值,然后以data域的值為地址讀取相應(yīng)的數(shù)據(jù)記錄。這被稱為“非聚簇索引”。
InnoDB: 其數(shù)據(jù)文件本身就是索引文件。相比MyISAM,索引文件和數(shù)據(jù)文件是分離的,其表數(shù)據(jù)文件本身就是按B+Tree組織的一個索引結(jié)構(gòu),樹的葉節(jié)點data域保存了完整的數(shù)據(jù)記錄。這個索引的key是數(shù)據(jù)表的主鍵,因此InnoDB表數(shù)據(jù)文件本身就是主索引。這被稱為“聚簇索引(或聚集索引)”。而其余的索引都作為輔助索引,輔助索引的data域存儲相應(yīng)記錄主鍵的值而不是地址,這也是和MyISAM不同的地方。在根據(jù)主索引搜索時,直接找到key所在的節(jié)點即可取出數(shù)據(jù);在根據(jù)輔助索引查找時,則需要先取出主鍵的值,在走一遍主索引。 因此,在設(shè)計表的時候,不建議使用過長的字段作為主鍵,也不建議使用非單調(diào)的字段作為主鍵,這樣會造成主索引頻繁分裂。
27.簡述B-Tree與B+樹
B-Tree 是一種自平衡的樹。每個非葉子節(jié)點至多有兩個子節(jié)點。每個節(jié)點都存儲關(guān)鍵字值。其左子節(jié)點的關(guān)鍵字值小于該節(jié)點關(guān)鍵字值,且右子節(jié)點的關(guān)鍵字值大于或等于該節(jié)點關(guān)鍵字值。
B+樹也是是一種自平衡的樹。其基本定義與B樹相同,不同點在于數(shù)據(jù)只出現(xiàn)在葉子節(jié)點,所有葉子節(jié)點增加了一個鏈指針,方便進行范圍查詢。
B+樹中間節(jié)點不存放數(shù)據(jù),所以同樣大小的磁盤頁上可以容納更多節(jié)點元素,訪問葉子節(jié)點上關(guān)聯(lián)的數(shù)據(jù)也具有更好的緩存命中率。并且數(shù)據(jù)順序排列并且相連,所以便于區(qū)間查找和搜索。
B樹每一個節(jié)點都包含key和value,查詢效率比B+樹高。
5.B+樹索引
二叉查找樹
首先,讓我們先看一張圖:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-cCKCHaGe-1630242223264)(Mysql.assets/1.jpg)]
從圖中可以看到,我們?yōu)?user 表(用戶信息表)建立了一個二叉查找樹的索引。
圖中的圓為二叉查找樹的節(jié)點,節(jié)點中存儲了鍵(key)和數(shù)據(jù)(data)。鍵對應(yīng) user 表中的 id,數(shù)據(jù)對應(yīng) user 表中的行數(shù)據(jù)。
二叉查找樹的特點就是任何節(jié)點的左子節(jié)點的鍵值都小于當(dāng)前節(jié)點的鍵值,右子節(jié)點的鍵值都大于當(dāng)前節(jié)點的鍵值。頂端的節(jié)點我們稱為根節(jié)點,沒有子節(jié)點的節(jié)點我們稱之為葉節(jié)點。
如果我們需要查找 id=12 的用戶信息,利用我們創(chuàng)建的二叉查找樹索引,查找流程如下:
- 將根節(jié)點作為當(dāng)前節(jié)點,把 12 與當(dāng)前節(jié)點的鍵值 10 比較,12 大于 10,接下來我們把當(dāng)前節(jié)點>的右子節(jié)點作為當(dāng)前節(jié)點。
- 繼續(xù)把 12 和當(dāng)前節(jié)點的鍵值 13 比較,發(fā)現(xiàn) 12 小于 13,把當(dāng)前節(jié)點的左子節(jié)點作為當(dāng)前節(jié)點。
- 把 12 和當(dāng)前節(jié)點的鍵值 12 對比,12 等于 12,滿足條件,我們從當(dāng)前節(jié)點中取出 data,即 id=12,name=xm。
利用二叉查找樹我們只需要 3 次即可找到匹配的數(shù)據(jù)。如果在表中一條條的查找的話,我們需要 6 次才能找到。
平衡二叉樹
上面我們講解了利用二叉查找樹可以快速的找到數(shù)據(jù)。但是,如果上面的二叉查找樹是這樣的構(gòu)造:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-f0rJmvb7-1630242223266)(Mysql.assets/2.jpg)]
這個時候可以看到我們的二叉查找樹變成了一個鏈表。如果我們需要查找 id=17 的用戶信息,我們需要查找 7 次,也就相當(dāng)于全表掃描了。
導(dǎo)致這個現(xiàn)象的原因其實是二叉查找樹變得不平衡了,也就是高度太高了,從而導(dǎo)致查找效率的不穩(wěn)定。
為了解決這個問題,我們需要保證二叉查找樹一直保持平衡,就需要用到平衡二叉樹了。
平衡二叉樹又稱 AVL 樹,在滿足二叉查找樹特性的基礎(chǔ)上,要求每個節(jié)點的左右子樹的高度差不能超過 1。
下面是平衡二叉樹和非平衡二叉樹的對比:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vOoLIUFC-1630242223269)(Mysql.assets/3.jpg)]
由平衡二叉樹的構(gòu)造我們可以發(fā)現(xiàn)第一張圖中的二叉樹其實就是一棵平衡二叉樹。
平衡二叉樹保證了樹的構(gòu)造是平衡的,當(dāng)我們插入或刪除數(shù)據(jù)導(dǎo)致不滿足平衡二叉樹不平衡時,平衡二叉樹會進行調(diào)整樹上的節(jié)點來保持平衡。具體的調(diào)整方式這里就不介紹了。
平衡二叉樹相比于二叉查找樹來說,查找效率更穩(wěn)定,總體的查找速度也更快。
B 樹
因為內(nèi)存的易失性。一般情況下,我們都會選擇將 user 表中的數(shù)據(jù)和索引存儲在磁盤這種外圍設(shè)備中。
但是和內(nèi)存相比,從磁盤中讀取數(shù)據(jù)的速度會慢上百倍千倍甚至萬倍,所以,我們應(yīng)當(dāng)盡量減少從磁盤中讀取數(shù)據(jù)的次數(shù)。
另外,從磁盤中讀取數(shù)據(jù)時,都是按照磁盤塊來讀取的,并不是一條一條的讀。
如果我們能把盡量多的數(shù)據(jù)放進磁盤塊中,那一次磁盤讀取操作就會讀取更多數(shù)據(jù),那我們查找數(shù)據(jù)的時間也會大幅度降低。
如果我們用樹這種數(shù)據(jù)結(jié)構(gòu)作為索引的數(shù)據(jù)結(jié)構(gòu),那我們每查找一次數(shù)據(jù)就需要從磁盤中讀取一個節(jié)點,也就是我們說的一個磁盤塊。
我們都知道平衡二叉樹可是每個節(jié)點只存儲一個鍵值和數(shù)據(jù)的。那說明什么?說明每個磁盤塊僅僅存儲一個鍵值和數(shù)據(jù)!那如果我們要存儲海量的數(shù)據(jù)呢?
可以想象到二叉樹的節(jié)點將會非常多,高度也會極其高,我們查找數(shù)據(jù)時也會進行很多次磁盤 IO,我們查找數(shù)據(jù)的效率將會極低!
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VUZ7BwiR-1630242223271)(Mysql.assets/4.jpg)]
為了解決平衡二叉樹的這個弊端,我們應(yīng)該尋找一種單個節(jié)點可以存儲多個鍵值和數(shù)據(jù)的平衡樹。也就是我們接下來要說的 B 樹。
B 樹(Balance Tree)即為平衡樹的意思,下圖即是一棵 B 樹:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-0Dw8kpvs-1630242223272)(Mysql.assets/5.jpg)]
圖中的 p 節(jié)點為指向子節(jié)點的指針,二叉查找樹和平衡二叉樹其實也有,因為圖的美觀性,被省略了。
圖中的每個節(jié)點稱為頁,頁就是我們上面說的磁盤塊,在 MySQL 中數(shù)據(jù)讀取的基本單位都是頁,所以我們這里叫做頁更符合 MySQL 中索引的底層數(shù)據(jù)結(jié)構(gòu)。
從上圖可以看出,B 樹相對于平衡二叉樹,每個節(jié)點存儲了更多的鍵值(key)和數(shù)據(jù)(data),并且每個節(jié)點擁有更多的子節(jié)點,子節(jié)點的個數(shù)一般稱為階,上述圖中的 B 樹為 3 階 B 樹,高度也會很低。
基于這個特性,B 樹查找數(shù)據(jù)讀取磁盤的次數(shù)將會很少,數(shù)據(jù)的查找效率也會比平衡二叉樹高很多。
假如我們要查找 id=28 的用戶信息,那么我們在上圖 B 樹中查找的流程如下:
- 先找到根節(jié)點也就是頁 1,判斷 28 在鍵值 17 和 35 之間,那么我們根據(jù)頁 1 中的指針 p2 找到頁 3。
- 將 28 和頁 3 中的鍵值相比較,28 在 26 和 30 之間,我們根據(jù)頁 3 中的指針 p2 找到頁 8。
- 將 28 和頁 8 中的鍵值相比較,發(fā)現(xiàn)有匹配的鍵值 28,鍵值 28 對應(yīng)的用戶信息為(28,bv)。
B+ 樹
B+ 樹是對 B 樹的進一步優(yōu)化。讓我們先來看下 B+ 樹的結(jié)構(gòu)圖:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Pc9feq6q-1630242223273)(Mysql.assets/6.jpg)]
BTREE和B+TREE區(qū)別是什么?
- B+Tree 關(guān)鍵字的搜索采用的是左閉合區(qū)間,之所以采用左閉合區(qū)間是因為他要最好的去支持自增id,這也是mysql的設(shè)計初衷。即,如果id = 1命中,會繼續(xù)往下查找,直到找到葉子節(jié)點中的1。
- B+Tree 根節(jié)點和支節(jié)點沒有數(shù)據(jù)區(qū),關(guān)鍵字對應(yīng)的數(shù)據(jù)只保存在葉子節(jié)點中。即只有葉子節(jié)點中的關(guān)鍵字?jǐn)?shù)據(jù)區(qū)才會保存真正的數(shù)據(jù)內(nèi)容或者是內(nèi)容的地址。而在B樹種,如果根節(jié)點命中,則會直接返回數(shù)據(jù)。
- 在B+Tree中,葉子節(jié)點不會去保存子節(jié)點的引用。
- B+Tree葉子節(jié)點是順序排列的,并且相鄰的節(jié)點具有順序引用的關(guān)系,如上圖中葉子節(jié)點之間有指針相連接。
MySQL為什么最終要去選擇B+Tree?
- B+Tree是B TREE的變種,B TREE能解決的問題,B+TREE也能夠解決(降低樹的高度,增大節(jié)點存儲數(shù)據(jù)量)
- B+Tree掃庫和掃表能力更強。如果我們要根據(jù)索引去進行數(shù)據(jù)表的掃描,對B TREE進行掃描,需要把整棵樹遍歷一遍,而B+TREE只需要遍歷他的所有葉子節(jié)點即可(葉子節(jié)點之間有引用)。
- B+TREE磁盤讀寫能力更強。他的根節(jié)點和支節(jié)點不保存數(shù)據(jù)區(qū),所以根節(jié)點和支節(jié)點同樣大小的情況下,保存的關(guān)鍵字要比B TREE要多。而葉子節(jié)點不保存子節(jié)點引用,能用于保存更多的關(guān)鍵字和數(shù)據(jù)。所以,B+TREE讀寫一次磁盤加載的關(guān)鍵字比B TREE更多。
- B+Tree排序能力更強。上面的圖中可以看出,B+Tree天然具有排序功能。
- B+Tree查詢性能穩(wěn)定。B+Tree數(shù)據(jù)只保存在葉子節(jié)點,每次查詢數(shù)據(jù),查詢IO次數(shù)一定是穩(wěn)定的。當(dāng)然這個每個人的理解都不同,因為在B TREE如果根節(jié)點命中直接返回,確實效率更高。
28.簡述Hash索引
哈希索引(hash index)基于哈希表實現(xiàn),只有精確匹配索引所有列的查詢才有效。對于每一行數(shù)據(jù),存儲引擎都會對所有的索引列計算一個哈希碼(hash code),哈希碼是一個較小的值,并且不同鍵值的行計算出來的哈希碼也不一樣。哈希索引將所有的哈希碼存儲在索引中,同時在哈希表中保存指向每個數(shù)據(jù)行的指針。只有 Memory 引擎顯式支持哈希索引。
哈希索引也有幾個缺點:
- 索引存放的是hash值,所以僅支持 < = > 以及 IN 操作
- hash索引無法通過操作索引來排序,因為存放的時候經(jīng)過hash計算,但是計算的hash值和存放的不一定相等,所以無法排序
- 不能避免全表掃描,只是由于在memory表里支持非唯一值hash索引,就是不同的索引鍵,可能存在相同的hash值
- 如果哈希碰撞很多的話,性能也會變得很差
- 哈希索引無法被用來避免數(shù)據(jù)的排序操作
29.簡述自適應(yīng)Hash索引
InnoDB對于頻繁使用的某些索引值,會在內(nèi)存中基于 B-Tree 索引之上再創(chuàng)鍵一個哈希索引,這也被稱為自適應(yīng)Hash索引。
30.MySQL B+Tree索引和Hash索引的區(qū)別?
Hash 索引結(jié)構(gòu)的特殊性,其檢索效率非常高,索引的檢索可以一次定位,不像B-Tree 索引需要從根節(jié)點到枝節(jié)點,最后才能訪問到頁節(jié)點這樣多次的IO訪問,所以 Hash 索引的查詢效率要遠高于 B-Tree 索引。
可能很多人又有疑問了,既然 Hash 索引的效率要比 B-Tree 高很多,為什么大家不都用 Hash 索引而還要使用 B-Tree 索引呢?任何事物都是有兩面性的,Hash 索引也一樣,雖然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也帶來了很多限制和弊端,主要有以下這些。
(1)Hash 索引僅僅能滿足"=",“IN"和”<=>"查詢,不能使用范圍查詢。
由于 Hash 索引比較的是進行 Hash 運算之后的 Hash 值,所以它只能用于等值的過濾,不能用于基于范圍的過濾,因為經(jīng)過相應(yīng)的 Hash 算法處理之后的 Hash 值的大小關(guān)系,并不能保證和Hash運算前完全一樣。
(2)Hash 索引無法被用來避免數(shù)據(jù)的排序操作。
由于 Hash 索引中存放的是經(jīng)過 Hash 計算之后的 Hash 值,而且Hash值的大小關(guān)系并不一定和 Hash 運算前的鍵值完全一樣,所以數(shù)據(jù)庫無法利用索引的數(shù)據(jù)來避免任何排序運算;
(3)Hash 索引不能利用部分索引鍵查詢。
對于組合索引,Hash 索引在計算 Hash 值的時候是組合索引鍵合并后再一起計算 Hash 值,而不是單獨計算 Hash 值,所以通過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也無法被利用。
(4)Hash 索引在任何時候都不能避免表掃描。
前面已經(jīng)知道,Hash 索引是將索引鍵通過 Hash 運算之后,將 Hash運算結(jié)果的 Hash 值和所對應(yīng)的行指針信息存放于一個 Hash 表中,由于不同索引鍵存在相同 Hash 值,所以即使取滿足某個 Hash 鍵值的數(shù)據(jù)的記錄條數(shù),也無法從 Hash 索引中直接完成查詢,還是要通過訪問表中的實際數(shù)據(jù)進行相應(yīng)的比較,并得到相應(yīng)的結(jié)果。
(5)Hash 索引遇到大量Hash值相等的情況后性能并不一定就會比B-Tree索引高。
對于選擇性比較低的索引鍵,如果創(chuàng)建 Hash 索引,那么將會存在大量記錄指針信息存于同一個 Hash 值相關(guān)聯(lián)。這樣要定位某一條記錄時就會非常麻煩,會浪費多次表數(shù)據(jù)的訪問,而造成整體性能低下。
30.簡述聚集索引和稀疏索引
聚集索引按每張表的主鍵構(gòu)建一棵B+樹,數(shù)據(jù)庫中的每個搜索鍵值都有一個索引記錄,每個數(shù)據(jù)頁通過雙向鏈表連接。表數(shù)據(jù)訪問更快,但表更新代價高。
稀疏索引不會為每個搜索關(guān)鍵字創(chuàng)建索引記錄。搜索過程需要,我們首先按索引記錄進行操作,并按順序搜索,直到找到所需的數(shù)據(jù)為止。
31.簡述輔助索引與回表查詢
輔助索引是非聚集索引,葉子節(jié)點不包含記錄的全部數(shù)據(jù),包含了一個書簽用來告訴InnoDB哪里可以找到與索引相對應(yīng)的行數(shù)據(jù)。
通過輔助索引查詢,先通過書簽查到聚集索引,再根據(jù)聚集索引查對應(yīng)的值,需要兩次,也稱為回表查詢。
32.簡述聯(lián)合索引和最左匹配原則
聯(lián)合索引是指對表上的多個列的關(guān)鍵詞進行索引。
對于聯(lián)合索引的查詢,如果精確匹配聯(lián)合索引的左邊連續(xù)一列或者多列,則mysql會一直向右匹配直到遇到范圍查詢(>,<,between,like)就停止匹配。Mysql會對第一個索引字段數(shù)據(jù)進行排序,在第一個字段基礎(chǔ)上,再對第二個字段排序。
33.簡述覆蓋索引
覆蓋索引指一個索引包含或覆蓋了所有需要查詢的字段的值,不需要回表查詢,即索引本身存了對應(yīng)的值。
34.為什么數(shù)據(jù)庫不用紅黑樹用B+樹
紅黑樹的出度為 2,而 B Tree 的出度一般都非常大。紅黑樹的樹高 h 很明顯比 B Tree 大非常多,IO次數(shù)很多,導(dǎo)致會比較慢,因此檢索的次數(shù)也就更多。
B+Tree 相比于 B-Tree 更適合外存索引,擁有更大的出度,IO次數(shù)較少,檢索效率會更高。
35.基于主鍵索引的查詢和非主鍵索引的查詢有什么區(qū)別?
對于select * from 主鍵=XX,基于主鍵的普通查詢僅查找主鍵這棵樹,對于select * from 非主鍵=XX,基于非主鍵的查詢有可能存在回表過程(回到主鍵索引樹搜索的過程稱為回表),因為非主鍵索引葉子節(jié)點僅存主鍵值,無整行全部信息。
36.非主鍵索引的查詢一定會回表嗎?
不一定,當(dāng)查詢語句的要求字段全部命中索引,不用回表查詢。如select 主鍵 from 非主鍵=XX,此時非主鍵索引葉子節(jié)點即可拿到主鍵信息,不用回表。
鎖
1.分類
12. 行鎖和表鎖?
MyISAM和InnoDB存儲引擎使用的鎖:
-  MyISAM采用表級鎖(table-level locking)。 
-  InnoDB支持行級鎖(row-level locking)和表級鎖,默認(rèn)為行級鎖 表級鎖和行級鎖對比: 
-  表級鎖: Mysql中鎖定 粒度最大 的一種鎖,對當(dāng)前操作的整張表加鎖,實現(xiàn)簡單,資源消耗也比較少,加鎖快,不會出現(xiàn)死鎖。其鎖定粒度最大,觸發(fā)鎖沖突的概率最高,并發(fā)度最低,MyISAM和 InnoDB引擎都支持表級鎖。 
-  行級鎖: Mysql中鎖定 粒度最小 的一種鎖,只針對當(dāng)前操作的行進行加鎖。 行級鎖能大大減少數(shù)據(jù)庫操作的沖突。其加鎖粒度最小,并發(fā)度高,但加鎖的開銷也最大,加鎖慢,會出現(xiàn)死鎖。 InnoDB存儲引擎的鎖的算法有三種: 
-  Record lock:單個行記錄上的鎖 
-  Gap lock:間隙鎖,鎖定一個范圍,不包括記錄本身 
-  Next-key lock:record+gap 鎖定一個范圍,包含記錄本身 
13.行鎖,表鎖和頁鎖
1.行鎖
 行級鎖是Mysql中鎖定粒度最細(xì)的一種鎖,表示只針對當(dāng)前操作的行進行加鎖。行級鎖能大大減少數(shù)據(jù)庫操作的沖突。其加鎖粒度最小,但加鎖的開銷也最大。有可能會出現(xiàn)死鎖的情況。 行級鎖按照使用方式分為共享鎖和排他鎖。
共享鎖用法(S鎖 讀鎖):
若事務(wù)T對數(shù)據(jù)對象A加上S鎖,則事務(wù)T可以讀A但不能修改A,其他事務(wù)只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。這保證了其他事務(wù)可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。
select ... lock in share mode;共享鎖就是允許多個線程同時獲取一個鎖,一個鎖可以同時被多個線程擁有。
排它鎖用法(X 鎖 寫鎖):
若事務(wù)T對數(shù)據(jù)對象A加上X鎖,事務(wù)T可以讀A也可以修改A,其他事務(wù)不能再對A加任何鎖,直到T釋放A上的鎖。這保證了其他事務(wù)在T釋放A上的鎖之前不能再讀取和修改A。
select ... for update排它鎖,也稱作獨占鎖,一個鎖在某一時刻只能被一個線程占有,其它線程必須等待鎖被釋放之后才可能獲取到鎖。
2.表鎖
 表級鎖是mysql鎖中粒度最大的一種鎖,表示當(dāng)前的操作對整張表加鎖,資源開銷比行鎖少,不會出現(xiàn)死鎖的情況,但是發(fā)生鎖沖突的概率很大。被大部分的mysql引擎支持,MyISAM和InnoDB都支持表級鎖,但是InnoDB默認(rèn)的是行級鎖。
共享鎖用法:
LOCK TABLE table_name [ AS alias_name ] READ排它鎖用法:
LOCK TABLE table_name [AS alias_name][ LOW_PRIORITY ] WRITE解鎖用法:
unlock tables;3.頁鎖
 頁級鎖是MySQL中鎖定粒度介于行級鎖和表級鎖中間的一種鎖。表級鎖速度快,但沖突多,行級沖突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄。BDB支持頁級鎖
13.樂觀鎖和悲觀鎖?
樂觀鎖:每次去拿數(shù)據(jù)的時候都認(rèn)為別人不會修改,所以不會上鎖,但是在提交更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù)。
悲觀鎖:每次去拿數(shù)據(jù)的時候都認(rèn)為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會阻止,直到這個鎖被釋放。
數(shù)據(jù)庫的樂觀鎖需要自己實現(xiàn),在表里面添加一個 version 字段,每次修改成功值加 1,這樣每次修改的時候先對比一下,自己擁有的 version 和數(shù)據(jù)庫現(xiàn)在的 version 是否一致,如果不一致就不修改,這樣就實現(xiàn)了樂觀鎖。
18.MySQL的共享鎖排它鎖
共享鎖也稱為讀鎖,相互不阻塞,多個客戶在同一時刻可以同時讀取同一個資源而不相互干擾。排他鎖也稱為寫鎖,會阻塞其他的寫鎖和讀鎖,確保在給定時間內(nèi)只有一個用戶能執(zhí)行寫入并防止其他用戶讀取正在寫入的同一資源。
共享鎖又稱為讀鎖,簡稱S鎖,顧名思義,共享鎖就是多個事務(wù)對于同一數(shù)據(jù)可以共享一把鎖,都能訪問到數(shù)據(jù),但是只能讀不能修改。
排他鎖又稱為寫鎖,簡稱X鎖,顧名思義,排他鎖就是不能與其他所并存,如一個事務(wù)獲取了一個數(shù)據(jù)行的排他鎖,其他事務(wù)就不能再獲取該行的其他鎖,包括共享鎖和排他鎖,但是獲取排他鎖的事務(wù)是可以對數(shù)據(jù)就行讀取和修改。
對于共享鎖大家可能很好理解,就是多個事務(wù)只能讀數(shù)據(jù)不能改數(shù)據(jù),對于排他鎖大家的理解可能就有些差別,我當(dāng)初就犯了一個錯誤,以為排他鎖鎖住一行數(shù)據(jù)后,其他事務(wù)就不能讀取和修改該行數(shù)據(jù),其實不是這樣的。排他鎖指的是一個事務(wù)在一行數(shù)據(jù)加上排他鎖后,其他事務(wù)不能再在其上加其他的鎖。mysql InnoDB引擎默認(rèn)的修改數(shù)據(jù)語句,update,delete,insert都會自動給涉及到的數(shù)據(jù)加上排他鎖,select語句默認(rèn)不會加任何鎖類型,如果加排他鎖可以使用select …for update語句,加共享鎖可以使用select … lock in share mode語句。所以加過排他鎖的數(shù)據(jù)行在其他事務(wù)種是不能修改數(shù)據(jù)的,也不能通過for update和lock in share mode鎖的方式查詢數(shù)據(jù),但可以直接通過select …from…查詢數(shù)據(jù),因為普通查詢沒有任何鎖機制。
19.MySQL中的按粒度的鎖分類
表級鎖: 對當(dāng)前操作的整張表加鎖,實現(xiàn)簡單,加鎖快,但并發(fā)能力低。
行鎖: 鎖住某一行,如果表存在索引,那么記錄鎖是鎖在索引上的,如果表沒有索引,那么 InnoDB 會創(chuàng)建一個隱藏的聚簇索引加鎖。行級鎖能大大減少數(shù)據(jù)庫操作的沖突。其加鎖粒度最小,并發(fā)度高,但加鎖的開銷也最大,加鎖慢,會出現(xiàn)死鎖。
Gap 鎖:也稱為間隙鎖: 鎖定一個范圍但不包括記錄本身。其目的是為了防止同一事物的兩次當(dāng)前讀出現(xiàn)幻讀的情況。
Next-key Lock: 行鎖+gap鎖。
20.如何解決數(shù)據(jù)庫死鎖
其他
5.簡述事務(wù)
事務(wù)內(nèi)的語句要么全部執(zhí)行成功,要么全部執(zhí)行失敗。
事務(wù)滿足如下幾個特性:
- 原子性(Atomicity):一個事務(wù)中的所有操作要么全部完成,要么全部不完成。
- 一致性(Consistency):事務(wù)執(zhí)行前后數(shù)據(jù)庫的狀態(tài)保存一致。
- 隔離性(Isolation)多個并發(fā)事務(wù)對數(shù)據(jù)庫進行操作,事務(wù)間互不干擾。
- 持久性(Durability)事務(wù)執(zhí)行完畢,對數(shù)據(jù)的修改是永久的,即使系統(tǒng)故障也不會丟失
10.數(shù)據(jù)庫的事務(wù)隔離?
MySQL 的事務(wù)隔離是在 MySQL. ini 配置文件里添加的,在文件的最后添加:
transaction-isolation = REPEATABLE-READ
可用的配置值:READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE。
READ-UNCOMMITTED:未提交讀,最低隔離級別、事務(wù)未提交前,就可被其他事務(wù)讀取(會出現(xiàn)幻讀、臟讀、不可重復(fù)讀)。
READ-COMMITTED:提交讀,一個事務(wù)提交后才能被其他事務(wù)讀取到(會造成幻讀、不可重復(fù)讀)。
REPEATABLE-READ:可重復(fù)讀,默認(rèn)級別,一個事務(wù)執(zhí)行過程中看到的數(shù)據(jù)總是和事務(wù)啟動時看到的數(shù)據(jù)是一致的。在這個級別下事務(wù)未提交,做出的變更其它事務(wù)也看不到。
保證多次讀取同一個數(shù)據(jù)時,其值都和事務(wù)開始時候的內(nèi)容是一致,禁止讀取到別的事務(wù)未提交的數(shù)據(jù)(會造成幻讀)。
SERIALIZABLE:序列化,代價最高最可靠的隔離級別,該隔離級別能防止臟讀、不可重復(fù)讀、幻讀。
臟讀 :表示一個事務(wù)能夠讀取另一個事務(wù)中還未提交的數(shù)據(jù)。比如,某個事務(wù)嘗試插入記錄 A,此時該事務(wù)還未提交,然后另一個事務(wù)嘗試讀取到了記錄 A。
不可重復(fù)讀 :是指在一個事務(wù)內(nèi),多次讀同一數(shù)據(jù)。
幻讀 :指同一個事務(wù)內(nèi)多次查詢返回的結(jié)果集不一樣。比如同一個事務(wù) A 第一次查詢時候有 n 條記錄,但是第二次同等條件下查詢卻有 n+1 條記錄,這就好像產(chǎn)生了幻覺。發(fā)生幻讀的原因也是另外一個事務(wù)新增或者刪除或者修改了第一個事務(wù)結(jié)果集里面的數(shù)據(jù),同一個記錄的數(shù)據(jù)內(nèi)容被修改了,所有數(shù)據(jù)行的記錄就變多或者變少了。
1.數(shù)據(jù)庫的三范式是什么?
第一范式:強調(diào)的是列的原子性,即數(shù)據(jù)庫表的每一列都是不可分割的原子數(shù)據(jù)項。
第二范式:要求實體的屬性完全依賴于主關(guān)鍵字。所謂完全依賴是指不能存在僅依賴主關(guān)鍵字一部分的屬性。
第三范式:任何非主屬性不依賴于其它非主屬性。
2.一張自增表里面總共有 7 條數(shù)據(jù),刪除了最后 2 條數(shù)據(jù),重啟 MySQL 數(shù)據(jù)庫,又插入了一條數(shù)據(jù),此時 id 是幾?
表類型如果是 MyISAM ,那 id 就是 8。
表類型如果是 InnoDB,那 id 就是 6。
InnoDB 表只會把自增主鍵的最大 id 記錄在內(nèi)存中,所以重啟之后會導(dǎo)致最大 id 丟失。
3.如何獲取當(dāng)前數(shù)據(jù)庫版本?
使用 select version() 獲取當(dāng)前 MySQL 數(shù)據(jù)庫版本。
4.說一下 ACID 是什么?
Atomicity(原子性):一個事務(wù)(transaction)中的所有操作,或者全部完成,或者全部不完成,不會結(jié)束在中間某個環(huán)節(jié)。事務(wù)在執(zhí)行過程中發(fā)生錯誤,會被恢復(fù)(Rollback)到事務(wù)開始前的狀態(tài),就像這個事務(wù)從來沒有執(zhí)行過一樣。即,事務(wù)不可分割、不可約簡。
Consistency(一致性):在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預(yù)設(shè)約束、觸發(fā)器、級聯(lián)回滾等。
Isolation(隔離性):數(shù)據(jù)庫允許多個并發(fā)事務(wù)同時對其數(shù)據(jù)進行讀寫和修改的能力,隔離性可以防止多個事務(wù)并發(fā)執(zhí)行時由于交叉執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致。事務(wù)隔離分為不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重復(fù)讀(repeatable read)和串行化(Serializable)。
Durability(持久性):事務(wù)處理結(jié)束后,對數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會丟失。
6.char 和 varchar 的區(qū)別是什么?
char(n) :固定長度類型,比如訂閱 char(10),當(dāng)你輸入"abc"三個字符的時候,它們占的空間還是 10 個字節(jié),其他 7 個是空字節(jié)。
char 優(yōu)點:效率高;缺點:占用空間;適用場景:存儲密碼的 md5 值,固定長度的,使用 char 非常合適。
varchar(n) :可變長度,存儲的值是每個值占用的字節(jié)再加上一個用來記錄其長度的字節(jié)的長度。
所以,從空間上考慮 varcahr 比較合適;從效率上考慮 char 比較合適,二者使用需要權(quán)衡。
7.float 和 double 的區(qū)別是什么?
float 最多可以存儲 8 位的十進制數(shù),并在內(nèi)存中占 4 字節(jié)。
double 最可可以存儲 16 位的十進制數(shù),并在內(nèi)存中占 8 字節(jié)。
8.MySQL 的內(nèi)連接、左連接、右連接有什么區(qū)別?
內(nèi)連接關(guān)鍵字:inner join;左連接:left join;右連接:right join。
內(nèi)連接是把匹配的關(guān)聯(lián)數(shù)據(jù)顯示出來;左連接是左邊的表全部顯示出來,右邊的表顯示出符合條件的數(shù)據(jù);右連接正好相反。
9.怎么驗證 MySQL 的索引是否滿足需求?
使用 explain 查看 SQL 是如何執(zhí)行查詢語句的,從而分析你的索引是否滿足需求。
explain 語法:explain select * from table where type=1。
11.MySQL 常用的引擎?
InnoDB 引擎:InnoDB 引擎提供了對數(shù)據(jù)庫 acid 事務(wù)的支持,并且還提供了行級鎖和外鍵的約束,它的設(shè)計的目標(biāo)就是處理大數(shù)據(jù)容量的數(shù)據(jù)庫系統(tǒng)。MySQL 運行的時候,InnoDB 會在內(nèi)存中建立緩沖池,用于緩沖數(shù)據(jù)和索引。但是該引擎是不支持全文搜索,同時啟動也比較的慢,它是不會保存表的行數(shù)的,所以當(dāng)進行 select count(*) from table 指令的時候,需要進行掃描全表。由于鎖的粒度小,寫操作是不會鎖定全表的,所以在并發(fā)度較高的場景下使用會提升效率的。
MyIASM 引擎:MySQL 的默認(rèn)引擎,但不提供事務(wù)的支持,也不支持行級鎖和外鍵。因此當(dāng)執(zhí)行插入和更新語句時,即執(zhí)行寫操作的時候需要鎖定這個表,所以會導(dǎo)致效率會降低。不過和 InnoDB 不同的是,MyIASM 引擎是保存了表的行數(shù),于是當(dāng)進行 select count(*) from table 語句時,可以直接的讀取已經(jīng)保存的值而不需要進行掃描全表。所以,如果表的讀操作遠遠多于寫操作時,并且不需要事務(wù)的支持的,可以將 MyIASM 作為數(shù)據(jù)庫引擎的首選。
MySQL常見的三種存儲引擎(InnoDB、MyISAM、MEMORY)
InnoDB:支持事務(wù)處理,支持外鍵,支持崩潰修復(fù)能力和并發(fā)控制。如果需要對事務(wù)的完整性要求比較高(比如銀行),要求實現(xiàn)并發(fā)控制(比如售票),那選擇InnoDB有很大的優(yōu)勢。如果需要頻繁的更新、刪除操作的數(shù)據(jù)庫,也可以選擇InnoDB,因為支持事務(wù)的提交(commit)和回滾(rollback)。
MyISAM:插入數(shù)據(jù)快,空間和內(nèi)存使用比較低。如果表主要是用于插入新記錄和讀出記錄,那么選擇MyISAM能實現(xiàn)處理高效率。如果應(yīng)用的完整性、并發(fā)性要求比 較低,也可以使用。
MEMORY:所有的數(shù)據(jù)都在內(nèi)存中,數(shù)據(jù)的處理速度快,但是安全性不高。如果需要很快的讀寫速度,對數(shù)據(jù)的安全性要求較低,可以選擇MEMOEY。它對表的大小有要求,不能建立太大的表。所以,這類數(shù)據(jù)庫只使用在相對較小的數(shù)據(jù)庫表。
11.的MyISAM與InnoDB
MyISAM特點
- 不支持行鎖(MyISAM只有表鎖),讀取時對需要讀到的所有表加鎖,寫入時則對表加排他鎖;
- 不支持事務(wù)
- 不支持外鍵
- 不支持崩潰后的安全恢復(fù)
- 在表有讀取查詢的同時,支持往表中插入新紀(jì)錄
- 支持BLOB和TEXT的前500個字符索引,支持全文索引
- 支持延遲更新索引,極大地提升了寫入性能
- 對于不會進行修改的表,支持 壓縮表 ,極大地減少了磁盤空間的占用
InnoDB特點
- 支持行鎖,采用MVCC來支持高并發(fā),有可能死鎖
- 支持事務(wù)
- 支持外鍵
- 支持崩潰后的安全恢復(fù)
- 不支持全文索引
MyISAM和InnoDB兩者的應(yīng)用場景:
但是實際場景中,針對具體問題需要具體分析,一般而言可以遵循以下幾個問題:
 - 數(shù)據(jù)庫是否有外鍵?
 - 是否需要事務(wù)支持?
 - 是否需要全文索引?
 - 數(shù)據(jù)庫經(jīng)常使用什么樣的查詢模式?在寫多讀少的應(yīng)用中還是Innodb插入性能更穩(wěn)定,在并發(fā)情況下也能基本,如果是對讀取速度要求比較快的應(yīng)用還是選MyISAM。
 - 數(shù)據(jù)庫的數(shù)據(jù)有多大? 大尺寸傾向于innodb,因為事務(wù)日志,故障恢復(fù)。
14.MySQL 問題排查都有哪些手段?
使用 show processlist 命令查看當(dāng)前所有連接信息。
使用 explain 命令查詢 SQL 語句執(zhí)行計劃。
開啟慢查詢?nèi)罩?#xff0c;查看慢查詢的 SQL。
15.如何做 MySQL 的性能優(yōu)化?
為搜索字段創(chuàng)建索引。
避免使用 select *,列出需要查詢的字段。
垂直分割分表。
選擇正確的存儲引擎。
16.MySQL的架構(gòu)
MySQL可以分為應(yīng)用層,邏輯層,數(shù)據(jù)庫引擎層,物理層。
應(yīng)用層:負(fù)責(zé)和客戶端,響應(yīng)客戶端請求,建立連接,返回數(shù)據(jù)。
邏輯層:包括SQK接口,解析器,優(yōu)化器,Cache與buffer。
數(shù)據(jù)庫引擎層:有常見的MyISAM,InnoDB等等。
物理層:負(fù)責(zé)文件存儲,日志等等。
17.執(zhí)行SQL語言的過程
21.簡述InnoDB存儲引擎
InnoDB 是 MySQL 的默認(rèn)事務(wù)型引擎,支持事務(wù),表是基于聚簇索引建立的。支持表級鎖和行級鎖,支持外鍵,適合數(shù)據(jù)增刪改查都頻繁的情況。
InnoDB 采用 MVCC 來支持高并發(fā),并且實現(xiàn)了四個標(biāo)準(zhǔn)的隔離級別。其默認(rèn)級別是 REPEATABLE READ,并通過間隙鎖策略防止幻讀,間隙鎖使 InnoDB 不僅僅鎖定查詢涉及的行,還會對索引中的間隙進行鎖定防止幻行的插入。
22.簡述MyISAM存儲引擎
MySQL5.1及之前,MyISAM 是默認(rèn)存儲引擎。MyISAM不支持事務(wù),Myisam支持表級鎖,不支持行級鎖,表不支持外鍵,該存儲引擎存有表的行數(shù),count運算會更快。適合查詢頻繁,不適合對于增刪改要求高的情況
23.簡述Memory存儲引擎
Memory存儲引擎將所有數(shù)據(jù)都保存在內(nèi)存,不需要磁盤 IO。支持哈希索引,因此查找速度極快。Memory 表使用表級鎖,因此并發(fā)寫入的性能較低。
37.簡述MySQL使用EXPLAIN 的關(guān)鍵字段
explain關(guān)鍵字用于分析sql語句的執(zhí)行情況,可以通過他進行sql語句的性能分析。
type:表示連接類型,從好到差的類型排序為
- system:系統(tǒng)表,數(shù)據(jù)已經(jīng)加載到內(nèi)存里。
- const:常量連接,通過索引一次就找到。
- eq_ref:唯一性索引掃描,返回所有匹配某個單獨值的行。
- ref:非主鍵非唯一索引等值掃描,const或eq_ref改為普通非唯一索引。
- range:范圍掃描,在索引上掃碼特定范圍內(nèi)的值。
- index:索引樹掃描,掃描索引上的全部數(shù)據(jù)。
- all:全表掃描。
key:顯示MySQL實際決定使用的鍵。
key_len:顯示MySQL決定使用的鍵長度,長度越短越好
Extra:額外信息
- Using filesort:MySQL使用外部的索引排序,很慢需要優(yōu)化。
- Using temporary:使用了臨時表保存中間結(jié)果,很慢需要優(yōu)化。
- Using index:使用了覆蓋索引。
- Using where:使用了where。
38.簡述MySQL優(yōu)化流程
39.簡述MySQL中的日志log
redo log: 存儲引擎級別的log(InnoDB有,MyISAM沒有),該log關(guān)注于事務(wù)的恢復(fù).在重啟mysql服務(wù)的時候,根據(jù)redo log進行重做,從而使事務(wù)有持久性。
undo log:是存儲引擎級別的log(InnoDB有,MyISAM沒有)保證數(shù)據(jù)的原子性,該log保存了事務(wù)發(fā)生之前的數(shù)據(jù)的一個版本,可以用于回滾,是MVCC的重要實現(xiàn)方法之一。
bin log:數(shù)據(jù)庫級別的log,關(guān)注恢復(fù)數(shù)據(jù)庫的數(shù)據(jù)。
40.數(shù)據(jù)庫中多個事務(wù)同時進行可能會出現(xiàn)什么問題?
- 丟失修改
- 臟讀:當(dāng)前事務(wù)可以查看到別的事務(wù)未提交的數(shù)據(jù)。
- 不可重讀:在同一事務(wù)中,使用相同的查詢語句,同一數(shù)據(jù)資源莫名改變了。
- 幻讀:在同一事務(wù)中,使用相同的查詢語句,莫名多出了一些之前不存在的數(shù)據(jù),或莫名少了一些原先存在的數(shù)據(jù)。
41.什么是MVCC?
MVCC為多版本并發(fā)控制,即同一條記錄在系統(tǒng)中存在多個版本。其存在目的是在保證數(shù)據(jù)一致性的前提下提供一種高并發(fā)的訪問性能。對數(shù)據(jù)讀寫在不加讀寫鎖的情況下實現(xiàn)互不干擾,從而實現(xiàn)數(shù)據(jù)庫的隔離性,在事務(wù)隔離級別為讀提交和可重復(fù)讀中使用到。
在InnoDB中,事務(wù)在開始前會向事務(wù)系統(tǒng)申請一個事務(wù)ID,該ID是按申請順序嚴(yán)格遞增的。每行數(shù)據(jù)具有多個版本,每次事務(wù)更新數(shù)據(jù)都會生成新的數(shù)據(jù)版本,而不會直接覆蓋舊的數(shù)據(jù)版本。數(shù)據(jù)的行結(jié)構(gòu)中包含多個信息字段。其中實現(xiàn)MVCC的主要涉及最近更改該行數(shù)據(jù)的事務(wù)ID(DB_TRX_ID)和可以找到歷史數(shù)據(jù)版本的指針(DB_ROLL_PTR)。InnoDB在每個事務(wù)開啟瞬間會為其構(gòu)造一個記錄當(dāng)前已經(jīng)開啟但未提交的事務(wù)ID的視圖數(shù)組。通過比較鏈表中的事務(wù)ID與該行數(shù)據(jù)的值與對應(yīng)的DB_TRX_ID,并通過DB_ROLL_PTR找到歷史數(shù)據(jù)的值以及對應(yīng)的DB_TRX_ID來決定當(dāng)前版本的數(shù)據(jù)是否應(yīng)該被當(dāng)前事務(wù)所見。最終實現(xiàn)在不加鎖的情況下保證數(shù)據(jù)的一致性。
42.讀提交和可重復(fù)讀都基于MVCC實現(xiàn),有什么區(qū)別?
在可重復(fù)讀級別下,只會在事務(wù)開始前創(chuàng)建視圖,事務(wù)中后續(xù)的查詢共用一個視圖。而讀提交級別下每個語句執(zhí)行前都會創(chuàng)建新的視圖。因此對于可重復(fù)讀,查詢只能看到事務(wù)創(chuàng)建前就已經(jīng)提交的數(shù)據(jù)。而對于讀提交,查詢能看到每個語句啟動前已經(jīng)提交的數(shù)據(jù)。
43.InnoDB如何保證事務(wù)的原子性、持久性和一致性?
利用undo log保障原子性。該log保存了事務(wù)發(fā)生之前的數(shù)據(jù)的一個版本,可以用于回滾,從而保證事務(wù)原子性。
利用redo log保證事務(wù)的持久性,該log關(guān)注于事務(wù)的恢復(fù).在重啟mysql服務(wù)的時候,根據(jù)redo log進行重做,從而使事務(wù)有持久性。
利用undo log+redo log保障一致性。事務(wù)中的執(zhí)行需要redo log,如果執(zhí)行失敗,需要undo log 回滾。
44.MySQL是如何保證主備一致的?
MySQL通過binlog(二進制日志)實現(xiàn)主備一致。binlog記錄了所有修改了數(shù)據(jù)庫或可能修改數(shù)據(jù)庫的語句,而不會記錄select、show這種不會修改數(shù)據(jù)庫的語句。在備份的過程中,主庫A會有一個專門的線程將主庫A的binlog發(fā)送給 備庫B進行備份。其中binlog有三種記錄格式:
45.redo log與binlog的區(qū)別?
46.crash-safe能力是什么?
InnoDB通過redo log保證即使數(shù)據(jù)庫發(fā)生異常重啟,之前提交的記錄都不會丟失,這個能力稱為crash-safe。
47.WAL技術(shù)是什么?
WAL的全稱是Write-Ahead Logging,它的關(guān)鍵點就是先寫日志,再寫磁盤。事務(wù)在提交寫入磁盤前,會先寫到redo log里面去。如果直接寫入磁盤涉及磁盤的隨機I/O訪問,涉及磁盤隨機I/O訪問是非常消耗時間的一個過程,相比之下先寫入redo log,后面再找合適的時機批量刷盤能提升性能。
48.兩階段提交是什么?
為了保證binlog和redo log兩份日志的邏輯一致,最終保證恢復(fù)到主備數(shù)據(jù)庫的數(shù)據(jù)是一致的,采用兩階段提交的機制。
49.只靠binlog可以支持?jǐn)?shù)據(jù)庫崩潰恢復(fù)嗎?
不可以。 歷史原因:
50.簡述MySQL主從復(fù)制
MySQL提供主從復(fù)制功能,可以方便的實現(xiàn)數(shù)據(jù)的多處自動備份,不僅能增加數(shù)據(jù)庫的安全性,還能進行讀寫分離,提升數(shù)據(jù)庫負(fù)載性能。
主從復(fù)制流程:
讀寫分離:即只在MySQL主庫上寫,只在MySQL從庫上讀,以減少數(shù)據(jù)庫壓力,提高性能。
51.緩存
my.cnf加入以下配置,重啟Mysql開啟查詢緩存
query_cache_type=1 query_cache_size=600000Mysql執(zhí)行以下命令也可以開啟查詢緩存
set global query_cache_type=1; set global query_cache_size=600000;如上,開啟查詢緩存后在同樣的查詢條件以及數(shù)據(jù)情況下,會直接在緩存中返回結(jié)果。這里的查詢條件包括查詢本身、當(dāng)前要查詢的數(shù)據(jù)庫、客戶端協(xié)議版本號等一些可能影響結(jié)果的信息。因此任何兩個查詢在任何字符上的不同都會導(dǎo)致緩存不命中。此外,如果查詢中包含任何用戶自定義函數(shù)、存儲函數(shù)、用戶變量、臨時表、Mysql庫中的系統(tǒng)表,其查詢結(jié)果也不會被緩存。
緩存建立之后,Mysql的查詢緩存系統(tǒng)會跟蹤查詢中涉及的每張表,如果這些表(數(shù)據(jù)或結(jié)構(gòu))發(fā)生變化,那么和這張表相關(guān)的所有緩存數(shù)據(jù)都將失效。
緩存雖然能夠提升數(shù)據(jù)庫的查詢性能,但是緩存同時也帶來了額外的開銷,每次查詢后都要做一次緩存操作,失效后還要銷毀。 因此,開啟緩存查詢要謹(jǐn)慎,尤其對于寫密集的應(yīng)用來說更是如此。如果開啟,要注意合理控制緩存空間大小,一般來說其大小設(shè)置為幾十MB比較合適。此外,還可以通過sql_cache和sql_no_cache來控制某個查詢語句是否需要緩存:
select sql_no_cache count(*) from usr;52.大表優(yōu)化
當(dāng)MySQL單表記錄數(shù)過大時,數(shù)據(jù)庫的CRUD性能會明顯下降,一些常見的優(yōu)化措施如下:
限定數(shù)據(jù)的范圍: 務(wù)必禁止不帶任何限制數(shù)據(jù)范圍條件的查詢語句。比如:我們當(dāng)用戶在查詢訂單歷史的時候,我們可以控制在一個月的范圍內(nèi)。;
讀/寫分離: 經(jīng)典的數(shù)據(jù)庫拆分方案,主庫負(fù)責(zé)寫,從庫負(fù)責(zé)讀;
緩存: 使用MySQL的緩存,另外對重量級、更新少的數(shù)據(jù)可以考慮使用應(yīng)用級別的緩存;
垂直分區(qū):
根據(jù)數(shù)據(jù)庫里面數(shù)據(jù)表的相關(guān)性進行拆分。 例如,用戶表中既有用戶的登錄信息又有用戶的基本信息,可以將用戶表拆分成兩個單獨的表,甚至放到單獨的庫做分庫。
簡單來說垂直拆分是指數(shù)據(jù)表列的拆分,把一張列比較多的表拆分為多張表。 如下圖所示,這樣來說大家應(yīng)該就更容易理解了。
垂直拆分的優(yōu)點: 可以使得行數(shù)據(jù)變小,在查詢時減少讀取的Block數(shù),減少I/O次數(shù)。此外,垂直分區(qū)可以簡化表的結(jié)構(gòu),易于維護。
垂直拆分的缺點: 主鍵會出現(xiàn)冗余,需要管理冗余列,并會引起Join操作,可以通過在應(yīng)用層進行Join來解決。此外,垂直分區(qū)會讓事務(wù)變得更加復(fù)雜;
? 5. 水平分區(qū):
保持?jǐn)?shù)據(jù)表結(jié)構(gòu)不變,通過某種策略存儲數(shù)據(jù)分片。這樣每一片數(shù)據(jù)分散到不同的表或者庫中,達到了分布式的目的。 水平拆分可以支撐非常大的數(shù)據(jù)量。
水平拆分是指數(shù)據(jù)表行的拆分,表的行數(shù)超過200萬行時,就會變慢,這時可以把一張的表的數(shù)據(jù)拆成多張表來存放。舉個例子:我們可以將用戶信息表拆分成多個用戶信息表,這樣就可以避免單一表數(shù)據(jù)量過大對性能造成影響。
水品拆分可以支持非常大的數(shù)據(jù)量。需要注意的一點是:分表僅僅是解決了單一表數(shù)據(jù)過大的問題,但由于表的數(shù)據(jù)還是在同一臺機器上,其實對于提升MySQL 并發(fā)能力沒有什么意義,所以 水品拆分最好分庫 。
水平拆分能夠 支持非常大的數(shù)據(jù)量存儲,應(yīng)用端改造也少,但 分片事務(wù)難以解決 ,跨界點Join 性能較差,邏輯復(fù)雜。《Java工程師修煉之道》的作者推薦 盡量不要對數(shù)據(jù)進行分片,因為拆分會帶來邏輯、部署、運維的各種復(fù)雜度 ,一般的數(shù)據(jù)表在優(yōu)化得當(dāng)?shù)那闆r下支撐千萬以下的數(shù)據(jù)量是沒有太大問題的。如果實在要分片,盡量選擇客戶端分片架構(gòu),這樣可以減少一次和中間件的網(wǎng)絡(luò) I/O。
下面補充一下數(shù)據(jù)庫分片的兩種常見方案:
- 客戶端代理: 分片邏輯在應(yīng)用端,封裝在jar包中,通過修改或者封裝JDBC層來實現(xiàn)。 當(dāng)當(dāng)網(wǎng)的 Sharding-JDBC 、阿里的TDDL是兩種比較常用的實現(xiàn)。
- 中間件代理: 在應(yīng)用和數(shù)據(jù)中間加了一個代理層。分片邏輯統(tǒng)一維護在中間件服務(wù)中。 我們現(xiàn)在談的 Mycat、360的Atlas、網(wǎng)易的DDB等等都是這種架構(gòu)的實現(xiàn)。
52.查詢語句不同元素(where、jion、limit、group by、having等等)執(zhí)行先后順序?
一個查詢語句同時出現(xiàn)了where,group by,having,order by的時候,執(zhí)行順序和編寫順序是:
1.執(zhí)行where xx對全表數(shù)據(jù)做篩選,返回第1個結(jié)果集。
2.針對第1個結(jié)果集使用group by分組,返回第2個結(jié)果集。
3.針對第2個結(jié)果集中的每1組數(shù)據(jù)執(zhí)行select xx,有幾組就執(zhí)行幾次,返回第3個結(jié)果集。
4.針對第3個結(jié)集執(zhí)行having xx進行篩選,返回第4個結(jié)果集。
5.針對第4個結(jié)果集排序。
通過一個順口溜總結(jié)下順序:我(W)哥(G)是(SH)偶(O)像。按照執(zhí)行順序的關(guān)鍵詞首字母分別是W(where)->G(Group)->S(Select)->H(Having)->O(Order),對應(yīng)漢語首字母可以編成容易記憶的順口溜:我(W)哥(G)是(SH)偶(O)像
53.什么是臨時表,臨時表什么時候刪除?
什么是臨時表:MySQL用于存儲一些中間結(jié)果集的表,臨時表只在當(dāng)前連接可見,當(dāng)關(guān)閉連接時,Mysql會自動刪除表并釋放所有空間。為什么會產(chǎn)生臨時表:一般是由于復(fù)雜的SQL導(dǎo)致臨時表被大量創(chuàng)建
臨時表分為兩種,一種是內(nèi)存臨時表,一種是磁盤臨時表。內(nèi)存臨時表采用的是memory存儲引擎,磁盤臨時表采用的是myisam存儲引擎(磁盤臨時表也可以使用innodb存儲引擎,通過internal_tmp_disk_storage_engine參數(shù)來控制使用哪種存儲引擎,從mysql5.7.6之后默認(rèn)為innodb存儲引擎,之前版本默認(rèn)為myisam存儲引擎)。分別通過Created_tmp_disk_tables 和 Created_tmp_tables 兩個參數(shù)來查看產(chǎn)生了多少磁盤臨時表和所有產(chǎn)生的臨時表(內(nèi)存和磁盤)。
內(nèi)存臨時表空間的大小由兩個參數(shù)控制:tmp_table_size 和 max_heap_table_size 。一般來說是通過兩個參數(shù)中較小的數(shù)來控制內(nèi)存臨時表空間的最大值,而對于開始在內(nèi)存中創(chuàng)建的臨時表,后來由于數(shù)據(jù)太大轉(zhuǎn)移到磁盤上的臨時表,只由max_heap_table_size參數(shù)控制。針對直接在磁盤上產(chǎn)生的臨時表,沒有大小控制。
下列操作會使用到臨時表:
-  union查詢 
-  對于視圖的操作,比如使用一些TEMPTABLE算法、union或aggregation 
-  子查詢 
-  join 包括not in、exist等 
-  查詢產(chǎn)生的派生表 
-  復(fù)雜的group by 和 order by 
-  Insert select 同一個表,mysql會產(chǎn)生一個臨時表緩存select的行 
-  多個表更新 
-  GROUP_CONCAT() 或者 COUNT(DISTINCT) 語句 Mysql還會阻止內(nèi)存表空間的使用,直接使用磁盤臨時表: 
-  表中含有BLOB或者TEXT列 
-  使用union或者union all時,select子句有大于512字節(jié)的列 
-  Show columns或者 desc 表的時候,有LOB或者TEXT 
-  GROUP BY 或者 DISTINCT 子句中包含長度大于512字節(jié)的列 
54.非關(guān)系型數(shù)據(jù)庫和關(guān)系型數(shù)據(jù)庫區(qū)別,優(yōu)勢比較?
關(guān)系型數(shù)據(jù)庫和非關(guān)系型區(qū)別
關(guān)系型數(shù)據(jù)庫
關(guān)系型數(shù)據(jù)庫,是指采用了關(guān)系模型來組織數(shù)據(jù)的數(shù)據(jù)庫,其以行和列的形式存儲數(shù)據(jù),以便于用戶理解,關(guān)系型數(shù)據(jù)庫這一系列的行和列被稱為表,一組表組成了數(shù)據(jù)庫。用戶通過查詢來檢索數(shù)據(jù)庫中的數(shù)據(jù),而查詢是一個用于限定數(shù)據(jù)庫中某些區(qū)域的執(zhí)行代碼。關(guān)系模型可以簡單理解為二維表格模型,而一個關(guān)系型數(shù)據(jù)庫就是由二維表及其之間的關(guān)系組成的一個數(shù)據(jù)組織。
當(dāng)前主流的關(guān)系型數(shù)據(jù)庫:
 Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL等。
非關(guān)系型數(shù)據(jù)庫
結(jié)構(gòu)不固定,集合內(nèi)數(shù)據(jù)字段可以不一樣,自由度高,可以減少一些時間和空間的開銷。
四大類型:
 鍵值對存儲(key-value),文檔存儲(document store:mongodb),基于列的數(shù)據(jù)庫(column-oriented),還有就是圖形數(shù)據(jù)庫(graph database)
主流的非關(guān)系型數(shù)據(jù)庫有 NoSql、MongoDB、Cloudant、
特征:
 1、使用鍵值對存儲數(shù)據(jù);
 2、分布式;
 3、一般不支持ACID特性;
 4、非關(guān)系型數(shù)據(jù)庫嚴(yán)格上不是一種數(shù)據(jù)庫,應(yīng)該是一種數(shù)據(jù)結(jié)構(gòu)化存儲方法的集合。
非關(guān)系型數(shù)據(jù)庫:
 NoSql、Cloudant。
 臨時性鍵值存儲(memcached、Redis)、永久性鍵值存儲(ROMA、Redis)、面向文檔的數(shù)據(jù)庫(MongoDB、CouchDB)、面向列的數(shù)據(jù)庫(Cassandra、HBase)
非關(guān)系型數(shù)據(jù)庫的優(yōu)勢:
 1、格式靈活:存儲數(shù)據(jù)的格式可以是key,value形式、文檔形式、圖片形式等等,文檔形式、圖片形式等等,使用靈活,應(yīng)用場景廣泛,而關(guān)系型數(shù)據(jù)庫則只支持基礎(chǔ)類型。
 2、速度快:nosql可以使用硬盤或者隨機存儲器作為載體,而關(guān)系型數(shù)據(jù)庫只能使用硬盤;
 3、高擴展性,基于鍵值對,數(shù)據(jù)之間沒有耦合性,所以非常容易水平擴展。
 4、成本低:nosql數(shù)據(jù)庫部署簡單,基本都是開源軟件。
 5、易于數(shù)據(jù)的分散,分布式數(shù)據(jù)庫
 各個數(shù)據(jù)之間存在關(guān)聯(lián)是關(guān)系型數(shù)據(jù)庫得名的主要原因,為了進行join處理,關(guān)系型數(shù)據(jù)庫不得不把數(shù)據(jù)存儲在同一個服務(wù)器內(nèi),這不利于數(shù)據(jù)的分散,這也是關(guān)系型數(shù)據(jù)庫并不擅長大數(shù)據(jù)量的寫入處理的原因。相反NoSQL數(shù)據(jù)庫原本就不支持Join處理,各個數(shù)據(jù)都是獨立設(shè)計的,很容易把數(shù)據(jù)分散在多個服務(wù)器上,故減少了每個服務(wù)器上的數(shù)據(jù)量,即使要處理大量數(shù)據(jù)的寫入,也變得更加容易,數(shù)據(jù)的讀入操作當(dāng)然也同樣容易。
缺點:
 1、不提供關(guān)系型數(shù)據(jù)庫對事物的處理。NoSQL數(shù)據(jù)庫只應(yīng)用在特定領(lǐng)域,基本上不進行復(fù)雜的處理,但它恰恰彌補了之前所列舉的關(guān)系型數(shù)據(jù)庫的不足之處。
關(guān)系型數(shù)據(jù)庫最典型的數(shù)據(jù)結(jié)構(gòu)是表,由二維表及其之間的聯(lián)系所組成的一個數(shù)據(jù)組織
 關(guān)系型數(shù)據(jù)庫的優(yōu)勢:
 1、易于維護:都是使用表結(jié)構(gòu),格式一致;
 2、使用方便:SQL語言通用,可用于復(fù)雜查詢;
 3、復(fù)雜操作:支持SQL,可以進行Join等復(fù)雜查詢,可用于一個表以及多個表之間非常復(fù)雜的查詢。
 \3. 事務(wù)支持使得對于安全性能很高的數(shù)據(jù)訪問要求得以實現(xiàn)。
 \4. 由于以標(biāo)準(zhǔn)化為前提,數(shù)據(jù)更新的開銷很小(相同的字段基本上都只有一處)
缺點(不擅長):
 1、讀寫性能比較差,尤其是海量數(shù)據(jù)的高效率讀寫;
 2、固定的表結(jié)構(gòu),靈活度稍欠;
 3、高并發(fā)讀寫需求,傳統(tǒng)關(guān)系型數(shù)據(jù)庫來說,硬盤I/O是一個很大的瓶頸。
總結(jié)
 
                            
                        - 上一篇: vue面试题,知识点汇总(有答案)
- 下一篇: 详解Vuex常见问题、深入理解Vuex
