pos機專業(yè)面試

 新聞資訊3  |   2023-08-20 14:29  |  投稿人:pos機之家

網(wǎng)上有很多關(guān)于pos機專業(yè)面試,數(shù)據(jù)庫精選 60 道面試題的知識,也有很多人為大家解答關(guān)于pos機專業(yè)面試的問題,今天pos機之家(m.nxzs9ef.cn)為大家整理了關(guān)于這方面的知識,讓我們一起來看下吧!

本文目錄一覽:

1、pos機專業(yè)面試

pos機專業(yè)面試

大家好,我是賀同學(xué)。

金三銀四到了,給大家整理一些數(shù)據(jù)庫必知必會的面試題。

基礎(chǔ)相關(guān)

1、關(guān)系型和非關(guān)系型數(shù)據(jù)庫的區(qū)別?

關(guān)系型數(shù)據(jù)庫的優(yōu)點

容易理解,因為它采用了關(guān)系模型來組織數(shù)據(jù)。可以保持數(shù)據(jù)的一致性。數(shù)據(jù)更新的開銷比較小。支持復(fù)雜查詢(帶 where 子句的查詢)

非關(guān)系型數(shù)據(jù)庫(NOSQL)的優(yōu)點

無需經(jīng)過 SQL 層的解析,讀寫效率高?;阪I值對,讀寫性能很高,易于擴展可以支持多種類型數(shù)據(jù)的存儲,如圖片,文檔等等。擴展(可分為內(nèi)存性數(shù)據(jù)庫以及文檔型數(shù)據(jù)庫,比如 Redis,MongoDB,HBase 等,適合場景:數(shù)據(jù)量大高可用的日志系統(tǒng)/地理位置存儲系統(tǒng))。2、詳細說一下一條 MySQL 語句執(zhí)行的步驟

Server 層按順序執(zhí)行 SQL 的步驟為:

客戶端請求 -> 連接器(驗證用戶身份,給予權(quán)限)查詢緩存(存在緩存則直接返回,不存在則執(zhí)行后續(xù)操作)分析器(對 SQL 進行詞法分析和語法分析操作)優(yōu)化器(主要對執(zhí)行的 SQL 優(yōu)化選擇最優(yōu)的執(zhí)行方案方法)執(zhí)行器(執(zhí)行時會先看用戶是否有執(zhí)行權(quán)限,有才去使用這個引擎提供的接口)-> 去引擎層獲取數(shù)據(jù)返回(如果開啟查詢緩存則會緩存查詢結(jié)果)索引相關(guān)3、MySQL 使用索引的原因?

根本原因

索引的出現(xiàn),就是為了提高數(shù)據(jù)查詢的效率,就像書的目錄一樣。對于數(shù)據(jù)庫的表而言,索引其實就是它的“目錄”。

擴展

創(chuàng)建唯一性索引,可以保證數(shù)據(jù)庫表中每一行數(shù)據(jù)的唯一性。幫助引擎層避免排序和臨時表將隨機 IO 變?yōu)轫樞?IO,加速表和表之間的連接。4、索引的三種常見底層數(shù)據(jù)結(jié)構(gòu)以及優(yōu)缺點

三種常見的索引底層數(shù)據(jù)結(jié)構(gòu):分別是哈希表、有序數(shù)組和搜索樹。

哈希表這種適用于等值查詢的場景,比如 memcached 以及其它一些 NoSQL 引擎,不適合范圍查詢。有序數(shù)組索引只適用于靜態(tài)存儲引擎,等值和范圍查詢性能好,但更新數(shù)據(jù)成本高。N 叉樹由于讀寫上的性能優(yōu)點以及適配磁盤訪問模式以及廣泛應(yīng)用在數(shù)據(jù)庫引擎中。擴展(以 InnoDB 的一個整數(shù)字段索引為例,這個 N 差不多是 1200??脴涓呤?4 的時候,就可以存 1200 的 3 次方個值,這已經(jīng) 17 億了??紤]到樹根的數(shù)據(jù)塊總是在內(nèi)存中的,一個 10 億行的表上一個整數(shù)字段的索引,查找一個值最多只需要訪問 3 次磁盤。其實,樹的第二層也有很大概率在內(nèi)存中,那么訪問磁盤的平均次數(shù)就更少了。)5、索引的常見類型以及它是如何發(fā)揮作用的?

根據(jù)葉子節(jié)點的內(nèi)容,索引類型分為主鍵索引和非主鍵索引。

主鍵索引的葉子節(jié)點存的整行數(shù)據(jù),在InnoDB里也被稱為聚簇索引。非主鍵索引葉子節(jié)點存的主鍵的值,在InnoDB里也被稱為二級索引。6、MyISAM 和 InnoDB 實現(xiàn) B 樹索引方式的區(qū)別是什么?InnoDB 存儲引擎:B+ 樹索引的葉子節(jié)點保存數(shù)據(jù)本身,其數(shù)據(jù)文件本身就是索引文件。MyISAM 存儲引擎:B+ 樹索引的葉子節(jié)點保存數(shù)據(jù)的物理地址,葉節(jié)點的 data 域存放的是數(shù)據(jù)記錄的地址,索引文件和數(shù)據(jù)文件是分離的。7、InnoDB 為什么設(shè)計 B+ 樹索引?

兩個考慮因素:

InnoDB 需要執(zhí)行的場景和功能需要在特定查詢上擁有較強的性能。CPU 將磁盤上的數(shù)據(jù)加載到內(nèi)存中需要花費大量時間。

為什么選擇 B+ 樹:

哈希索引雖然能提供O(1)復(fù)雜度查詢,但對范圍查詢和排序卻無法很好的支持,最終會導(dǎo)致全表掃描。B 樹能夠在非葉子節(jié)點存儲數(shù)據(jù),但會導(dǎo)致在查詢連續(xù)數(shù)據(jù)可能帶來更多的隨機 IO。而 B+ 樹的所有葉節(jié)點可以通過指針來相互連接,減少順序遍歷帶來的隨機 IO。普通索引還是唯一索引?由于唯一索引用不上 change buffer 的優(yōu)化機制,因此如果業(yè)務(wù)可以接受,從性能角度出發(fā)建議你優(yōu)先考慮非唯一索引。8、什么是覆蓋索引和索引下推?

覆蓋索引:

