尚硅谷MySQL數(shù)據(jù)庫面試題寶典,mysql面試必考!mysql工作必用!






1,主鍵(唯一索引)匹配
2.全值匹配(單值匹配)
3.最左前綴匹配
4.范圍匹配
5.索掃描
6.全表掃描

oderby 需要條件才排序



MySQL 內(nèi)部有多個核心模塊組成,包括:
- 連接器(Connection Manager):負(fù)責(zé)處理客戶端連接和身份驗證等操作。
- 查詢處理器(Query Processor):負(fù)責(zé)解析 SQL 語句、生成執(zhí)行計劃和執(zhí)行查詢,是 MySQL 的核心組件。
- 存儲引擎(Storage Engine):負(fù)責(zé)管理表的數(shù)據(jù)存儲和檢索,主要包括 MyISAM、InnoDB、Memory、Archive 等多個不同的存儲引擎。
- 事務(wù)處理器(Transaction Manager):負(fù)責(zé)管理事務(wù)的提交、回滾和鎖定等操作。
- 備份恢復(fù)(Backup and Recovery):負(fù)責(zé)管理 MySQL 數(shù)據(jù)庫的備份和恢復(fù)。


.ibd 文件是 InnoDB 存儲引擎使用的表空間文件,存儲了該表的數(shù)據(jù)和索引。
與之相對應(yīng)的是 .frm 文件,該文件存儲了該表的元數(shù)據(jù)信息,包括表結(jié)構(gòu)、列名、列數(shù)據(jù)類型等信息。
最初的 InnoDB 版本中,.frm 和 .ibd 文件是分離的,這意味著如果用戶需要重建表,需要處理兩個文件。后來的 InnoDB 版本將 .frm 文件整合到了 .ibd 文件中,使得在重建表時變得更加容易。



假設(shè)一個銀行系統(tǒng)需要對客戶進(jìn)行轉(zhuǎn)賬操作,涉及到兩個賬戶的扣款和存款操作,這時可以采用ACID的特性來保證事務(wù)處理的正確性。
在這個過程中,需要滿足以下條件:
- 原子性(Atomicity):要么兩個賬戶的扣款和存款都成功,要么全部失敗回滾,確保數(shù)據(jù)的完整性和一致性。
- 一致性(Consistency):在轉(zhuǎn)賬的過程中,必須保證兩個賬戶的余額總和不變,即一個賬戶的扣款金額必須等于另一個賬戶的存款金額。undolog
- 隔離性(Isolation):多個用戶同時進(jìn)行轉(zhuǎn)賬操作時,每個用戶的操作應(yīng)該相互隔離,避免因為并發(fā)操作而導(dǎo)致的不一致性問題。
- 持久性(Durability):一旦轉(zhuǎn)賬完成,其結(jié)果就應(yīng)該被永久保存在數(shù)據(jù)庫中,并對所有后續(xù)對數(shù)據(jù)的訪問和操作都可見。redolog
如果銀行系統(tǒng)不能滿足以上條件,在并發(fā)訪問的情況下,很可能會發(fā)生數(shù)據(jù)錯誤或者數(shù)據(jù)丟失等問題。因此,ACID特性是保證數(shù)據(jù)庫管理系統(tǒng)正確性的重要保障。
- 原子性:原子性是指一個事務(wù)中的所有操作要么全部成功,要么全部失敗回滾,從而保證操作的原子性。實現(xiàn)原子性需要使用事務(wù)日志機(jī)制,將所有事務(wù)操作寫入到日志中,只有在提交完成后才將變更操作應(yīng)用到數(shù)據(jù)庫。如果事務(wù)執(zhí)行失敗,數(shù)據(jù)庫會利用回滾操作將之前的操作全部撤銷。undolog
- 一致性:一致性是指保證數(shù)據(jù)在事務(wù)執(zhí)行前后都滿足完整性約束條件,保證數(shù)據(jù)的正確性。實現(xiàn)一致性可以通過應(yīng)用程序和數(shù)據(jù)庫系統(tǒng)約束條件來進(jìn)行校驗和處理。此外,還可以使用觸發(fā)器和存儲過程等手段來實現(xiàn)一致性。
- 隔離性:隔離性是指多個并發(fā)事務(wù)之間互不干擾,所見即所得,防止出現(xiàn)臟讀、不可重復(fù)讀、幻讀等問題。隔離級別決定了事務(wù)的隔離程度,分為讀未提交、讀已提交、可重復(fù)讀和串行化四種級別。隔離性的實現(xiàn)可以通過鎖機(jī)制、**多版本并發(fā)控制(MVCC)**等方式來實現(xiàn)。修改丟失
- 持久性:持久性是指一旦事務(wù)提交,其所做的修改將永久保存在數(shù)據(jù)庫中,即使數(shù)據(jù)庫系統(tǒng)發(fā)生故障也能夠恢復(fù)。實現(xiàn)持久性需要使用日志機(jī)制,將所有變更操作寫入到磁盤等非易失性存儲器中,保證在數(shù)據(jù)庫系統(tǒng)崩潰后數(shù)據(jù)能夠得到恢復(fù)。

