mysql面试考点_mysql面试知识点
1 引擎-MyISAM和InnoDB的區(qū)別
a?是否支持行級(jí)鎖?:
MyISAM 只有表級(jí)鎖(table-level locking),
而InnoDB 支持行級(jí)鎖(row-level locking)和表級(jí)鎖,默認(rèn)為行級(jí)鎖。
b?是否支持事務(wù)和崩潰后的安全恢復(fù):
MyISAM?強(qiáng)調(diào)的是性能,每次查詢(xún)具有原子性,其執(zhí)行速度比InnoDB類(lèi)型更快,但是不提供事務(wù)支持。
但是InnoDB?提供事務(wù)支持事務(wù),外部鍵等高級(jí)數(shù)據(jù)庫(kù)功能。 具有事務(wù)(commit)、回滾(rollback)和崩潰修復(fù)能力(crash recovery capabilities)的事務(wù)安全(transaction-safe (ACID compliant))型表。
c 是否支持外鍵:
MyISAM不支持,而InnoDB支持。
d 是否支持MVCC?:
僅 InnoDB 支持。應(yīng)對(duì)高并發(fā)事務(wù), MVCC比單純的加鎖更高效;MVCC只在?READ COMMITTED?和?REPEATABLE READ?兩個(gè)隔離級(jí)別下工作;MVCC可以使用 樂(lè)觀(optimistic)鎖 和 悲觀(pessimistic)鎖來(lái)實(shí)現(xiàn);各數(shù)據(jù)庫(kù)中MVCC實(shí)現(xiàn)并不統(tǒng)一。
e 文件:
Innodb 創(chuàng)建表后生成的文件有:【聚簇索引】--【只在主鍵索引樹(shù)的葉子節(jié)點(diǎn)存儲(chǔ)了具體數(shù)據(jù):節(jié)省磁盤(pán)】
frm:創(chuàng)建表的語(yǔ)句
idb:表里面的數(shù)據(jù)+索引文件
Myisam 創(chuàng)建表后生成的文件有:【非聚簇索引】---【查詢(xún)性能高】
frm:創(chuàng)建表的語(yǔ)句
MYD:表里面的數(shù)據(jù)文件(myisam data)
MYI:表里面的索引文件(myisam index)
f 樹(shù)節(jié)點(diǎn)值:
MyISAM:B+Tree葉節(jié)點(diǎn)的data域存放的是數(shù)據(jù)記錄的地址。在索引檢索的時(shí)候,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其 data 域的值,然后以 data 域的值為地址讀取相應(yīng)的數(shù)據(jù)記錄。這被稱(chēng)為“非聚簇索引”。
InnoDB:其數(shù)據(jù)文件本身就是索引文件。相比MyISAM,索引文件和數(shù)據(jù)文件是分離的。InnoDB表數(shù)據(jù)文件本身就是按B+Tree組織的一個(gè)索引結(jié)構(gòu),樹(shù)的葉節(jié)點(diǎn)data域保存了完整的數(shù)據(jù)記錄。這個(gè)索引的key是數(shù)據(jù)表的主鍵,因此InnoDB表數(shù)據(jù)文件本身就是主索引。這被稱(chēng)為“聚簇索引(或聚集索引)”。而其余的索引都作為輔助索引,輔助索引的data域存儲(chǔ)相應(yīng)記錄主鍵的值而不是地址,這也是和MyISAM不同的地方。在根據(jù)主索引搜索時(shí),直接找到key所在的節(jié)點(diǎn)即可取出數(shù)據(jù);在根據(jù)輔助索引查找時(shí),則需要先取出主鍵的值,再走一遍主索引。?因此,在設(shè)計(jì)表的時(shí)候,不建議使用過(guò)長(zhǎng)的字段作為主鍵,也不建議使用非單調(diào)的字段作為主鍵,這樣會(huì)造成主索引頻繁分裂。
2 索引
MySQL索引使用的數(shù)據(jù)結(jié)構(gòu)主要有BTree索引?和?哈希索引?。
對(duì)于哈希索引來(lái)說(shuō),底層的數(shù)據(jù)結(jié)構(gòu)就是哈希表,因此在絕大多數(shù)需求為單條記錄查詢(xún)的時(shí)候,可以選擇哈希索引,查詢(xún)性能最快;其余大部分場(chǎng)景,建議選擇BTree索引。
BTree索引使用的是B樹(shù)中的B+Tree,但對(duì)于主要的兩種存儲(chǔ)引擎的實(shí)現(xiàn)方式是不同的。
索引結(jié)構(gòu):【B+樹(shù)】
1.二叉查找樹(shù)也叫二叉排序樹(shù),時(shí)間復(fù)雜度取決于樹(shù)高,為O(lgn)。但是樹(shù)可能不平衡,退化為鏈表,時(shí)間復(fù)雜度為O(n)
2.平衡二叉樹(shù),做旋轉(zhuǎn)操作,所有節(jié)點(diǎn)的左右子樹(shù)高度不能超過(guò)1,時(shí)間復(fù)雜度O(lgn)。當(dāng)插入數(shù)據(jù)時(shí),需要1次旋轉(zhuǎn)維持平衡。刪除數(shù)據(jù)時(shí),需要O(lgn)次維持平衡。
3.紅黑樹(shù),根到葉子的最長(zhǎng)的可能路徑不多于最短的可能路徑的兩倍長(zhǎng)。插入或者刪除,O(1)次的旋轉(zhuǎn)或者變色。但是查詢(xún)慢。
4.B(B-)樹(shù),每個(gè)非葉節(jié)點(diǎn)有多個(gè)子樹(shù)。矮胖子。局部性原理。緩存命中率高。每個(gè)節(jié)點(diǎn)存儲(chǔ)真實(shí)的數(shù)據(jù)。
5.B+樹(shù),只有葉子節(jié)點(diǎn)存儲(chǔ)真實(shí)的數(shù)據(jù),非葉子節(jié)點(diǎn)只存儲(chǔ)鍵。真實(shí)數(shù)據(jù)包括行的全部數(shù)據(jù)、主鍵、地址等。葉子節(jié)點(diǎn)之間通過(guò)雙向鏈表鏈接。
與B樹(shù)相比,優(yōu)勢(shì):
更少的IO次數(shù)。每個(gè)節(jié)點(diǎn)存儲(chǔ)的記錄數(shù)多,訪問(wèn)時(shí)所需要的IO次數(shù)更少。這樣訪問(wèn)局部性原理的利用更好,緩存命中率更高。
更適用范圍查詢(xún)。只對(duì)葉節(jié)點(diǎn)的指針鏈表進(jìn)行遍歷即可。
更穩(wěn)定的查詢(xún)效率:復(fù)雜度穩(wěn)定為樹(shù)高,因?yàn)樗袛?shù)據(jù)都在葉節(jié)點(diǎn)。
劣勢(shì):
鍵重復(fù)時(shí),占用空間大。
因此,最大優(yōu)勢(shì)在于樹(shù)高更小。B+樹(shù)高度一般在2-4層。樹(shù)高由階數(shù)決定,階數(shù)越大樹(shù)越矮;而階數(shù)的大小又取決于每個(gè)節(jié)點(diǎn)可以存儲(chǔ)多少條記錄。
Innodb中每個(gè)節(jié)點(diǎn)使用一個(gè)頁(yè)(page),頁(yè)的大小為16KB,其中元數(shù)據(jù)只占大約128字節(jié)左右(包括文件管理頭信息、頁(yè)面頭信息等等),大多數(shù)空間都用來(lái)存儲(chǔ)數(shù)據(jù)。
對(duì)于非葉節(jié)點(diǎn),記錄只包含索引的鍵和指向下一層節(jié)點(diǎn)的指針。假設(shè)每個(gè)非葉節(jié)點(diǎn)頁(yè)面存儲(chǔ)1000條記錄,則每條記錄大約占用16字節(jié);當(dāng)索引是整型或較短的字符串時(shí),這個(gè)假設(shè)是合理的。延伸一下,我們經(jīng)常聽(tīng)到建議說(shuō)索引列長(zhǎng)度不應(yīng)過(guò)大,原因就在這里:索引列太長(zhǎng),每個(gè)節(jié)點(diǎn)包含的記錄數(shù)太少,會(huì)導(dǎo)致樹(shù)太高,索引的效果會(huì)大打折扣,而且索引還會(huì)浪費(fèi)更多的空間。
對(duì)于葉節(jié)點(diǎn),記錄包含了索引的鍵和值(值可能是行的主鍵、一行完整數(shù)據(jù)等,具體見(jiàn)前文),數(shù)據(jù)量更大。這里假設(shè)每個(gè)葉節(jié)點(diǎn)頁(yè)面存儲(chǔ)100條記錄(實(shí)際上,當(dāng)索引為聚簇索引時(shí),這個(gè)數(shù)字可能不足100;當(dāng)索引為輔助索引時(shí),這個(gè)數(shù)字可能遠(yuǎn)大于100;可以根據(jù)實(shí)際情況進(jìn)行估算)。
對(duì)于一顆3層B+樹(shù),第一層(根節(jié)點(diǎn))有1個(gè)頁(yè)面,可以存儲(chǔ)1000條記錄;第二層有1000個(gè)頁(yè)面,可以存儲(chǔ)1000*1000條記錄;第三層(葉節(jié)點(diǎn))有1000*1000個(gè)頁(yè)面,每個(gè)頁(yè)面可以存儲(chǔ)100條記錄,因此可以存儲(chǔ)1000*1000*100條記錄,即1億條。而對(duì)于二叉樹(shù),存儲(chǔ)1億條記錄則需要26層左右。
那,為什么使用B+樹(shù),不用hash呢?
1.hash需要把全部數(shù)據(jù)加載到內(nèi)存中,如果數(shù)據(jù)量大,將非常消耗內(nèi)存。采用B+樹(shù),按照節(jié)點(diǎn)分段加載,會(huì)減少內(nèi)存消耗。
2.唯一查找一個(gè)值時(shí),hash更快。但是數(shù)據(jù)庫(kù)中經(jīng)常查詢(xún)多條數(shù)據(jù),由于B+樹(shù)數(shù)據(jù)的有序性,葉子節(jié)點(diǎn)有鏈表相連,查詢(xún)效率會(huì)快很多。
3 事務(wù)
事務(wù)是邏輯上的一組操作,要么都執(zhí)行,要么都不執(zhí)行。
事務(wù)最經(jīng)典也經(jīng)常被拿出來(lái)說(shuō)例子就是轉(zhuǎn)賬了。假如小明要給小紅轉(zhuǎn)賬1000元,這個(gè)轉(zhuǎn)賬會(huì)涉及到兩個(gè)關(guān)鍵操作就是:將小明的余額減少1000元,將小紅的余額增加1000元。萬(wàn)一在這兩個(gè)操作之間突然出現(xiàn)錯(cuò)誤比如銀行系統(tǒng)崩潰,導(dǎo)致小明余額減少而小紅的余額沒(méi)有增加,這樣就不對(duì)了。事務(wù)就是保證這兩個(gè)關(guān)鍵操作要么都成功,要么都要失敗。
四大特性:
原子性(Atomicity):事務(wù)是最小的執(zhí)行單位,不允許分割。事務(wù)的原子性確保動(dòng)作要么全部完成,要么完全不起作用;
一致性(Consistency):?執(zhí)行事務(wù)前后,數(shù)據(jù)保持一致,多個(gè)事務(wù)對(duì)同一個(gè)數(shù)據(jù)讀取的結(jié)果是相同的;
隔離性(Isolation):并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),一個(gè)用戶(hù)的事務(wù)不被其他事務(wù)所干擾,各并發(fā)事務(wù)之間數(shù)據(jù)庫(kù)是獨(dú)立的;
持久性(Durability):?一個(gè)事務(wù)被提交之后。它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變是持久的,即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響。
4 并發(fā)事務(wù)的問(wèn)題:
在典型的應(yīng)用程序中,多個(gè)事務(wù)并發(fā)運(yùn)行,經(jīng)常會(huì)操作相同的數(shù)據(jù)來(lái)完成各自的任務(wù)(多個(gè)用戶(hù)對(duì)同一數(shù)據(jù)進(jìn)行操作)。并發(fā)雖然是必須的,但可能會(huì)導(dǎo)致以下的問(wèn)題。
臟讀(Dirty read):當(dāng)一個(gè)事務(wù)正在訪問(wèn)數(shù)據(jù)并且對(duì)數(shù)據(jù)進(jìn)行了修改,而這種修改還沒(méi)有提交到數(shù)據(jù)庫(kù)中,這時(shí)另外一個(gè)事務(wù)也訪問(wèn)了這個(gè)數(shù)據(jù),然后使用了這個(gè)數(shù)據(jù)。因?yàn)檫@個(gè)數(shù)據(jù)是還沒(méi)有提交的數(shù)據(jù),那么另外一個(gè)事務(wù)讀到的這個(gè)數(shù)據(jù)是“臟數(shù)據(jù)”,依據(jù)“臟數(shù)據(jù)”所做的操作可能是不正確的。
丟失修改(Lost to modify):指在一個(gè)事務(wù)讀取一個(gè)數(shù)據(jù)時(shí),另外一個(gè)事務(wù)也訪問(wèn)了該數(shù)據(jù),那么在第一個(gè)事務(wù)中修改了這個(gè)數(shù)據(jù)后,第二個(gè)事務(wù)也修改了這個(gè)數(shù)據(jù)。這樣第一個(gè)事務(wù)內(nèi)的修改結(jié)果就被丟失,因此稱(chēng)為丟失修改。 例如:事務(wù)1讀取某表中的數(shù)據(jù)A=20,事務(wù)2也讀取A=20,事務(wù)1修改A=A-1,事務(wù)2也修改A=A-1,最終結(jié)果A=19,事務(wù)1的修改被丟失。
不可重復(fù)讀(Unrepeatableread):指在一個(gè)事務(wù)內(nèi)多次讀同一數(shù)據(jù)。在這個(gè)事務(wù)還沒(méi)有結(jié)束時(shí),另一個(gè)事務(wù)也訪問(wèn)該數(shù)據(jù)。那么,在第一個(gè)事務(wù)中的兩次讀數(shù)據(jù)之間,由于第二個(gè)事務(wù)的修改導(dǎo)致第一個(gè)事務(wù)兩次讀取的數(shù)據(jù)可能不太一樣。這就發(fā)生了在一個(gè)事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是不一樣的情況,因此稱(chēng)為不可重復(fù)讀。
幻讀(Phantom read):幻讀與不可重復(fù)讀類(lèi)似。它發(fā)生在一個(gè)事務(wù)(T1)讀取了幾行數(shù)據(jù),接著另一個(gè)并發(fā)事務(wù)(T2)插入了一些數(shù)據(jù)時(shí)。在隨后的查詢(xún)中,第一個(gè)事務(wù)(T1)就會(huì)發(fā)現(xiàn)多了一些原本不存在的記錄,就好像發(fā)生了幻覺(jué)一樣,所以稱(chēng)為幻讀。
不可重復(fù)讀和幻讀區(qū)別:
不可重復(fù)讀的重點(diǎn)是修改比如多次讀取一條記錄發(fā)現(xiàn)其中某些列的值被修改,幻讀的重點(diǎn)在于新增或者刪除比如多次讀取一條記錄發(fā)現(xiàn)記錄增多或減少了。
5 事務(wù)隔離級(jí)別
READ-UNCOMMITTED(讀取未提交):最低的隔離級(jí)別,允許讀取尚未提交的數(shù)據(jù)變更,可能會(huì)導(dǎo)致臟讀、幻讀或不可重復(fù)讀。
READ-COMMITTED(讀取已提交):?允許讀取并發(fā)事務(wù)已經(jīng)提交的數(shù)據(jù),可以阻止臟讀,但是幻讀或不可重復(fù)讀仍有可能發(fā)生。
REPEATABLE-READ(可重復(fù)讀):?對(duì)同一字段的多次讀取結(jié)果都是一致的,除非數(shù)據(jù)是被本身事務(wù)自己所修改,可以阻止臟讀和不可重復(fù)讀,但幻讀仍有可能發(fā)生。
SERIALIZABLE(可串行化):?最高的隔離級(jí)別,完全服從ACID的隔離級(jí)別。所有的事務(wù)依次逐個(gè)執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾,也就是說(shuō),該級(jí)別可以防止臟讀、不可重復(fù)讀以及幻讀。
默認(rèn)隔離級(jí)別:
MySQL InnoDB 存儲(chǔ)引擎的默認(rèn)支持的隔離級(jí)別是REPEATABLE-READ(可重讀)。使用的是Next-Key Lock 鎖算法,因此可以避免幻讀的產(chǎn)生。
InnoDB 存儲(chǔ)引擎在?分布式事務(wù)的情況下一般會(huì)用到?SERIALIZABLE(可串行化)?隔離級(jí)別。
6 鎖機(jī)制與InnoDB鎖算法
MyISAM和InnoDB存儲(chǔ)引擎使用的鎖:
MyISAM采用表級(jí)鎖(table-level locking)。
InnoDB支持行級(jí)鎖(row-level locking)和表級(jí)鎖,默認(rèn)為行級(jí)鎖
表級(jí)鎖和行級(jí)鎖對(duì)比:
表級(jí)鎖:?MySQL中鎖定?粒度最大?的一種鎖,對(duì)當(dāng)前操作的整張表加鎖,實(shí)現(xiàn)簡(jiǎn)單,資源消耗也比較少,加鎖快,不會(huì)出現(xiàn)死鎖。其鎖定粒度最大,觸發(fā)鎖沖突的概率最高,并發(fā)度最低,MyISAM和 InnoDB引擎都支持表級(jí)鎖。
行級(jí)鎖:?MySQL中鎖定?粒度最小?的一種鎖,只針對(duì)當(dāng)前操作的行進(jìn)行加鎖。 行級(jí)鎖能大大減少數(shù)據(jù)庫(kù)操作的沖突。其加鎖粒度最小,并發(fā)度高,但加鎖的開(kāi)銷(xiāo)也最大,加鎖慢,會(huì)出現(xiàn)死鎖。
InnoDB存儲(chǔ)引擎的鎖的算法有三種:
Record lock:單個(gè)行記錄上的鎖
Gap lock:間隙鎖,鎖定一個(gè)范圍,不包括記錄本身。目的是為了阻止多個(gè)事務(wù)將記錄插入到同一范圍內(nèi),而這會(huì)導(dǎo)致幻讀問(wèn)題的產(chǎn)生。有兩種方式顯式關(guān)閉gap鎖:(除了外鍵約束和唯一性檢查外,其余情況僅使用record lock) A. 將事務(wù)隔離級(jí)別設(shè)置為RC B. 將參數(shù)innodb_locks_unsafe_for_binlog設(shè)置為1
Next-key lock:record+gap 鎖定一個(gè)范圍,包含記錄本身。為了解決Phantom Problem幻讀問(wèn)題。Innodb對(duì)于行的查詢(xún)使用next-key lock。當(dāng)查詢(xún)的索引含有唯一屬性時(shí),將next-key lock降級(jí)為record key。
7 表優(yōu)化
當(dāng)MySQL單表記錄數(shù)過(guò)大時(shí),數(shù)據(jù)庫(kù)的CRUD性能會(huì)明顯下降,一些常見(jiàn)的優(yōu)化措施如下:
a 限定數(shù)據(jù)的范圍
務(wù)必禁止不帶任何限制數(shù)據(jù)范圍條件的查詢(xún)語(yǔ)句。比如:我們當(dāng)用戶(hù)在查詢(xún)訂單歷史的時(shí)候,我們可以控制在一個(gè)月的范圍內(nèi);
b 讀寫(xiě)分離
經(jīng)典的數(shù)據(jù)庫(kù)拆分方案,主庫(kù)負(fù)責(zé)寫(xiě),從庫(kù)負(fù)責(zé)讀;
c 垂直分區(qū)
根據(jù)數(shù)據(jù)庫(kù)里面數(shù)據(jù)表的相關(guān)性進(jìn)行拆分。?例如,用戶(hù)表中既有用戶(hù)的登錄信息又有用戶(hù)的基本信息,可以將用戶(hù)表拆分成兩個(gè)單獨(dú)的表,甚至放到單獨(dú)的庫(kù)做分庫(kù)。
簡(jiǎn)單來(lái)說(shuō)垂直拆分是指數(shù)據(jù)表列的拆分,把一張列比較多的表拆分為多張表。
優(yōu)點(diǎn):?可以使得列數(shù)據(jù)變小,在查詢(xún)時(shí)減少讀取的Block數(shù),減少I(mǎi)/O次數(shù)。此外,垂直分區(qū)可以簡(jiǎn)化表的結(jié)構(gòu),易于維護(hù)。
缺點(diǎn):?主鍵會(huì)出現(xiàn)冗余,需要管理冗余列,并會(huì)引起Join操作,可以通過(guò)在應(yīng)用層進(jìn)行Join來(lái)解決。此外,垂直分區(qū)會(huì)讓事務(wù)變得更加復(fù)雜;
d 水平分區(qū)
保持?jǐn)?shù)據(jù)表結(jié)構(gòu)不變,通過(guò)某種策略存儲(chǔ)數(shù)據(jù)分片。這樣每一片數(shù)據(jù)分散到不同的表或者庫(kù)中,達(dá)到了分布式的目的。 水平拆分可以支撐非常大的數(shù)據(jù)量。
水平拆分是指數(shù)據(jù)表行的拆分,表的行數(shù)超過(guò)200萬(wàn)行時(shí),就會(huì)變慢,這時(shí)可以把一張的表的數(shù)據(jù)拆成多張表來(lái)存放。舉個(gè)例子:我們可以將用戶(hù)信息表拆分成多個(gè)用戶(hù)信息表,這樣就可以避免單一表數(shù)據(jù)量過(guò)大對(duì)性能造成影響。
水平拆分可以支持非常大的數(shù)據(jù)量。需要注意的一點(diǎn)是:分表僅僅是解決了單一表數(shù)據(jù)過(guò)大的問(wèn)題,但由于表的數(shù)據(jù)還是在同一臺(tái)機(jī)器上,其實(shí)對(duì)于提升MySQL并發(fā)能力沒(méi)有什么意義,所以水平拆分最好分庫(kù)?。
水平拆分能夠?支持非常大的數(shù)據(jù)量存儲(chǔ),應(yīng)用端改造也少,但?分片事務(wù)難以解決?,跨節(jié)點(diǎn)Join性能較差,邏輯復(fù)雜。一般的數(shù)據(jù)表在優(yōu)化得當(dāng)?shù)那闆r下支撐千萬(wàn)以下的數(shù)據(jù)量是沒(méi)有太大問(wèn)題的。如果實(shí)在要分片,盡量選擇客戶(hù)端分片架構(gòu),這樣可以減少一次和中間件的網(wǎng)絡(luò)I/O。
下面補(bǔ)充一下數(shù)據(jù)庫(kù)分片的兩種常見(jiàn)方案:
客戶(hù)端代理:?分片邏輯在應(yīng)用端,封裝在jar包中,通過(guò)修改或者封裝JDBC層來(lái)實(shí)現(xiàn)。?當(dāng)當(dāng)網(wǎng)的?Sharding-JDBC?、阿里的TDDL是兩種比較常用的實(shí)現(xiàn)。
中間件代理:?在應(yīng)用和數(shù)據(jù)中間加了一個(gè)代理層。分片邏輯統(tǒng)一維護(hù)在中間件服務(wù)中。?我們現(xiàn)在談的?Mycat?、360的Atlas、網(wǎng)易的DDB等等都是這種架構(gòu)的實(shí)現(xiàn)。
8 池化思想
池化設(shè)計(jì)應(yīng)該不是一個(gè)新名詞。我們常見(jiàn)的如java線程池、jdbc連接池、redis連接池等就是這類(lèi)設(shè)計(jì)的代表實(shí)現(xiàn)。這種設(shè)計(jì)會(huì)初始預(yù)設(shè)資源,解決的問(wèn)題就是抵消每次獲取資源的消耗,如創(chuàng)建線程的開(kāi)銷(xiāo),獲取遠(yuǎn)程連接的開(kāi)銷(xiāo)等。就好比你去食堂打飯,打飯的大媽會(huì)先把飯盛好幾份放那里,你來(lái)了就直接拿著飯盒加菜即可,不用再臨時(shí)又盛飯又打菜,效率就高了。除了初始化資源,池化設(shè)計(jì)還包括如下這些特征:池子的初始值、池子的活躍值、池子的最大值等,這些特征可以直接映射到j(luò)ava線程池和數(shù)據(jù)庫(kù)連接池的成員屬性中。
在連接池中,創(chuàng)建連接后,將其放置在池中,并再次使用它,因此不必建立新的連接。如果使用了所有連接,則會(huì)建立一個(gè)新連接并將其添加到池中。連接池還減少了用戶(hù)必須等待建立與數(shù)據(jù)庫(kù)的連接的時(shí)間。
數(shù)據(jù)庫(kù)連接本質(zhì)就是一個(gè) socket 的連接。數(shù)據(jù)庫(kù)服務(wù)端還要維護(hù)一些緩存和用戶(hù)權(quán)限信息之類(lèi)的 所以占用了一些內(nèi)存。我們可以把數(shù)據(jù)庫(kù)連接池是看做是維護(hù)的數(shù)據(jù)庫(kù)連接的緩存,以便將來(lái)需要對(duì)數(shù)據(jù)庫(kù)的請(qǐng)求時(shí)可以重用這些連接。為每個(gè)用戶(hù)打開(kāi)和維護(hù)數(shù)據(jù)庫(kù)連接,尤其是對(duì)動(dòng)態(tài)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的網(wǎng)站應(yīng)用程序的請(qǐng)求,既昂貴又浪費(fèi)資源。
9 如何做持久化
undo日志:
記錄的是修改前的值,在操作任何數(shù)據(jù)之前,首先將數(shù)據(jù)備份到一個(gè)地方(這個(gè)存儲(chǔ)數(shù)據(jù)備份的地方稱(chēng)為Undo Log)。然后進(jìn)行數(shù)據(jù)的修改。如果出現(xiàn)了錯(cuò)誤或者用戶(hù)執(zhí)行了ROLLBACK語(yǔ)句,系統(tǒng)可以利用Undo Log中的備份將數(shù)據(jù)恢復(fù)到事務(wù)開(kāi)始之前的狀態(tài)。
舉例:
事務(wù)A要將字段age的值由原來(lái)的1修改為2,要將name的值由原來(lái)的Alice修改為Bob,
假設(shè)現(xiàn)在數(shù)據(jù)庫(kù)出現(xiàn)了宕機(jī)的問(wèn)題,分為兩種情況:
如果在上表第三步之前數(shù)據(jù)庫(kù)掛了,則最終數(shù)據(jù)和日志均為原數(shù)據(jù);
如果第三步及以后出現(xiàn)異常,則undo已經(jīng)記錄了原來(lái)的值,則可以利用undo日志將數(shù)據(jù)恢復(fù)為原數(shù)據(jù)。
原理
當(dāng)事務(wù)提交之后,undo不會(huì)被馬上刪除,而是放入待刪除隊(duì)列,由purge線程來(lái)判斷是否刪除和處理。在mysql5.6之前,undo只存在于共享表空間中,之后的版本中,則可以配置為獨(dú)立的文件。
undo內(nèi)部默認(rèn)128個(gè)回滾段槽(rseg slot),每個(gè)rseg slot內(nèi)部有1024個(gè)回滾段(rollback segment)。其中:
slot0——共1個(gè),預(yù)留給系統(tǒng)表空間
slot1~slot31——共31個(gè),預(yù)留給臨時(shí)表空間
slot32~slot127——共96個(gè),預(yù)留給undo獨(dú)立表空間
缺點(diǎn):
由于undo日志會(huì)被清理掉,不能保證事務(wù)的持久性,因此才需要引入redo日志來(lái)保證事務(wù)的持久性。
redo日志:
記錄的是修改后最新的數(shù)據(jù)和冗余的undo日志,和Undo Log相反,Redo Log記錄的是新數(shù)據(jù)的備份。在事務(wù)提交前,只要將Redo Log持久化即可,不需要將數(shù)據(jù)持久化。當(dāng)系統(tǒng)崩潰時(shí),雖然數(shù)據(jù)沒(méi)有持久化,但是Redo Log已經(jīng)持久化。系統(tǒng)可以根據(jù)Redo Log的內(nèi)容,將所有數(shù)據(jù)恢復(fù)到最新的狀態(tài)。
舉例:
事務(wù)B要將字段age的值由原來(lái)的1修改為2,要將name的值由原來(lái)的Alice修改為Bob,redo日志記錄的過(guò)程表如下:
其中,redo日志必須先于數(shù)據(jù)寫(xiě)入磁盤(pán)(即步驟8和步驟9的順序不能改變)。因?yàn)槿绻贿@樣,在數(shù)據(jù)提交之后再寫(xiě)redo日志,一旦redo日志的寫(xiě)入過(guò)程出現(xiàn)異常,將無(wú)法保證持久性。
記錄redo日志時(shí),先記入redo log buffer,最后再一起寫(xiě)入磁盤(pán),這樣可以減少I(mǎi)O,提升性能。
另外,未提交的事務(wù)和回滾了的事務(wù)也會(huì)計(jì)入redo日志。
mysql恢復(fù)的策略:
恢復(fù)時(shí),先根據(jù)redo重做所有事務(wù)(包括未提交和回滾了的)。再根據(jù)undo回滾未提交的事務(wù)。
如上,如果事務(wù)B異常未提交事務(wù)就宕機(jī),恢復(fù)時(shí),先根據(jù)redo日志將數(shù)據(jù)恢復(fù)為age=2&name=Bob,然后再根據(jù)undo記錄的age=1&name=Alice將數(shù)據(jù)恢復(fù)如初。
如果事務(wù)C異常未提交事務(wù)就宕機(jī),恢復(fù)時(shí),根據(jù)redo日志,可以直接恢復(fù)至age=1&name=Alice的初始狀態(tài)。
redo日志會(huì)隨著時(shí)間推移而越來(lái)越大,為了提升redo的恢復(fù)性能,引入了checkpoint機(jī)制,在恢復(fù)的時(shí)候,只需要從checkpoint的位置往后恢復(fù)即可。
總結(jié)
以上是生活随笔為你收集整理的mysql面试考点_mysql面试知识点的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 与时间相关的java源码_Java 调整
- 下一篇: s3c6410 jpeg编码 linux