在某個查詢里面,索引 k 已經(jīng)“覆蓋了”我們的查詢需求,稱為覆蓋索引。覆蓋索引可以減少樹的搜索次數(shù),顯著提升查詢性能,所以使用覆蓋索引是一個常用的性能優(yōu)化手段。

索引下推:

MySQL 5.6 引入的索引下推優(yōu)化(index conditIOn pushdown), 可以在索引遍歷過程中,對索引中包含的字段先做判斷,直接過濾掉不滿足條件的記錄,減少回表次數(shù)。9、哪些操作會導(dǎo)致索引失效?對索引使用左或者左右模糊匹配,也就是 like %xx 或者 like %xx% 這兩種方式都會造成索引失效。原因在于查詢的結(jié)果可能是多個,不知道從哪個索引值開始比較,于是就只能通過全表掃描的方式來查詢。對索引進行函數(shù)/對索引進行表達式計算,因為索引保持的是索引字段的原始值,而不是經(jīng)過函數(shù)計算的值,自然就沒辦法走索引。對索引進行隱式轉(zhuǎn)換相當(dāng)于使用了新函數(shù)。WHERE 子句中的 OR語句,只要有條件列不是索引列,就會進行全表掃描。10、字符串加索引直接創(chuàng)建完整索引,這樣可能會比較占用空間。創(chuàng)建前綴索引,節(jié)省空間,但會增加查詢掃描次數(shù),并且不能使用覆蓋索引。倒序存儲,再創(chuàng)建前綴索引,用于繞過字符串本身前綴的區(qū)分度不夠的問題。創(chuàng)建 hash 字段索引,查詢性能穩(wěn)定,有額外的存儲和計算消耗,跟第三種方式一樣,都不支持范圍掃描。日志相關(guān)11、MySQL 的 change buffer 是什么?當(dāng)需要更新一個數(shù)據(jù)頁時,如果數(shù)據(jù)頁在內(nèi)存中就直接更新;而如果這個數(shù)據(jù)頁還沒有在內(nèi)存中的話,在不影響數(shù)據(jù)一致性的前提下,InnoDB 會將這些更新操作緩存在 change buffer 中。這樣就不需要從磁盤中讀入這個數(shù)據(jù)頁了,在下次查詢需要訪問這個數(shù)據(jù)頁的時候,將數(shù)據(jù)頁讀入內(nèi)存,然后執(zhí)行 change buffer 中與這個頁有關(guān)的操作。通過這種方式就能保證這個數(shù)據(jù)邏輯的正確性。注意唯一索引的更新就不能使用 change buffer,實際上也只有普通索引可以使用。適用場景:- 對于寫多讀少的業(yè)務(wù)來說,頁面在寫完以后馬上被訪問到的概率比較小,此時 change buffer 的使用效果最好。這種業(yè)務(wù)模型常見的就是賬單類、日志類的系統(tǒng)。- 反過來,假設(shè)一個業(yè)務(wù)的更新模式是寫入之后馬上會做查詢,那么即使?jié)M足了條件,將更新先記錄在 change buffer,但之后由于馬上要訪問這個數(shù)據(jù)頁,會立即觸發(fā) merge 過程。這樣隨機訪問 IO 的次數(shù)不會減少,反而增加了 change buffer 的維護代價。12、MySQL 是如何判斷一行掃描數(shù)的?MySQL 在真正開始執(zhí)行語句之前,并不能精確地知道滿足這個條件的記錄有多少條。而只能根據(jù)統(tǒng)計信息來估算記錄數(shù)。這個統(tǒng)計信息就是索引的“區(qū)分度。13、MySQL 的 redo log 和 binlog 區(qū)別?14、為什么需要 redo log?redo log 主要用于 MySQL 異常重啟后的一種數(shù)據(jù)恢復(fù)手段,確保了數(shù)據(jù)的一致性。其實是為了配合 MySQL 的 WAL 機制。因為 MySQL 進行更新操作,為了能夠快速響應(yīng),所以采用了異步寫回磁盤的技術(shù),寫入內(nèi)存后就返回。但是這樣,會存在 crash后 內(nèi)存數(shù)據(jù)丟失的隱患,而 redo log 具備 crash safe 的能力。15、為什么 redo log 具有 crash-safe 的能力,是 binlog 無法替代的?

第一點:redo log 可確保 innoDB 判斷哪些數(shù)據(jù)已經(jīng)刷盤,哪些數(shù)據(jù)還沒有

redo log 和 binlog 有一個很大的區(qū)別就是,一個是循環(huán)寫,一個是追加寫。也就是說 redo log 只會記錄未刷盤的日志,已經(jīng)刷入磁盤的數(shù)據(jù)都會從 redo log 這個有限大小的日志文件里刪除。binlog 是追加日志,保存的是全量的日志。當(dāng)數(shù)據(jù)庫 crash 后,想要恢復(fù)未刷盤但已經(jīng)寫入 redo log 和 binlog 的數(shù)據(jù)到內(nèi)存時,binlog 是無法恢復(fù)的。雖然 binlog 擁有全量的日志,但沒有一個標(biāo)志讓 innoDB 判斷哪些數(shù)據(jù)已經(jīng)刷盤,哪些數(shù)據(jù)還沒有。但 redo log 不一樣,只要刷入磁盤的數(shù)據(jù),都會從 redo log 中抹掉,因為是循環(huán)寫!數(shù)據(jù)庫重啟后,直接把 redo log 中的數(shù)據(jù)都恢復(fù)至內(nèi)存就可以了。

第二點:如果 redo log 寫入失敗,說明此次操作失敗,事務(wù)也不可能提交

redo log 每次更新操作完成后,就一定會寫入日志,如果寫入失敗,說明此次操作失敗,事務(wù)也不可能提交。redo log 內(nèi)部結(jié)構(gòu)是基于頁的,記錄了這個頁的字段值變化,只要crash后讀取redo log進行重放,就可以恢復(fù)數(shù)據(jù)。這就是為什么 redo log 具有 crash-safe 的能力,而 binlog 不具備。16、當(dāng)數(shù)據(jù)庫 crash 后,如何恢復(fù)未刷盤的數(shù)據(jù)到內(nèi)存中?

根據(jù) redo log 和 binlog 的兩階段提交,未持久化的數(shù)據(jù)分為幾種情況:

change buffer 寫入,redo log 雖然做了 fsync 但未 commit,binlog 未 fsync 到磁盤,這部分數(shù)據(jù)丟失。change buffer 寫入,redo log fsync 未 commit,binlog 已經(jīng) fsync 到磁盤,先從 binlog 恢復(fù) redo log,再從 redo log 恢復(fù) change buffer。change buffer 寫入,redo log 和 binlog 都已經(jīng) fsync,直接從 redo log 里恢復(fù)。17、redo log 寫入方式?

redo log包括兩部分內(nèi)容,分別是內(nèi)存中的日志緩沖(redo log buffer)和磁盤上的日志文件(redo log file)。

MySQL 每執(zhí)行一條 DML 語句,會先把記錄寫入 redo log buffer(用戶空間) ,再保存到內(nèi)核空間的緩沖區(qū) OS-buffer 中,后續(xù)某個時間點再一次性將多個操作記錄寫到 redo log File(刷盤) 。這種先寫日志,再寫磁盤的技術(shù),就是WAL。

可以發(fā)現(xiàn),redo log buffer寫入到redo log file,是經(jīng)過OS buffer中轉(zhuǎn)的。其實可以通過參數(shù)innodb_flush_log_at_trx_commit進行配置,參數(shù)值含義如下:

0:稱為延遲寫,事務(wù)提交時不會將redo log buffer中日志寫入到OS buffer,而是每秒寫入OS buffer并調(diào)用寫入到redo log file中。1:稱為實時寫,實時刷”,事務(wù)每次提交都會將redo log buffer中的日志寫入OS buffer并保存到redo log file中。2:稱為實時寫,延遲刷。每次事務(wù)提交寫入到OS buffer,然后是每秒將日志寫入到redo log file。18、redo log 的執(zhí)行流程?

我們來看下Redo log的執(zhí)行流程,假設(shè)執(zhí)行的 SQL 如下:

update T set a =1 where id =666MySQL 客戶端將請求語句 update T set a =1 where id =666,發(fā)往 MySQL Server 層。MySQL Server 層接收到 SQL 請求后,對其進行分析、優(yōu)化、執(zhí)行等處理工作,將生成的 SQL 執(zhí)行計劃發(fā)到 InnoDB 存儲引擎層執(zhí)行。InnoDB 存儲引擎層將a修改為1的這個操作記錄到內(nèi)存中。記錄到內(nèi)存以后會修改 redo log 的記錄,會在添加一行記錄,其內(nèi)容是需要在哪個數(shù)據(jù)頁上做什么修改。此后,將事務(wù)的狀態(tài)設(shè)置為 prepare ,說明已經(jīng)準(zhǔn)備好提交事務(wù)了。等到 MySQL Server 層處理完事務(wù)以后,會將事務(wù)的狀態(tài)設(shè)置為 commit,也就是提交該事務(wù)。在收到事務(wù)提交的請求以后,redo log 會把剛才寫入內(nèi)存中的操作記錄寫入到磁盤中,從而完成整個日志的記錄過程。19、binlog 的概念是什么,起到什么作用, 可以保證 crash-safe 嗎?binlog 是歸檔日志,屬于 MySQL Server 層的日志??梢詫崿F(xiàn)主從復(fù)制數(shù)據(jù)恢復(fù)兩個作用。當(dāng)需要恢復(fù)數(shù)據(jù)時,可以取出某個時間范圍內(nèi)的 binlog 進行重放恢復(fù)。但是 binlog 不可以做 crash safe,因為 crash 之前,binlog 可能沒有寫入完全 MySQL 就掛了。所以需要配合 redo log 才可以進行 crash safe。20、什么是兩階段提交?

MySQL 將 redo log 的寫入拆成了兩個步驟:prepare 和 commit,中間再穿插寫入binlog,這就是"兩階段提交"。

而兩階段提交就是讓這兩個狀態(tài)保持邏輯上的一致。redolog 用于恢復(fù)主機故障時的未更新的物理數(shù)據(jù),binlog 用于備份操作。兩者本身就是兩個獨立的個體,要想保持一致,就必須使用分布式事務(wù)的解決方案來處理。

為什么需要兩階段提交呢?

如果不用兩階段提交的話,可能會出現(xiàn)這樣情況先寫 redo log,crash 后 bin log 備份恢復(fù)時少了一次更新,與當(dāng)前數(shù)據(jù)不一致。先寫 bin log,crash 后,由于 redo log 沒寫入,事務(wù)無效,所以后續(xù) bin log 備份恢復(fù)時,數(shù)據(jù)不一致。兩階段提交就是為了保證 redo log 和 binlog 數(shù)據(jù)的安全一致性。只有在這兩個日志文件邏輯上高度一致了才能放心的使用。

在恢復(fù)數(shù)據(jù)時,redolog 狀態(tài)為 commit 則說明 binlog 也成功,直接恢復(fù)數(shù)據(jù);如果 redolog 是 prepare,則需要查詢對應(yīng)的 binlog事務(wù)是否成功,決定是回滾還是執(zhí)行。

21、MySQL 怎么知道 binlog 是完整的?

一個事務(wù)的 binlog 是有完整格式的:

statement 格式的 binlog,最后會有 COMMIT;row 格式的 binlog,最后會有一個 XID event。22、什么是 WAL 技術(shù),有什么優(yōu)點?

WAL,中文全稱是 Write-Ahead Logging,它的關(guān)鍵點就是日志先寫內(nèi)存,再寫磁盤。MySQL 執(zhí)行更新操作后,在真正把數(shù)據(jù)寫入到磁盤前,先記錄日志

好處是不用每一次操作都實時把數(shù)據(jù)寫盤,就算 crash 后也可以通過redo log 恢復(fù),所以能夠?qū)崿F(xiàn)快速響應(yīng) SQL 語句。

23、binlog 日志的三種格式

binlog 日志有三種格式

Statement:基于SQL語句的復(fù)制((statement-based replication,SBR))Row:基于行的復(fù)制。(row-based replication,RBR)Mixed:混合模式復(fù)制。(mixed-based replication,MBR)

Statement格式

每一條會修改數(shù)據(jù)的 SQL 都會記錄在 binlog 中