(1)臟讀(Dirty read): 當(dāng)一個事務(wù)正在訪問數(shù)據(jù)并且對數(shù)據(jù)進(jìn)行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時另外一個事務(wù)也訪問了這個數(shù)據(jù),然后使用了這個數(shù)據(jù)。因為這個數(shù)據(jù)是還沒有提交的數(shù)據(jù),那么另外一個事務(wù)讀到的這個數(shù)據(jù)是“臟數(shù)據(jù)”,依據(jù)“臟數(shù)據(jù)”所做的操作可能是不正確的。
(2)丟失修改(Lost to modify): 指在一個事務(wù)讀取一個數(shù)據(jù)時,另外一個事務(wù)也訪問了該數(shù)據(jù),那么在第一個事務(wù)中修改了這個數(shù)據(jù)后,第二個事務(wù)也修改了這個數(shù)據(jù)。這樣第一個事務(wù)內(nèi)的修改結(jié)果就被丟失,因此稱為丟失修改。 例如:事務(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的修改被丟失。
(3)不可重復(fù)讀(Unrepeatableread): 指在一個事務(wù)內(nèi)多次讀同一數(shù)據(jù)。在這個事務(wù)還沒有結(jié)束時,另一個事務(wù)也訪問該數(shù)據(jù)。那么,在第一個事務(wù)中的兩次讀數(shù)據(jù)之間,由于第二個事務(wù)的修改導(dǎo)致第一個事務(wù)兩次讀取的數(shù)據(jù)可能不太一樣。這就發(fā)生了在一個事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是不一樣的情況,因此稱為不可重復(fù)讀。
(4)幻讀(Phantom read): 幻讀與不可重復(fù)讀類似。它發(fā)生在一個事務(wù)(T1)讀取了幾行數(shù)據(jù),接著另一個并發(fā)事務(wù)(T2)插入了一些數(shù)據(jù)時。在隨后的查詢中,第一個事務(wù)(T1)就會發(fā)現(xiàn)多了一些原本不存在的記錄,就好像發(fā)生了幻覺一樣,所以稱為幻讀。
不可重復(fù)度和幻讀區(qū)別:
不可重復(fù)讀針對的是一份數(shù)據(jù)的修改
幻讀針對的是行數(shù)修改
不可重復(fù)讀的重點是修改,幻讀的重點在于新增或者刪除。
(同樣的條件, 你讀取過的數(shù)據(jù), 再次讀取出來發(fā)現(xiàn)值不一樣了 ):事務(wù)1中的A先生讀取自己的工資為 1000的操作還沒完成,事務(wù)2中的B先生就修改了A的工資為2000,導(dǎo) 致A再讀自己的工資時工資變?yōu)?2000;這就是不可重復(fù)讀。
同樣的條件, 第1次和第2次讀出來的記錄數(shù)不一樣 ):假某工資單表中工資大于3000的有4人,事務(wù)1讀取了所有工資大于3000的人,共查到4條記錄,這時事務(wù)2 又插入了一條工資大于3000的記錄,事務(wù)1再次讀取時查到的記錄就變?yōu)榱?條,這樣就導(dǎo)致了幻讀。

