1. 程式人生 > 資料庫 >MySQL面試複習題

MySQL面試複習題

MySQL 索引的原理和資料結構能介紹一下嗎?

  1. MySQL使用的資料結構為B+樹

B+ 樹和 B- 樹有什麼區別?

  1. B-樹的資料是存放在索引結點上,而B+樹的資料是存放在索引結點只作為索引使用,資料存放在葉子結點上(MyIsam和Innodb不一樣)
  2. B+樹葉子結點的資料都存放在連結串列中,且連結串列資料都是有序儲存的

為什麼MySQL資料庫索引使用B+樹

  1. 跟其他樹相比,B+樹索引結點上並沒有存放具體資料,因此磁碟讀寫代價更低。
  2. 根據上面說到的,B+樹葉子結點存放在連結串列的特性,非常適合做範圍查詢。

使用 MySQL 索引都有哪些原則?

  1. 索引不宜過多,過多的索引會導致操作執行效率低下
  2. 只對查詢頻繁的欄位做索引
  3. 對排序、分組、聯合查詢頻率高的欄位做索引

MySQL 聚簇索引和二級索引的區別是什麼?他們分別是如何儲存的?

  1. 資料儲存和索引都在一起,炸到索引就能找到資料。
  2. 資料儲存和索引是分開的,在innodb中,二級索引儲存的並非資料實體地址,而是主鍵值,因此通過二級索引查詢會導致查詢兩次。

MySQL InnoDB 如何防止記憶體緩衝區被汙染?

緩衝池機制主要目的是避免每次訪問磁碟,快速資料訪問。

InnoDB是使用LRU演算法來管理緩衝頁。

但傳統的LRU連結串列是無法滿足Mysql的要求的,主要有兩個問題:

  1. 預讀失效

    Mysql會預先把可能會被訪問的資料提前放入緩衝池,但如果大量沒擊中,那就很浪費效能了。

    這時候Mysql就對LRU進行了優化,拆分為兩部分

    新生代(5/8):存放真正預讀成功的資料,並延長他的存活時間。

    老生代(3/8):存放預讀的資料,但存活時間會盡可能短。

    這樣就能解決預讀失敗了,但解決不了緩衝池汙染。

  2. 緩衝池汙染

    在掃描大量資料時,頁會把資料載入到緩衝池(老年代的頭部),然後在1s不到又訪問到了他,這時候他就會成為熱資料,而假如是全表掃描的話,那就會把所有的真正的熱資料被大量換出。

    因此Mysql加入了“老生代停留時間視窗(innodb_old_blocks_time)”的機制,只有在“被訪問”並且大於“老生代停留時間視窗”,才會被放入新生代頭部。預設是1000

參考文章:


MySQL InnoDB 事務隔離級別如何實現?

隔離級別 髒讀 不可重複讀 幻讀
未提交讀(Read uncommitted) 可能 可能 可能
已提交讀(Read committed) 不可能 可能 可能
可重複讀(Repeatable read) 不可能 不可能 可能
可序列化(Serializable) 不可能 不可能 不可能
  • 未提交讀(Read Uncommitted):允許髒讀,也就是可能讀取到其他會話中未提交事務修改的資料
  • 已提交讀(Read Committed):只能讀取到已經提交的資料。Oracle等多數資料庫預設都是該級別 (不重複讀)
  • 可重複讀(Repeated Read):可重複讀。在同一個事務內的查詢都是事務開始時刻一致的,InnoDB預設級別。在SQL標準中,該隔離級別消除了不可重複讀,但是還存在幻象讀
  • 可序列化(Serializable):完全序列化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞

InnoDB預設是行級鎖,內部會生成三個隱藏欄位:db_trx_id(事務id)、db_roll_pt(回滾指標)、delete_flag(刪除標記)


版本鏈使用場景(readView)

  1. 當前操作的事務id為102,假設版本鏈資料[1,2,100,101],活躍列表為[100,101],活躍列表就是未提交的活躍事務,因此事務2是已提交,所以事務5會拷貝一份事務2並插入版本鏈最後一個元素
  2. 當隔離界別為可重複讀,需要操作事務查詢或修改時,那麼就單獨讀取事務102的資料,這樣就能實現隔離其他未提交的事務。
  3. 當隔離界別為讀已提交,流程跟可重複讀差不多,但在每次讀取資料前都會生成一個readView,保證不會查詢到當前事務未提交的資料。

DML操作

  • INSERT:建立一條資料,db_trx_id 的值為當前事務 id, db_roll_pt 為 null 。
  • UPDATE:複製一行資料,將當前複製後這一行的 db_trx_id 置為當前事務的 id,db_roll_pt 是一個指標,指向複製前的那一條的。
  • DELETE:複製一行資料,將當前複製後這一行的 db_trx_id 置為當前事務的 id,db_roll_pt 是一個指標,指向複製前的那一條的。並把 delete_flag 置為 true 。

B+樹是如何分裂的

待更新