優(yōu)點:不需要記錄每一行的變化,減少了binlog日志量,節(jié)約了IO,提高性能。缺點:由于記錄的只是執(zhí)行語句,為了這些語句能在備庫上正確運行,還必須記錄每條語句在執(zhí)行的時候的一些相關(guān)信息,以保證所有語句能在備庫得到和在主庫端執(zhí)行時候相同的結(jié)果。

Row格式

不記錄 SQL 語句上下文相關(guān)信息,僅保存哪條記錄被修改。

優(yōu)點:binlog 中可以不記錄執(zhí)行的 SQL 語句的上下文相關(guān)的信息,僅需要記錄那一條記錄被修改成什么了。所以rowlevel的日志內(nèi)容會非常清楚的記錄下每一行數(shù)據(jù)修改的細節(jié)。不會出現(xiàn)某些特定情況下的存儲過程、或 function、或trigger的調(diào)用和觸發(fā)無法被正確復(fù)制的問題。缺點:可能會產(chǎn)生大量的日志內(nèi)容。

Mixed格式

實際上就是 Statement 與 Row 的結(jié)合。一般的語句修改使用 statment 格式保存 binlog,如一些函數(shù),statement 無法完成主從復(fù)制的操作,則采用 row 格式保存 binlog,MySQL 會根據(jù)執(zhí)行的每一條具體的 SQL 語句來區(qū)分對待記錄的日志形式。

24、redo log日志格式

redo log buffer (內(nèi)存中)是由首尾相連的四個文件組成的,它們分別是:ib_logfile_1、ib_logfile_2、ib_logfile_3、ib_logfile_4。

write pos 是當(dāng)前記錄的位置,一邊寫一邊后移,寫到第 3 號文件末尾后就回到 0 號文件開頭。checkpoint 是當(dāng)前要擦除的位置,也是往后推移并且循環(huán)的,擦除記錄前要把記錄更新到數(shù)據(jù)文件。write pos 和 checkpoint 之間的是“粉板”上還空著的部分,可以用來記錄新的操作。如果 write pos 追上 checkpoint,表示“粉板”滿了,這時候不能再執(zhí)行新的更新,得停下來先擦掉一些記錄,把 checkpoint 推進一下。有了 redo log,當(dāng)數(shù)據(jù)庫發(fā)生宕機重啟后,可通過 redo log將未落盤的數(shù)據(jù)(check point之后的數(shù)據(jù))恢復(fù),保證已經(jīng)提交的事務(wù)記錄不會丟失,這種能力稱為crash-safe。25、原本可以執(zhí)行得很快的 SQL 語句,執(zhí)行速度卻比預(yù)期的慢很多,原因是什么?如何解決?

原因:從大到小可分為四種情況

MySQL 數(shù)據(jù)庫本身被堵住了,比如:系統(tǒng)或網(wǎng)絡(luò)資源不夠。SQL 語句被堵住了,比如:表鎖,行鎖等,導(dǎo)致存儲引擎不執(zhí)行對應(yīng)的 SQL 語句。確實是索引使用不當(dāng),沒有走索引。表中數(shù)據(jù)的特點導(dǎo)致的,走了索引,但回表次數(shù)龐大。

解決:

考慮采用 force index 強行選擇一個索引考慮修改語句,引導(dǎo) MySQL 使用我們期望的索引。比如把“order by b limit 1” 改成 “order by b,a limit 1” ,語義的邏輯是相同的。第三種方法是,在有些場景下,可以新建一個更合適的索引,來提供給優(yōu)化器做選擇,或刪掉誤用的索引。如果確定是索引根本沒必要,可以考慮刪除索引。26、InnoDB 數(shù)據(jù)頁結(jié)構(gòu)

一個數(shù)據(jù)頁大致劃分七個部分

File Header:表示頁的一些通用信息,占固定的38字節(jié)。page Header:表示數(shù)據(jù)頁專有信息,占固定的56字節(jié)。inimum+Supermum:兩個虛擬的偽記錄,分別表示頁中的最小記錄和最大記錄,占固定的26字節(jié)。User Records:真正存儲我們插入的數(shù)據(jù),大小不固定。Free Space:頁中尚未使用的部分,大小不固定。Page Directory:頁中某些記錄的相對位置,也就是各個槽對應(yīng)的記錄在頁面中的地址偏移量。File Trailer:用于檢驗頁是否完整,占固定大小 8 字節(jié)。數(shù)據(jù)相關(guān)27、MySQL 是如何保證數(shù)據(jù)不丟失的?只要redolog 和 binlog 保證持久化磁盤就能確保MySQL異常重啟后回復(fù)數(shù)據(jù)在恢復(fù)數(shù)據(jù)時,redolog 狀態(tài)為 commit 則說明 binlog 也成功,直接恢復(fù)數(shù)據(jù);如果 redolog 是 prepare,則需要查詢對應(yīng)的 binlog事務(wù)是否成功,決定是回滾還是執(zhí)行。28、誤刪數(shù)據(jù)怎么辦?

DBA 的最核心的工作就是保證數(shù)據(jù)的完整性,先要做好預(yù)防,預(yù)防的話大概是通過這幾個點:

權(quán)限控制與分配(數(shù)據(jù)庫和服務(wù)器權(quán)限)制作操作規(guī)范定期給開發(fā)進行培訓(xùn)搭建延遲備庫做好 SQL 審計,只要是對線上數(shù)據(jù)有更改操作的語句(DML和DDL)都需要進行審核做好備份。備份的話又分為兩個點 (1)如果數(shù)據(jù)量比較大,用物理備份 xtrabackup。定期對數(shù)據(jù)庫進行全量備份,也可以做增量備份。(2)如果數(shù)據(jù)量較少,用 mysqldump 或者 mysqldumper。再利用 binlog 來恢復(fù)或者搭建主從的方式來恢復(fù)數(shù)據(jù)。定期備份binlog 文件也是很有必要的如果發(fā)生了數(shù)據(jù)刪除的操作,又可以從以下幾個點來恢復(fù):DML 誤操作語句造成數(shù)據(jù)不完整或者丟失。可以通過 flashback,美團的 myflash,也是一個不錯的工具,本質(zhì)都差不多都是先解析 binlog event,然后在進行反轉(zhuǎn)。把 delete 反轉(zhuǎn)為insert,insert 反轉(zhuǎn)為 delete,update前后 image 對調(diào)。所以必須設(shè)置binlog_format=row 和 binlog_row_image=full,切記恢復(fù)數(shù)據(jù)的時候,應(yīng)該先恢復(fù)到臨時的實例,然后在恢復(fù)回主庫上。DDL語句誤操作(truncate和drop),由于DDL語句不管 binlog_format 是 row 還是 statement ,在 binlog 里都只記錄語句,不記錄 image 所以恢復(fù)起來相對要麻煩得多。只能通過全量備份+應(yīng)用 binlog 的方式來恢復(fù)數(shù)據(jù)。一旦數(shù)據(jù)量比較大,那么恢復(fù)時間就特別長rm 刪除:使用備份跨機房,或者最好是跨城市保存。29、drop、truncate 和 delete 的區(qū)別DELETE 語句執(zhí)行刪除的過程是每次從表中刪除一行,并且同時將該行的刪除操作作為事務(wù)記錄在日志中保存以便進行進行回滾操作。TRUNCATE TABLE 則一次性地從表中刪除所有的數(shù)據(jù)并不把單獨的刪除操作記錄記入日志保存,刪除行是不能恢復(fù)的。并且在刪除的過程中不會激活與表有關(guān)的刪除觸發(fā)器。執(zhí)行速度快。drop語句將表所占用的空間全釋放掉。在速度上,一般來說,drop> truncate > delete。如果想刪除部分數(shù)據(jù)用 delete,注意帶上 where 子句,回滾段要足夠大;如果想刪除表,當(dāng)然用 drop;如果想保留表而將所有數(shù)據(jù)刪除,如果和事務(wù)無關(guān),用 truncate 即可;如果和事務(wù)有關(guān),或者想觸發(fā) trigger,還是用 delete;如果是整理表內(nèi)部的碎片,可以用 truncate 跟上 reuse stroage,再重新導(dǎo)入/插入數(shù)據(jù)。30、在 MySQL 中有兩個 kill 命令一個是 kill query + 線程 id,表示終止這個線程中正在執(zhí)行的語句一個是 kill connection + 線程 id,這里 connection 可缺省,表示斷開這個線程的連接

kill 不掉的原因

kill命令被堵了,還沒到位kill命令到位了,但是沒被立刻觸發(fā)kill命令被觸發(fā)了,但執(zhí)行完也需要時間31、如何理解 MySQL 的邊讀邊發(fā)如果客戶端接受慢,會導(dǎo)致 MySQL 服務(wù)端由于結(jié)果發(fā)不出去,這個事務(wù)的執(zhí)行時間會很長。服務(wù)端并不需要保存一個完整的結(jié)果集,取數(shù)據(jù)和發(fā)數(shù)據(jù)的流程都是通過一個 next_buffer 來操作的。內(nèi)存的數(shù)據(jù)頁都是在 Buffer_Pool中操作的。InnoDB 管理 Buffer_Pool 使用的是改進的 LRU 算法,使用鏈表實現(xiàn),實現(xiàn)上,按照 5:3 的比例把整個 LRU 鏈表分成了 young 區(qū)域和 old 區(qū)域。32、MySQL 的大表查詢?yōu)槭裁床粫瑑?nèi)存?由于 MySQL 是邊讀變發(fā),因此對于數(shù)據(jù)量很大的查詢結(jié)果來說,不會再 server 端保存完整的結(jié)果集,所以,如果客戶端讀結(jié)果不及時,會堵住 MySQL 的查詢過程,但是不會把內(nèi)存打爆。InnoDB 引擎內(nèi)部,由于有淘汰策略,InnoDB 管理 Buffer_Pool 使用的是改進的 LRU 算法,使用鏈表實現(xiàn),實現(xiàn)上,按照 5:3 的比例把整個 LRU 鏈表分成了 young 區(qū)域和 old 區(qū)域。對冷數(shù)據(jù)的全掃描,影響也能做到可控制。33、MySQL 臨時表的用法和特性只對當(dāng)前session可見??梢耘c普通表重名。增刪改查用的是臨時表。show tables 不顯示普通表。在實際應(yīng)用中,臨時表一般用于處理比較復(fù)雜的計算邏輯。由于臨時表是每個線程自己可見的,所以不需要考慮多個線程執(zhí)行同一個處理時臨時表的重名問題,在線程退出的時候,臨時表會自動刪除。34、MySQL 存儲引擎介紹(InnoDB、MyISAM、MEMORY)InnoDB 是事務(wù)型數(shù)據(jù)庫的首選引擎,支持事務(wù)安全表 (ACID),支持行鎖定和外鍵。MySQL5.5.5 之后,InnoDB 作為默認存儲引擎MyISAM 基于 ISAM 的存儲引擎,并對其進行擴展。它是在 Web、數(shù)據(jù)存儲和其他應(yīng)用環(huán)境下最常用的存儲引擎之一。MyISAM 擁有較高的插入、查詢速度,但不支持事務(wù)。在 MySQL5.5.5 之前的版本中,MyISAM 是默認存儲引擎MEMORY 存儲引擎將表中的數(shù)據(jù)存儲到內(nèi)存中,為查詢和引用其他表數(shù)據(jù)提供快速訪問。35、都說 InnoDB 好,那還要不要使用 MEMORY 引擎?內(nèi)存表就是使用 memory 引擎創(chuàng)建的表為什么我不建議你在生產(chǎn)環(huán)境上使用內(nèi)存表。這里的原因主要包括兩個方面:鎖粒度問題;數(shù)據(jù)持久化問題。由于重啟會丟數(shù)據(jù),如果一個備庫重啟,會導(dǎo)致主備同步線程停止;如果主庫跟這個備庫是雙 M 架構(gòu),還可能導(dǎo)致主庫的內(nèi)存表數(shù)據(jù)被刪掉。36、如果數(shù)據(jù)庫誤操作, 如何執(zhí)行數(shù)據(jù)恢復(fù)?

數(shù)據(jù)庫在某個時候誤操作,就可以找到距離誤操作最近的時間節(jié)點的bin log,重放到臨時數(shù)據(jù)庫里,然后選擇誤刪的數(shù)據(jù)節(jié)點,恢復(fù)到線上數(shù)據(jù)庫。

主從備份相關(guān)37、MySQL 是如何保證主備同步?

主備關(guān)系的建立:

一開始創(chuàng)建主備關(guān)系的時候,是由備庫指定的,比如基于位點的主備關(guān)系,備庫說“我要從binlog文件A的位置P”開始同步,主庫就從這個指定的位置開始往后發(fā)。而主備關(guān)系搭建之后,是主庫決定要發(fā)給數(shù)據(jù)給備庫的,所以主庫有新的日志也會發(fā)給備庫。

MySQL 主備切換流程:

客戶端讀寫都是直接訪問A,而節(jié)點B是備庫,只要將A的更新都同步過來,到本地執(zhí)行就可以保證數(shù)據(jù)是相同的。當(dāng)需要切換的時候就把節(jié)點換一下,A的節(jié)點B的備庫

一個事務(wù)完整的同步過程:

備庫B和主庫A建立來了長鏈接,主庫A內(nèi)部專門線程用于維護了這個長鏈接。在備庫B上通過changemaster命令設(shè)置主庫A的IP端口用戶名密碼以及從哪個位置開始請求binlog包括文件名和日志偏移量在備庫B上執(zhí)行start-slave命令備庫會啟動兩個線程:io_thread和sql_thread分別負責(zé)建立連接和讀取中轉(zhuǎn)日志進行解析執(zhí)行備庫讀取主庫傳過來的binlog文件備庫收到文件寫到本地成為中轉(zhuǎn)日志后來由于多線程復(fù)制方案的引入,sql_thread演化成了多個線程。38、什么是主備延遲

主庫和備庫在執(zhí)行同一個事務(wù)的時候出現(xiàn)時間差的問題,主要原因有:

有些部署條件下,備庫所在機器的性能要比主庫性能差。備庫的壓力較大。大事務(wù),一個主庫上語句執(zhí)行10分鐘,那么這個事務(wù)可能會導(dǎo)致從庫延遲10分鐘。39、為什么要有多線程復(fù)制策略?因為單線程復(fù)制的能力全面低于多線程復(fù)制,對于更新壓力較大的主庫,備庫可能是一直追不上主庫的,帶來的現(xiàn)象就是備庫上seconds_behind_master值越來越大。在實際應(yīng)用中,建議使用可靠性優(yōu)先策略,減少主備延遲,提升系統(tǒng)可用性,盡量減少大事務(wù)操作,把大事務(wù)拆分小事務(wù)。40、MySQL 的并行策略有哪些?按表分發(fā)策略:如果兩個事務(wù)更新不同的表,它們就可以并行。因為數(shù)據(jù)是存儲在表里的,所以按表分發(fā),可以保證兩個 worker 不會更新同一行。缺點:如果碰到熱點表,比如所有的更新事務(wù)都會涉及到某一個表的時候,所有事務(wù)都會被分配到同一個 worker 中,就變成單線程復(fù)制了。按行分發(fā)策略:如果兩個事務(wù)沒有更新相同的行,它們在備庫上可以并行。如果兩個事務(wù)沒有更新相同的行,它們在備庫上可以并行執(zhí)行。顯然,這個模式要求 binlog 格式必須是 row。缺點:相比于按表并行分發(fā)策略,按行并行策略在決定線程分發(fā)的時候,需要消耗更多的計算資源。41、MySQL的一主一備和一主多從有什么區(qū)別?

在一主一備的雙 M 架構(gòu)里,主備切換只需要把客戶端流量切到備庫;而在一主多從架構(gòu)里,主備切換除了要把客戶端流量切到備庫外,還需要把從庫接到新主庫上。