非鎖定讀 mvcc
可以這樣認(rèn)為,當(dāng)delete一條記錄時,undo log 中會記錄一條對應(yīng)的insert記錄,當(dāng)update一條記錄時,它記錄一條對應(yīng)相反的update記錄。
過版本鏈,我們就可以看出事務(wù)版本號、表格隱藏的列和undo log它們之間的關(guān)系

undo log有什么用途呢?
- 事務(wù)回滾時,保證原子性和一致性。
- 用于MVCC快照讀。
快照讀和當(dāng)前讀

當(dāng)前讀(update、insert、delete 當(dāng)前讀)
Read view 匹配條件規(guī)則如下:
- 如果數(shù)據(jù)事務(wù)ID
trx_id < min_limit_id
,表明生成該版本的事務(wù)在生成Read View前,已經(jīng)提交(因為事務(wù)ID是遞增的),所以該版本可以被當(dāng)前事務(wù)訪問。 - 如果
trx_id>= max_limit_id
,表明生成該版本的事務(wù)在生成ReadView后才生成,所以該版本不可以被當(dāng)前事務(wù)訪問。 - 如果
min_limit_id =<trx_id< max_limit_id
,需腰分3種情況討論
RR隔離級別,當(dāng)連續(xù)兩個快照讀中出現(xiàn)當(dāng)前讀,并且當(dāng)前讀有其他事務(wù)新增的數(shù)據(jù),就會出現(xiàn)幻讀 因為快照讀,所以沒加鎖,B不會被阻塞
在 REPEATABLE READ 隔離級別下,事務(wù) A 第一次執(zhí)行普通的 SELECT 語句時生成了一個 ReadView(且在 RR 下只會生成一個 RV),之后事務(wù) B 向 user 表中新插入一條記錄并提交。
ReadView 并不能阻止事務(wù) A 執(zhí)行 UPDATE 或者 DELETE 語句來改動這個新插入的記錄(由于事務(wù) B 已經(jīng)提交,因此改動該記錄并不會造成阻塞),但是這樣一來,這條新記錄的 trx_id
隱藏列的值就變成了事務(wù) A 的事務(wù) id。之后 A 再使用普通的 SELECT 語句去查詢這條記錄時就可以看到這條記錄了,也就可以把這條記錄返回給客戶端。
因為這個特殊現(xiàn)象的存在,我們也可以認(rèn)為 MVCC 并不能完全禁止幻讀。




RR隔離級別下,加鎖的select, update, delete等語句,會使用間隙鎖+ 臨鍵鎖,鎖住索引記錄之間的范圍,避免范圍間插入記錄,以避免產(chǎn)生幻影行記錄,那就是說RR隔離級別解決了幻讀問題???

slow query log
show variables like 'slow_query_log%'





兩階段提交




使用字符串存儲日期雖然容易上手,但是存在以下兩個問題:
- 字符串占用的空間更大;
- 字符串存儲的日期比較效率比較低(逐個字符進(jìn)行比對),無法用日期相關(guān)的API。


高價值



- JOIN的效率高于子查詢的情況:
- 當(dāng)需要檢索多個表之間據(jù)時,使用JOIN可以更理解查詢語句。
- 當(dāng)需要進(jìn)行大量的數(shù)據(jù)過濾、分組和排序時,JOIN通常比子查詢更高效,因為它可以利用索引對數(shù)據(jù)進(jìn)行更快速的訪問和處理。
- 子查詢的效率高于JOIN的情況:
- 當(dāng)需要在多個表中進(jìn)行復(fù)雜的關(guān)聯(lián)和過濾時,使用子查詢可能會更加直觀和方便。此時,JOIN需要更復(fù)雜的查詢語句才能實現(xiàn)相同的功能。
- 當(dāng)要從一個大表中獲取少量數(shù)據(jù)時,使用子查詢可能比JOIN更高效。因為JOIN可能會產(chǎn)生更大的中間結(jié)果集,而子查詢只需要返回所需的行。

COUNT(*)
比COUNT(列名)
更高效。這是因為COUNT(*)
不需要檢查具體的列的值,只需要讀取表中的行數(shù)即可得出結(jié)果,而COUNT(列名)
需要先對指定的列進(jìn)行非NULL值的檢查,然后才能計數(shù)。
