后端面試題(mysql常見知識(shí)點(diǎn))

為什么分庫分表

  • 單表數(shù)據(jù)量過大,會(huì)出現(xiàn)慢查詢,所以需要水平分表

  • 可以把低頻、高頻的字段分開為多個(gè)表,低頻的表作為附加表,且邏輯更加清晰,性能更優(yōu)

  • 隨著系統(tǒng)的業(yè)務(wù)模塊的增多,放到單庫會(huì)增加其復(fù)雜度,邏輯不清晰,不好維護(hù),所以會(huì)對(duì)業(yè)務(wù)進(jìn)行微服務(wù)拆分,同時(shí)拆分?jǐn)?shù)據(jù)庫

  • 怎么分庫分表

  • 對(duì)于水平,不同的業(yè)務(wù)按不同的條件去分,比如財(cái)務(wù)數(shù)據(jù),可以按年份作為庫,月份做為表。 比如多用戶系統(tǒng),可以按用戶id取模劃分。
  • 對(duì)于垂直,一般按不同的業(yè)務(wù)模塊來劃分即可
  • 事務(wù)

  • 原子性(Atomicity):指事務(wù)是一個(gè)不可分割的最小工作單位,事務(wù)中的操作只有都發(fā)生和都不發(fā)生兩種情況

  • 一致性(Consistency):事務(wù)必須使數(shù)據(jù)庫從一個(gè)一致狀態(tài)變換到另外一個(gè)一致狀態(tài),舉一個(gè)栗子,李二給王五轉(zhuǎn)賬50元,其事務(wù)就是讓李二賬戶上減去50元,王五賬戶上加上50元;一致性是指其他事務(wù)看到的情況是要么李二還沒有給王五轉(zhuǎn)賬的狀態(tài),要么王五已經(jīng)成功接收到李二的50元轉(zhuǎn)賬。而對(duì)于李二少了50元,王五還沒加上50元這個(gè)中間狀態(tài)是不可見的。

  • 隔離性(Isolation):一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾,即一個(gè)事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對(duì)并發(fā)的其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾。

  • 持久性(Durability):一個(gè)事務(wù)一旦提交成功,它對(duì)數(shù)據(jù)庫中數(shù)據(jù)的改變將是永久性的,接下來的其他操作或故障不應(yīng)對(duì)其有任何影響。

  • 悲觀鎖,排他鎖,寫鎖

    數(shù)據(jù)更新、插入、刪除都是帶鎖的。 只有獲得鎖才能更新數(shù)據(jù),如果查詢其他也有for update 或者讀鎖,那么他的查詢也不能更新

  • select * from table where id=xx for update;

  • 盡量要帶上條件,且條件一定要有索引, 避免鎖表

    讀鎖,共享鎖

  • select ... lock in share mode;

  • 讀鎖相互可以兼容,與寫鎖沖突,所以如果數(shù)據(jù)上了寫鎖,讀鎖就要等待。同理,如果數(shù)據(jù)上了讀鎖,寫鎖就要等待查看鎖

  • 鎖情況 select * from information_schema.innodb_locks;

  • 引擎整體情況 包括鎖 show engine innodb status;

  • 索引

  • 對(duì)于聯(lián)合索引 index(a,b,c), 5.7版本及之前遵從最左匹配原則,就是說 單純是 a和ab和abc和ac走索引,其他不走

  • 當(dāng)存在多個(gè)索引,possible keys有多個(gè),但是使用的時(shí)候mysql會(huì)選取成本最少的那一個(gè)使用

  • 什么字段適合加索引? where order by group by

  • 不應(yīng)該建立索引的字段規(guī)則 1.不應(yīng)該在字段比較長的字段上建立索引,因?yàn)闀?huì)消耗大量的空間 2.對(duì)于頻繁更新、插入的字段應(yīng)該少建立索引,因?yàn)樵谛薷暮筒迦胫?,?shù)據(jù)庫會(huì)去維護(hù)索引,會(huì)消耗資源 3.盡量少在無用字段上建立索引【where條件中用不到的字段】 4.表記錄太少不應(yīng)該創(chuàng)建索引 5.數(shù)據(jù)重復(fù)且分布平均的表字段不應(yīng)該創(chuàng)建索引【選擇性太低,例如性別、狀態(tài)、真假值等字段】

  • 通常場景,IN條件查詢走索引;

  • 當(dāng)IN多條件查詢時(shí),例子: id in (1,2)。 如果數(shù)據(jù)量大于總數(shù)據(jù)量30%(這個(gè)數(shù)好像不準(zhǔn)確),就會(huì)走全表掃描(暫未找到官方結(jié)論,但在Mysql版本為8.0.18中,本人驗(yàn)證基本符合上述結(jié)論);

  • 當(dāng)IN是單條件,例子:id in (1) 數(shù)據(jù)量大于總數(shù)據(jù)30%時(shí),依然走索引。

  • 隔離級(jí)別

  • 臟讀:事務(wù)a讀到了事務(wù)b未提交到數(shù)據(jù)

  • 不可重復(fù)讀:事務(wù)a讀到了事務(wù)提交的數(shù)據(jù)

  • 幻讀:事務(wù)a讀到了事務(wù)b insert的數(shù)據(jù)(第一次查詢讀條數(shù)和第二次讀不同)

  • 級(jí)別臟讀不可重復(fù)讀幻讀Read uncommitted√v√Read committed Sql Server -- Oracle×v√Repeatable read Mysql××√Serializable×××

    但是mysql的innodb通過mvcc機(jī)制避免了幻讀。

  • 普通讀(快照讀,即普通的select)讀到的是歷史版本的數(shù)據(jù),

  • 當(dāng)前讀(select..for update , insert , update, delete)這些因?yàn)樾枰薷臄?shù)據(jù),所以就不能讀 歷史數(shù)據(jù),所以就會(huì)加鎖阻塞。

  • 但是如果是穿插使用的話--先普通讀再當(dāng)前讀,是無法避免幻讀的。

  • mvcc

  • 多版本并發(fā)控制技術(shù)
  • 為了解決并發(fā)安全問題+提高并發(fā)處理能力+解決讀寫沖突
  • 讀寫并發(fā)阻塞問題,提高并發(fā)讀寫能力
  • 采用樂觀鎖的實(shí)現(xiàn),降低了死鎖的概率, 因?yàn)橛袀€(gè)事務(wù)id
  • 解決一致性讀讀問題,可重復(fù)讀
  • 悲觀鎖用來解決寫和寫讀沖突
  • 底層原理:
  • 主要實(shí)現(xiàn)rr rc的隔離級(jí)別。 通過undolog readview技術(shù)共同實(shí)現(xiàn)可重復(fù)讀、讀已提交 undolog: 事務(wù)的歷史版本鏈表,全局(多個(gè)事務(wù)共享)維護(hù)一個(gè), 每一行有一個(gè)遞增的事務(wù)id 前一個(gè)版本的指針 和一個(gè)隱藏的rowid readview:每個(gè)事務(wù)開啟的時(shí)候,當(dāng)前讀后生成一個(gè)readview。有 trx_ids(活躍-未提交的事務(wù)id) min_trx_id(trx_ids中最?。? max_rtx_id(預(yù)分配的下一個(gè)trx_id) creator_trx_id (創(chuàng)建readview的trx_id)

    匹配規(guī)則: 如果數(shù)據(jù)事務(wù)ID trx_id < min_limit_id,表明生成該版本的事務(wù)在生成Read View前,已經(jīng)提交(因?yàn)槭聞?wù)ID是遞增的),所以該版本可以被當(dāng)前事務(wù)訪問。 如果trx_id>= max_limit_id,表明生成該版本的事務(wù)在生成ReadView后才生成,所以該版本不可以被當(dāng)前事務(wù)訪問。 如果 min_limit_id =<trx_id< max_limit_id,需腰分3種情況討論

    (1).如果m_ids包含trx_id,則代表Read View生成時(shí)刻,這個(gè)事務(wù)還未提交,但是如果數(shù)據(jù)的trx_id等于creator_trx_id的話,表明數(shù)據(jù)是自己生成的,因此是可見的。

    (2)如果m_ids包含trx_id,并且trx_id不等于creator_trx_id,則Read View生成時(shí),事務(wù)未提交,并且不是自己生產(chǎn)的,所以當(dāng)前事務(wù)也是看不見的;

    (3).如果m_ids不包含trx_id,則說明你這個(gè)事務(wù)在Read View生成之前就已經(jīng)提交了,修改的結(jié)果,當(dāng)前事務(wù)是能看見的

    rr: 使用第一次當(dāng)前讀創(chuàng)建的readview rc: 每一次當(dāng)前讀都更新readview

    三范式

  • 第一范式(1NF):每個(gè)列都不可以再拆分。(比如地址,如果用到城市、省份的數(shù)據(jù)的話,一定還要繼續(xù)拆分)

  • 第二范式(2NF):在第一范式的基礎(chǔ)上,非主鍵列完全依賴于主鍵,而不能是依賴于主鍵的一部分。(在第一范式的基礎(chǔ)上消除非主鍵對(duì)主鍵的部分依賴, 比如成績表有學(xué)號(hào)、學(xué)生、系主任、系名、課程、分?jǐn)?shù)), 其實(shí)如果學(xué)號(hào)+課程為主鍵就能確定分?jǐn)?shù),所以其他無關(guān)的字段就可以分離出去)

  • 第三范式(3NF):在第二范式的基礎(chǔ)上,非主鍵列只依賴于主鍵,不依賴于其他非主鍵。(其實(shí)說白了就是面向?qū)ο缶幊痰乃枷耄热纾喊严得?、系主任拆到另一張表?/p>

  • 但也不一定必須滿足3范式,對(duì)于數(shù)據(jù)量大的業(yè)務(wù)其實(shí)要避免3表及以上的join操作,因?yàn)橐苊鉀]有用到索引,而是用一張寬表記錄,查詢即可。

    怎么保證acid

  • 原子性: undolog, 保留一份事務(wù)中語句的操作日志,當(dāng)執(zhí)行發(fā)生錯(cuò)誤時(shí)候,進(jìn)行回滾,用反向邏輯執(zhí)行操作語句。

  • 持久性: redolog, 無論是redolog,還是正常當(dāng)數(shù)據(jù),都是先寫到buffer,在寫到磁盤。但是redolog是通過追加當(dāng)模式寫入,即:順序?qū)?。而?shù)據(jù) 是隨機(jī)寫,明顯速度更慢,而且mysql是按頁即16kb的傳輸,所以更慢。采用了先持久化到redolog的方式。 innodb_flush_log_at_trx_commit = 1為 redolog同步到磁盤。如果是0,則系統(tǒng)每秒刷一次buffer到內(nèi)存。

  • 隔離性:寫寫操作,通過鎖。寫讀操作,mvcc。

  • 一致性:事務(wù)到目的,上面三種特性共同保障數(shù)據(jù)最終一致性

  • 數(shù)據(jù)庫出現(xiàn)慢查詢原因

  • 硬件資源問題,如內(nèi)存不足

  • 出現(xiàn)高并發(fā),查詢數(shù)量過大

  • 沒有建立索引

  • sql沒有命中索引

  • 返回很多不必要的數(shù)據(jù)

  • 數(shù)據(jù)庫數(shù)量大

  • 一億訂單數(shù)據(jù)如何設(shè)計(jì)數(shù)據(jù)庫,需要賣家、狀態(tài)進(jìn)行查詢

  • 水平分表

  • 通過買家好hash (因?yàn)橥ㄟ^買家查詢的量是很大的)

  • 做好映射,比如:賣家:買家列表--> 買家通過路由規(guī)則找到表 --> 再通過條件進(jìn)行查詢 --> 合并

  • innodb myisam區(qū)別

  • 事務(wù)

  • 外鍵

  • innodb:聚簇索引 不支持fulltext 但可以通過sphinx插件支持。 myisam: 非聚簇 支持fulltext全文索引

  • 行鎖 表鎖

  • 存儲(chǔ)文件, innodb兩個(gè):.frm(表定義) .ibd(數(shù)據(jù)和索引存儲(chǔ)) myisam三個(gè): .frm .myd(數(shù)據(jù)存儲(chǔ)) .myi(索引存儲(chǔ))

  • 為啥不用b樹

    b樹非頁子節(jié)點(diǎn)保存有數(shù)據(jù),如果按照一行數(shù)據(jù)1k,不算上指針和鍵值的情況下,一個(gè)節(jié)點(diǎn)是16k,也就最大是16行數(shù)據(jù), 所以3層b樹最多是 16 * 16 * 16 = 4096行,太少了,所以只能增加層高,意味著增加io次數(shù),所以這個(gè)方案不可用

    redolog和binglog有啥不同

  • 使用場景不同:binlog主要用于備份、遷移、數(shù)據(jù)同步, redolog主要保證事務(wù)的持久性,遇到故障時(shí)候提供回滾重放操作

  • 記錄時(shí)機(jī)不同,binglog是在commit之后再一次性記錄的,redolog是事務(wù)中執(zhí)行的時(shí)候一條一條記錄的

  • binlog是記錄執(zhí)行語句,redolog是記錄物理塊的數(shù)據(jù)變更

  • ?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
    【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
    平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

    相關(guān)閱讀更多精彩內(nèi)容

    友情鏈接更多精彩內(nèi)容