42、主庫出問題如何解決?基于位點的主備切換:存在找同步位點這個問題MySQL 5.6 版本引入了 GTID,徹底解決了這個困難。那么,GTID 到底是什么意思,又是如何解決找同步位點這個問題呢?GTID:全局事務(wù) ID,是一個事務(wù)在提交的時候生成的,是這個事務(wù)的唯一標(biāo)識;它由兩部分組成,格式是:GTID=server_uuid:gno每個 MySQL 實例都維護了一個 GTID 集合,用來對應(yīng)“這個實例執(zhí)行過的所有事務(wù)”。在基于 GTID 的主備關(guān)系里,系統(tǒng)認為只要建立主備關(guān)系,就必須保證主庫發(fā)給備庫的日志是完整的。因此,如果實例 B 需要的日志已經(jīng)不存在,A’就拒絕把日志發(fā)給 B。43、MySQL 讀寫分離涉及到過期讀問題的幾種解決方案?強制走主庫方案sleep 方案判斷主備無延遲方案配合 semi-sync 方案等主庫位點方案GTID 方案。實際生產(chǎn)中,先客戶端對請求做分類,區(qū)分哪些請求可以接受過期讀,而哪些請求完全不能接受過期讀;然后,對于不能接受過期讀的語句,再使用等 GTID 或等位點的方案。44、MySQL的并發(fā)鏈接和并發(fā)查詢有什么區(qū)別?在執(zhí)行show processlist的結(jié)果里,看到了幾千個連接,指的是并發(fā)連接。而"當(dāng)前正在執(zhí)行"的語句,才是并發(fā)查詢。并發(fā)連接數(shù)多影響的是內(nèi)存,并發(fā)查詢太高對CPU不利。一個機器的CPU核數(shù)有限,線程全沖進來,上下文切換的成本就會太高。所以需要設(shè)置參數(shù):innodb_thread_concurrency 用來限制線程數(shù),當(dāng)線程數(shù)達到該參數(shù),InnoDB就會認為線程數(shù)用完了,會阻止其他語句進入引擎執(zhí)行。性能相關(guān)45、短時間提高 MySQL 性能的方法第一種方法:先處理掉那些占著連接但是不工作的線程?;蛘咴倏紤]斷開事務(wù)內(nèi)空閑太久的連接。kill connection + id第二種方法:減少連接過程的消耗:慢查詢性能問題在 MySQL 中,會引發(fā)性能問題的慢查詢,大體有以下三種可能:索引沒有設(shè)計好;SQL 語句沒寫好;MySQL 選錯了索引(force index)。46、為什么 MySQL 自增主鍵 ID 不連續(xù)?唯一鍵沖突事務(wù)回滾自增主鍵的批量申請深層次原因是:MySQL 不判斷自增主鍵是否存在,從而減少加鎖的時間范圍和粒度,這樣能保持更高的性能,確保自增主鍵不能回退,所以才有自增主鍵不連續(xù)。自增主鍵怎么做到唯一性?自增值加1來通過自增鎖控制并發(fā)。47、InnoDB 為什么要用自增 ID 作為主鍵?自增主鍵的插入模式,符合遞增插入,每次都是追加操作,不涉及挪動記錄,也不會觸發(fā)葉子節(jié)點的分裂。每次插入新的記錄就會順序添加到當(dāng)前索引節(jié)點的后續(xù)位置,當(dāng)一頁寫滿,就會自動開辟一個新的頁。而有業(yè)務(wù)邏輯的字段做主鍵,不容易保證有序插入,由于每次插入主鍵的值近似于隨機因此每次新紀(jì)錄都要被插到現(xiàn)有索引頁得中間某個位置, 頻繁的移動、分頁操作造成了大量的碎片,得到了不夠緊湊的索引結(jié)構(gòu),寫數(shù)據(jù)成本較高。48、如何最快的復(fù)制一張表?為了避免對源表加讀鎖,更穩(wěn)妥的方案是先將數(shù)據(jù)寫到外部文本文件,然后再寫回目標(biāo)表一種方法是,使用 mysqldump 命令將數(shù)據(jù)導(dǎo)出成一組 INSERT 語句另一種方法是直接將結(jié)果導(dǎo)出成.csv 文件。MySQL 提供語法,用來將查詢結(jié)果導(dǎo)出到服務(wù)端本地目錄:select * from db1.t where a>900 into outfile '/server_tmp/t.csv';得到.csv 導(dǎo)出文件后,你就可以用下面的 load data 命令將數(shù)據(jù)導(dǎo)入到目標(biāo)表 db2.t 中:load data infile '/server_tmp/t.csv' into table db2.t;物理拷貝:在 MySQL 5.6 版本引入了可傳輸表空間(transportable tablespace) 的方法,可以通過導(dǎo)出 + 導(dǎo)入表空間的方式,實現(xiàn)物理拷貝表的功能。49、grant 和 flush privileges語句grant語句會同時修改數(shù)據(jù)表和內(nèi)存,判斷權(quán)限的時候使用的內(nèi)存數(shù)據(jù),因此,規(guī)范使用是不需要加上 flush privileges 語句。flush privileges 語句本身會用數(shù)據(jù)表的數(shù)據(jù)重建一份內(nèi)存權(quán)限數(shù)據(jù),所以在權(quán)限數(shù)據(jù)可能存在不一致的情況下再使用。50、要不要使用分區(qū)表?分區(qū)并不是越細越好。實際上,單表或者單分區(qū)的數(shù)據(jù)一千萬行,只要沒有特別大的索引,對于現(xiàn)在的硬件能力來說都已經(jīng)是小表了。分區(qū)也不要提前預(yù)留太多,在使用之前預(yù)先創(chuàng)建即可。比如,如果是按月分區(qū),每年年底時再把下一年度的 12 個新分區(qū)創(chuàng)建上即可。對于沒有數(shù)據(jù)的歷史分區(qū),要及時的 drop 掉。51、join 用法使用 left join 左邊的表不一定是驅(qū)動表如果需要 left join 的語義,就不能把被驅(qū)動表的字段放在 where 條件里面做等值判斷或不等值判斷,必須都寫在 on 里面標(biāo)準(zhǔn)的 group by 語句,是需要在 select 部分加一個聚合函數(shù),比如select a,count(*) from t group by a order by null;52、MySQL 有哪些自增ID?各自場景是什么?表的自增 ID 達到上限之后,在申請值不會變化,進而導(dǎo)致聯(lián)系插入數(shù)據(jù)的時候報主鍵沖突錯誤。row_id 達到上限之后,歸 0 在重新遞增,如果出現(xiàn)相同的 row_id 后寫的數(shù)據(jù)會覆蓋之前的數(shù)據(jù)。Xid 只需要不在同一個 binlog 文件出現(xiàn)重復(fù)值即可,理論上會出現(xiàn)重復(fù)值,但概率極小可忽略不計。InnoDB 的 max_trx_id 遞增值每次 MySQL 重啟會保存起來。Xid 是由 server 層維護的。InnoDB 內(nèi)部使用 Xid,就是為了能夠在 InnoDB 事務(wù)和 server 之間做關(guān)聯(lián)。但是,InnoDB 自己的 trx_id,是另外維護的。thread_id 是我們使用中最常見的,而且也是處理得最好的一個自增 id 邏輯了。使用了insert_unique算法53、Xid 在 MySQL 內(nèi)部是怎么生成的呢?

MySQL 內(nèi)部維護了一個全局變量 global_query_id,每次執(zhí)行語句(包括select語句)的時候?qū)⑺x值給 Query_id,然后給這個變量加 1。如果當(dāng)前語句是這個事務(wù)執(zhí)行的第一條語句,那么 MySQL 還會同時把 Query_id 賦值給這個事務(wù)的 Xid。

而 global_query_id 是一個純內(nèi)存變量,重啟之后就清零了。所以你就知道了,在同一個數(shù)據(jù)庫實例中,不同事務(wù)的 Xid 也是有可能相同的。但是 MySQL 重啟之后會重新生成新的 binlog 文件,這就保證了,同一個 binlog 文件里,Xid 一定是惟一的。

鎖相關(guān)54、說一下 MySQL 的鎖MySQL 在 server 層 和 存儲引擎層 都運用了大量的鎖MySQL server 層需要講兩種鎖,第一種是MDL(metadata lock) 元數(shù)據(jù)鎖,第二種則 Table Lock 表鎖。MDL 又名元數(shù)據(jù)鎖,那么什么是元數(shù)據(jù)呢,任何描述數(shù)據(jù)庫的內(nèi)容就是元數(shù)據(jù),比如我們的表結(jié)構(gòu)、庫結(jié)構(gòu)等都是元數(shù)據(jù)。那為什么需要 MDL 呢?主要解決兩個問題:事務(wù)隔離問題;數(shù)據(jù)復(fù)制問題InnoDB 有五種表級鎖:IS(意向讀鎖);IX(意向?qū)戞i);S(讀);X(寫);AUTO-INC在對表進行select/insert/delete/update語句時候不會加表級鎖IS和IX的作用是為了判斷表中是否有已經(jīng)被加鎖的記錄自增主鍵的保障就是有 AUTO-INC 鎖,是語句級別的:為表的某個列添加 AUTO_INCREMENT 屬性,之后在插?記錄時,可以不指定該列的值,系統(tǒng)會?動為它賦上單調(diào)遞增的值。InnoDB 4 種行級鎖RecordLock:記錄鎖GapLock:間隙鎖解決幻讀;前一次查詢不存在的東西在下一次查詢出現(xiàn)了,其實就是事務(wù)A中的兩次查詢之間事務(wù)B執(zhí)行插入操作被事務(wù)A感知了Next-KeyLock:鎖住某條記錄又想阻止其它事務(wù)在改記錄前面的間隙插入新紀(jì)錄InsertIntentionLock:插入意向鎖;如果插入到同一行間隙中的多個事務(wù)未插入到間隙內(nèi)的同一位置則無須等待行鎖和表鎖的抉擇全表掃描用行級鎖55、什么是幻讀?

