MySQL 複習總結(MySQL面試必過!!!)

注:本篇是看了別人寫的一些面試題,然後記錄一下面試題的連接以及自己對面試題部分知識點的理解

 

我首先看的文章是下面這個,真的是太多了,有的沒有說的很深,需要再進一步學習下。可以先看下面鏈接這篇文章,我是看了這個文章寫的面試題,把一些不是很清晰記錄到這篇博客了。

https://blog.csdn.net/ThinkWon/article/details/104778621

 

 

1.MySQL text長度

mysql的text是65535的字節限制,而pg是不限制的、

2.覆蓋索引**聚簇索引(https://blog.csdn.net/alexdamiao/article/details/51934917)

索引覆蓋指的是,select 的列在索引中完全包括了,從二級索引拿就行了,不用再查一遍聚簇索引了。
聚簇索引中的每個葉子節點包含主鍵值、事務ID、回滾指針(rollback pointer用於事務和MVCC)和餘下的列。
對於非主鍵索引---包含了主鍵值。通過二級索引查詢首先查到是主鍵值,然後InnoDB再根據查到的主鍵值通過主鍵索引找到相應的數據塊。
主鍵會創建聚簇索引。

https://blog.csdn.net/universsky2015/article/details/102712058   這個裏面的圖清晰的解釋了。


innodb分主鍵索引和輔助索引,除了主鍵索引都是輔助索引(二級索引),都是使用的B+樹,B+樹數據解節點可以存儲更多的鍵值,然後葉子節點存儲data這樣就查的很快,B+樹非常的矮胖,這樣減少IO次數。
如果查輔助索引的話,輔助索引的葉子節點data存儲的是主鍵值,這樣就轉到查詢主鍵索引了,而索引覆蓋指的是 select 項只有你查詢的索引鍵值,不在查主鍵索引了。

聯合索引的B+樹存儲結構:每個之前存一個鍵的數據節點,現在存儲多個鍵(聯合索引中的鍵),然後根據聯合索引的順序進行依次鍵排序,最後葉子節點存儲的仍是主鍵值。


3.左連接

會取所有左表數據,加上右表數據,其中右邊要是在一個 on 條件的連接字段上有多條記錄,就生成多條(左邊重複,右表不重複)。
如果不建立索引會導致左連接是雙重for循環,及其消耗性能

5.5之後版本 默認有一個緩存塊嵌套循環Block Nested-Loop,這個會緩存多條左表記錄,減少IO次數。

4.innodb特性

插入緩存:針對非聚簇索引(非主鍵索引)。
多個參數:
innodb_change_buffer_max_size 參數設置 Insert Buffer 的最大內存使用量      
InnoDB_flush_log_at_trx_commit  設置 InnoDB 在事務提交後的日誌寫入頻率 因爲持久化是先從內存寫到binlog 再同步到磁盤的。
0:1s鍾寫入到日誌文件並刷新到磁盤。
1:每次事務提交都被寫入到日誌文件並刷新到磁盤(默認)
2:每次事務提交都被寫入到日誌文件但不刷新到磁盤
sync_binlog:MySQL server 在 binary log 每寫入 sync_binlog 次後,刷寫到磁盤。

二次寫
skip_innodb_doublewrite  默認是開啓的。
如果數據庫發生宕機時,可以通過重做日誌對該頁進行恢復,但是如果該頁本身已經損壞了,進行重做恢復是沒有意義的。因此引入了"二次寫"方案,提高數據頁的穩定性。

doublewrite 的整個流程如下:

對緩存池的髒頁進行刷新時,不直接寫入磁盤,而是通過 memcpy 函數將髒頁複製到內存中的 doublewrite buffer。
將內存中的 doublewrite buffer 寫入共享表空間的物理磁盤上(備份)。
將 doublewrite buffer 中的數據真正的刷新到表磁盤中。
如果寫 doublewrite buffer 失敗,那麼這些數據不會寫到磁盤,innodb 會載入磁盤原始數據和 redo 日誌比較,並重新刷到 doublewrite buffer。
如果寫 doublewrite buffer 成功,但是刷新到磁盤失敗,那麼 innodb 就不會通過redo日誌來恢復了,而是直接刷新 double write buffer 中的數據到磁盤。
skip_innodb_double_written 參數可以用來禁止 doublewrite(二次寫) 功能。

自適應哈希索引
Innodb存儲引擎會監控對錶上二級索引的查找,如果發現某二級索引被頻繁訪問,二級索引成爲熱數據,建立哈希索引可以帶來速度的提升
innodb_adaptive_hash_index | ON 

5.b&b+樹


多路平衡查找樹。
只能逐一加載每一個磁盤頁。
對於樹來說,IO次數就是樹的高度,而“矮胖”就是b樹的特徵之一,它的每個節點最多包含m個孩子,m稱爲b樹的階,m的大小取決於磁盤頁的大小。
b樹,數據節點存數據, b+樹,只有葉子節點存數據,其餘數據節點存的都是鍵值。

6.exists 和 in 


in 走索引,  exists 走 BNL 緩存塊嵌套循環Block Nested-Loop  5.5版本之後的mysql
not in 和not exists:如果查詢語句使用了not in,那麼內外表都進行全表掃描,沒有用到索引;而not extsts的子查詢依然能用到表上的索引。所以無論那個表大,用not exists都比not in要快。

7. innodb的鎖  https://segmentfault.com/a/1190000014133576

innodb的所有行鎖算法都是基於索引的。沒有索引的where就全表加鎖。

記錄鎖  鎖行
gap間隙鎖  鎖區域
next-key鎖  鎖區域+行

排他鎖和共享鎖
給行加完排它鎖前後都不能有沒釋放的排它鎖或者共享鎖,否則加鎖失敗,例如 悲觀鎖 select for update 就給行/表加排它鎖了。

加共享鎖 當前讀  select where ? lock in share mode;  這樣別的事務在當前事務沒提交前,不能加排他鎖/更新。這樣讀的話就是最新數據了。

還有一種方式是 快照讀  就是不加共享鎖,那麼其他事務可以加排它鎖,讀的只是一個快照了。
InnoDB默認的RR事務隔離級別下,不顯式加『lock in share mode』與『for update』的『select』操作都屬於快照讀,保證事務執行過程中只有第一次讀之前提交的修改和自己的修改可見,其他的均不可見;

MVCC 相當於一個行級鎖的變種,很多情況下避免了加鎖操作。
保存着兩個額外的系統版本號,使大多數讀操作都可以不用加鎖。這樣設計使得讀操作簡單,性能強,並且保證只會讀取到符合標準的行。不足之處是沒行記錄都需要額外的存儲空間,需要做更多的檢查工作,以及一些額外的維護工作。
MVCC目的是讓讀寫不衝突。記錄版本號,版本號每創建一個事務就會++。mvcc具體作用就是在寫事務沒有提交的情況下,我們也可以進行讀


8.樂觀鎖與悲觀鎖

樂觀鎖的實現大致是  數據庫加一個版本號version字段,然後做更新操作的時候先查一下
select version from task where id = xxx;
update task set value = newValue,version =  versionValue + 1   where version = versionValue;

悲觀鎖 (更新/插入多的環境)
begin ;
select res_id from tab where id = 1 for update
update tab set status = 1 where res_id = <res_id>
commit;
FOR UPDATE 僅適用於InnoDB,且必須在事務區塊(start sta/COMMIT)中才能生效。 只有明確select for update 的語句中明確id纔是行鎖,否則表鎖。

https://blog.csdn.net/She_lock/article/details/82022431


9.mysql一次SQL查詢的具體過程

客戶端創建sql --- 查詢緩存(一般關掉) --- SQL解析、預處理 查詢優化器 --- 存儲引擎API執行查詢


 

 

參照:

https://blog.csdn.net/ThinkWon/article/details/104778621           一坨面試題

https://blog.csdn.net/alexdamiao/article/details/51934917           聚簇索引&&覆蓋索引

https://blog.csdn.net/universsky2015/article/details/102712058   聚簇索引

https://segmentfault.com/a/1190000014133576                            innodb鎖

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章