值在同一個事務(wù)中,存在前后兩次查詢同一個范圍的數(shù)據(jù),第二次看到了第一次沒有查詢到的數(shù)據(jù)。

幻讀出現(xiàn)的場景:

事務(wù)的隔離級別是可重復(fù)讀,且是當(dāng)前讀?;米x指新插入的行。

幻讀帶來的問題:

對行鎖語義的破壞破壞了數(shù)據(jù)一致性

解決:

加間隙鎖,鎖住行與行之間的間隙,阻塞新插入的操作。帶來的問題:降低并發(fā)度,可能導(dǎo)致死鎖。其它為什么系列56、為什么 MySQL 會抖一下?臟頁會被后臺線程自動 flush,也會由于數(shù)據(jù)頁淘汰而觸發(fā) flush,而刷臟頁的過程由于會占用資源,可能會讓你的更新和查詢語句的響應(yīng)時間長一些。57、為什么刪除了表,表文件的大小還是沒變?數(shù)據(jù)項刪除之后 InnoDB 某個頁 page A 會被標(biāo)記為可復(fù)用。delete 命令把整個表的數(shù)據(jù)刪除,結(jié)果就是,所有的數(shù)據(jù)頁都會被標(biāo)記為可復(fù)用。但是磁盤上,文件不會變小。經(jīng)過大量增刪改的表,都是可能是存在空洞的。這些空洞也占空間所以,如果能夠把這些空洞去掉,就能達到收縮表空間的目的。重建表,就可以達到這樣的目的。可以使用 alter table A engine=InnoDB 命令來重建表。58、count(*)實現(xiàn)方式以及各種 count 對比對于 count(主鍵 id) 來說,InnoDB 引擎會遍歷整張表,把每一行的 id 值都取出來,返回給 server 層。server 層拿到 id 后,判斷是不可能為空的,就按行累加。對于 count(1) 來說,InnoDB 引擎遍歷整張表,但不取值。server 層對于返回的每一行,放一個數(shù)字“1”進去,判斷是不可能為空的,按行累加。單看這兩個用法的差別的話,你能對比出來,count(1) 執(zhí)行得要比 count(主鍵 id) 快。因為從引擎返回 id 會涉及到解析數(shù)據(jù)行,以及拷貝字段值的操作。對于 count(字段) 來說:如果這個“字段”是定義為 not null 的話,一行行地從記錄里面讀出這個字段,判斷不能為 null,按行累加;如果這個“字段”定義允許為 null,那么執(zhí)行的時候,判斷到有可能是 null,還要把值取出來再判斷一下,不是 null 才累加。也就是前面的第一條原則,server 層要什么字段,InnoDB 就返回什么字段。但是 count * 是例外,并不會把全部字段取出來,而是專門做了優(yōu)化,不取值。count(*) 肯定不是 null,按行累加。所以結(jié)論是:按照效率排序的話,count(字段)<count(主鍵 id)<count(1)≈count(※),所以建議盡量使用 count(*)。59、orderby 排序內(nèi)部原理MySQL 會為每個線程分配一個內(nèi)存(sort-buffer)用于排序該內(nèi)存大小為 sort_buffer_size;如果排序的數(shù)據(jù)量小于 sort_buffer_size,排序就會在內(nèi)存中完成;內(nèi)部排序分為兩種全字段排序:到索引樹上找到滿足條件的主鍵ID根據(jù)主鍵ID去取出數(shù)據(jù)放到sort_buffer然后進行快速排序rowid排序:通過控制排序的行數(shù)據(jù)的長度來讓sort_buffer中盡可能多的存放數(shù)據(jù)如果數(shù)據(jù)量很大,內(nèi)存中無法存下這么多,就會使用磁盤臨時文件來輔助排序,稱為外部排序;外部排序,MySQL會分為好幾份單獨的臨時文件來存放排序后的數(shù)據(jù),一般是磁盤文件中進行歸并,然后將這些文件合并成一個大文件;60、如何高效的使用 MySQL 顯式隨機消息隨機取出 Y1,Y2,Y3之后,算出Ymax,Ymin得到id集后算出Y1、Y2、Y3對應(yīng)的三個id 最后 select * from t where id in (id1, id2, id3) 這樣掃描的行數(shù)應(yīng)該是C+Ymax+3mysql> select count(*) into @C from t;set @Y1 = floor(@C * rand());set @Y2 = floor(@C * rand());set @Y3 = floor(@C * rand());Ymax = max(Y1,Y2,Y3)Ymin = min(Y1,Y2,Y3)select id from t limit Ymin,(Ymax - Ymin)

持續(xù)更新中。

參考:

極客時間《MySQL實戰(zhàn) 45 講》https://www.nowcoder.com/discuss/744934?type=1&order=0&pos=25&page=1&ncTraceId=&channel=-1&source_id=discuss_tag_nctrack

轉(zhuǎn)載自:微信公眾號,herongwei

以上就是關(guān)于pos機專業(yè)面試,數(shù)據(jù)庫精選 60 道面試題的知識,后面我們會繼續(xù)為大家整理關(guān)于pos機專業(yè)面試的知識,希望能夠幫助到大家!

轉(zhuǎn)發(fā)請帶上網(wǎng)址:http://m.nxzs9ef.cn/newstwo/101388.html

你可能會喜歡:

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請發(fā)送郵件至 babsan@163.com 舉報,一經(jīng)查實,本站將立刻刪除。