MySQL 面試總結(一)

MySQL 基礎模塊的面試題總結

說一下 MySQL 執行一條查詢語句的內部執行過程?

  • 客戶端先經過鏈接器鏈接到 MySQL 服務器。
  • 鏈接器權限驗證經過以後,先查詢是否有查詢緩存,若是有緩存(以前執行過此語句)則直接返回緩存數據,若是沒有緩存則進入分析器。
  • 分析器會對查詢語句進行語法分析和詞法分析,判斷 SQL 語法是否正確,若是查詢語法錯誤會直接返回給客戶端錯誤信息,若是語法正確則進入優化器。
  • 優化器是對查詢語句進行優化處理,例如一個表裏面有多個索引,優化器會判別哪一個索引性能更好。
  • 優化器執行完就進入執行器,執行器就開始執行語句進行查詢比對了,直到查詢到知足條件的全部數據,而後進行返回。

MySQL 提示「不存在此列」是執行到哪一個節點報出的?

此錯誤是執行到分析器階段報出的,由於 MySQL 會在分析器階段檢查 SQL 語句的正確性。面試

MySQL 查詢緩存的功能有何優缺點?

MySQL 查詢緩存功能是在鏈接器以後發生的,它的優勢是效率高,若是已經有緩存則會直接返回結果。 查詢緩存的缺點是失效太頻繁致使緩存命中率比較低,任何更新表操做都會清空查詢緩存,所以致使查詢緩存很是容易失效。正則表達式

如何關閉 MySQL 的查詢緩存功能?

MySQL 查詢緩存默認是開啓的,配置 querycachetype 參數爲 DEMAND(按需使用)關閉查詢緩存,MySQL 8.0 以後直接刪除了查詢緩存的功能。redis

MySQL 的經常使用引擎都有哪些?

MySQL 的經常使用引擎有 InnoDB、MyISAM、Memory 等,從 MySQL 5.5.5 版本開始 InnoDB 就成爲了默認的存儲引擎。sql

MySQL 能夠針對表級別設置數據庫引擎嗎?怎麼設置?

能夠針對不一樣的表設置不一樣的引擎。在 create table 語句中使用 engine=引擎名(好比Memory)來設置此表的存儲引擎。完整代碼以下:數據庫

create table student( id int primary key auto_increment, username varchar(120), age int ) ENGINE=Memory

經常使用的存儲引擎 InnoDB 和 MyISAM 有什麼區別?

InnoDB 和 MyISAM 最大的區別是 InnoDB 支持事務,而 MyISAM 不支持事務,它們主要區別以下:緩存

  • InnoDB 支持崩潰後安全恢復,MyISAM 不支持崩潰後安全恢復;
  • InnoDB 支持行級鎖,MyISAM 不支持行級鎖,只支持到表鎖;
  • InnoDB 支持外鍵,MyISAM 不支持外鍵;
  • MyISAM 性能比 InnoDB 高;
  • MyISAM 支持 FULLTEXT 類型的全文索引,InnoDB 不支持 FULLTEXT 類型的全文索引,可是 InnoDB 可使用 sphinx 插件支持全文索引,而且效果更好;
  • InnoDB 主鍵查詢性能高於 MyISAM。

InnoDB 有哪些特性?

1)插入緩衝(insert buffer):對於非彙集索引的插入和更新,不是每一次直接插入索引頁中,而是首先判斷插入的非彙集索引頁是否在緩衝池中,若是在,則直接插入,不然,先放入一個插入緩衝區中。好似欺騙數據庫這個非彙集的索引已經插入到葉子節點了,而後再以必定的頻率執行插入緩衝和非彙集索引頁子節點的合併操做,這時一般能將多個插入合併到一個操做中,這就大大提升了對非彙集索引執行插入和修改操做的性能。安全

2)兩次寫(double write):兩次寫給 InnoDB 帶來的是可靠性,主要用來解決部分寫失敗(partial page write)。doublewrite 有兩部分組成,一部分是內存中的 doublewrite buffer ,大小爲 2M,另一部分就是物理磁盤上的共享表空間中連續的 128 個頁,即兩個區,大小一樣爲 2M。當緩衝池的做業刷新時,並不直接寫硬盤,而是經過 memcpy 函數將髒頁先拷貝到內存中的 doublewrite buffer,以後經過 doublewrite buffer 再分兩次寫,每次寫入 1M 到共享表空間的物理磁盤上,而後立刻調用 fsync 函數,同步磁盤。以下圖所示服務器

avatar

3)自適應哈希索引(adaptive hash index):因爲 InnoDB 不支持 hash 索引,但在某些狀況下 hash 索引的效率很高,因而出現了 adaptive hash index 功能, InnoDB 存儲引擎會監控對錶上索引的查找,若是觀察到創建 hash 索引能夠提升性能的時候,則自動創建 hash 索引。併發

一張自增表中有三條數據,刪除了兩條數據以後重啓數據庫,再新增一條數據,此時這條數據的 ID 是幾?

若是這張表的引擎是 MyISAM,那麼 ID=4,若是是 InnoDB 那麼 ID=2(MySQL 8 以前的版本)。函數

MySQL 中什麼狀況會致使自增主鍵不能連續?

如下狀況會致使 MySQL 自增主鍵不能連續:

  • 惟一主鍵衝突會致使自增主鍵不連續;
  • 事務回滾也會致使自增主鍵不連續。

InnoDB 中自增主鍵能不能被持久化?

自增主鍵能不能被持久化,說的是 MySQL 重啓以後 InnoDB 能不能恢復重啓以前的自增列,InnoDB 在 8.0 以前是沒有持久化能力的,但 MySQL 8.0 以後就把自增主鍵保存到 redo log(一種日誌類型,下文會詳細講)中,當 MySQL 重啓以後就會從 redo log 日誌中恢復。

什麼是獨立表空間和共享表空間?它們的區別是什麼?

共享表空間:指的是數據庫的全部的表數據,索引文件所有放在一個文件中,默認這個共享表空間的文件路徑在 data 目錄下。 獨立表空間:每個表都將會生成以獨立的文件方式來進行存儲。 共享表空間和獨立表空間最大的區別是若是把表放再共享表空間,即便表刪除了空間也不會刪除,因此表依然很大,而獨立表空間若是刪除表就會清除空間。

如何設置獨立表空間?

獨立表空間是由參數 innodbfileper_table 控制的,把它設置成 ON 就是獨立表空間了,從 MySQL 5.6.6 版本以後,這個值就默認是 ON 了。

如何進行表空間收縮?

使用重建表的方式能夠收縮表空間,重建表有如下三種方式:

  • alter table t engine=InnoDB
  • optmize table t
  • truntace table t

說一下重建表的執行流程?

  • 創建一個臨時文件,掃描表 t 主鍵的全部數據頁;
  • 用數據頁中表 t 的記錄生成 B+ 樹,存儲到臨時文件中;
  • 生成臨時文件的過程當中,將全部對 t 的操做記錄在一個日誌文件(row log)中;
  • 臨時文件生成後,將日誌文件中的操做應用到臨時文件,獲得一個邏輯數據上與表 t相同的數據文件;
  • 用臨時文件替換表 t 的數據文件。

表的結構信息存在哪裏?

表結構定義佔有的存儲空間比較小,在 MySQL 8 以前,表結構的定義信息存在以 .frm 爲後綴的文件裏,在 MySQL 8 以後,則容許把表結構的定義信息存在系統數據表之中。

什麼是覆蓋索引?

覆蓋索引是指,索引上的信息足夠知足查詢請求,不須要再回到主鍵上去取數據。

若是把一個 InnoDB 表的主鍵刪掉,是否是就沒有主鍵,就沒辦法進行回表查詢了?

能夠回表查詢,若是把主鍵刪掉了,那麼 InnoDB 會本身生成一個長度爲 6 字節的 rowid 做爲主鍵。

執行一個 update 語句之後,我再去執行 hexdump 命令直接查看 ibd 文件內容,爲何沒有看到數據有改變呢?

多是由於 update 語句執行完成後,InnoDB 只保證寫完了 redo log、內存,可能還沒來得及將數據寫到磁盤。

內存表和臨時表有什麼區別?

  • 內存表,指的是使用 Memory 引擎的表,建表語法是 create table … engine=memory。這種表的數據都保存在內存裏,系統重啓的時候會被清空,可是表結構還在。除了這兩個特性看上去比較「奇怪」外,從其餘的特徵上看,它就是一個正常的表。
  • 而臨時表,可使用各類引擎類型 。若是是使用 InnoDB 引擎或者 MyISAM 引擎的臨時表,寫數據的時候是寫到磁盤上的。

併發事務會帶來哪些問題?

  • 髒讀
  • 修改丟失
  • 不可重複讀
  • 幻讀

什麼是髒讀和幻讀?

髒讀是一個事務在處理過程當中讀取了另一個事務未提交的數據;幻讀是指同一個事務內屢次查詢返回的結果集不同(好比增長了或者減小了行記錄)。

爲何會出現幻讀?幻讀會帶來什麼問題?

由於行鎖只能鎖定存在的行,針對新插入的操做沒有限定,因此就有可能產生幻讀。 幻讀帶來的問題以下:

  • 對行鎖語義的破壞;
  • 破壞了數據一致性。

如何避免幻讀?

使用間隙鎖的方式來避免出現幻讀。間隙鎖,是專門用於解決幻讀這種問題的鎖,它鎖的了行與行之間的間隙,可以阻塞新插入的操做 間隙鎖的引入也帶來了一些新的問題,好比:下降併發度,可能致使死鎖。

如何查看 MySQL 的空閒鏈接?

在 MySQL 的命令行中使用 show processlist; 查看全部鏈接,其中 Command 列顯示爲 Sleep 的表示空閒鏈接,以下圖所示:

avatar

MySQL 中的字符串類型都有哪些?

MySQL 的字符串類型和取值以下:

類型 取值範圍
CHAR(N) 0~255
VARCHAR(N) 0~65536
TINYBLOB 0~255
BLOB 0~65535
MEDUIMBLOB 0~167772150
LONGBLOB 0~4294967295
TINYTEXT 0~255
TEXT 0~65535
MEDIUMTEXT 0~167772150
LONGTEXT 0~4294967295
VARBINARY(N) 0~N個字節的變長字節字符集
BINARY(N) 0~N個字節的定長字節字符集

VARCHAR 和 CHAR 的區別是什麼?分別適用的場景有哪些?

VARCHAR 和 CHAR 最大區別就是,VARCHAR 的長度是可變的,而 CHAR 是固定長度,CHAR 的取值範圍爲1-255,所以 VARCHAR 可能會形成存儲碎片。因爲它們的特性決定了 CHAR 比較適合長度較短的字段和固定長度的字段,如身份證號、手機號等,反之則適合使用 VARCHAR。

MySQL 存儲金額應該使用哪一種數據類型?爲何?

MySQL 存儲金額應該使用 decimal ,由於若是存儲其餘數據類型,好比float 有致使小數點後數據丟失的風險。

limit 3,2 的含義是什麼?

去除前三條數據以後查詢兩條信息。

now() 和 current_date() 有什麼區別?

now() 返回當前時間包含日期和時分秒,current_date() 只返回當前時間,以下圖所示:

avatar

如何去重計算總條數?

使用 distinct 去重,使用 count 統計總條數,具體實現腳本以下:

select count(distinct f) from t

lastinsertid() 函數功能是什麼?有什麼特色?

lastinsertid() 用於查詢最後一次自增表的編號,它的特色是查詢時不須要不須要指定表名,使用 select last_insert_id() 便可查詢,由於不須要指定表名因此它始終以最後一條自增編號爲主,能夠被其它表的自增編號覆蓋。好比 A 表的最大編號是 10,lastinsertid() 查詢出來的值爲 10,這時 B 表插入了一條數據,它的最大編號爲 3,這個時候使用 lastinsertid() 查詢的值就是 3。

刪除表的數據有幾種方式?它們有什麼區別?

刪除數據有兩種方式:delete 和 truncate,它們的區別以下:

  • delete 能夠添加 where 條件刪除部分數據,truncate 不能添加 where 條件只能刪除整張表;
  • delete 的刪除信息會在 MySQL 的日誌中記錄,而 truncate 的刪除信息不被記錄在 MySQL 的日誌中,所以 detele 的信息能夠被找回而 truncate 的信息沒法被找回;
  • truncate 由於不記錄日誌因此執行效率比 delete 快。

delete 和 truncate 的使用腳本以下:

delete from t where username='redis'; truncate table t;

MySQL 中支持幾種模糊查詢?它們有什麼區別?

MySQL 中支持兩種模糊查詢:regexp 和 like,like 是對任意多字符匹配或任意單字符進行模糊匹配,而 regexp 則支持正則表達式的匹配方式,提供比 like 更多的匹配方式。 regexp 和 like 的使用示例以下: select * from person where uname like '%SQL%';> select from person where uname regexp '.SQL*.';

MySQL 支持枚舉嗎?如何實現?它的用途是什麼?

MySQL 支持枚舉,它的實現方式以下:

create table t( sex enum('boy','grid') default 'unknown' );

枚舉的做用是預約義結果值,當插入數據不在枚舉值範圍內,則插入失敗,提示錯誤 Data truncated for column 'xxx' at row n 。

count(column) 和 count(*) 有什麼區別?

count(column) 和 count() 最大區別是統計結果可能不一致,count(column) 統計不會統計列值爲 null 的數據,而 count() 則會統計全部信息,因此最終的統計結果可能會不一樣。

如下關於 count 說法正確的是?

A. count 的查詢性能在各類存儲引擎下的性能都是同樣的。 B. count 在 MyISAM 比 InnoDB 的性能要低。 C. count 在 InnoDB 中是一行一行讀取,而後累計計數的。 D. count 在 InnoDB 中存儲了總條數,查詢的時候直接取出。

答:C

爲何 InnoDB 不把總條數記錄下來,查詢的時候直接返回呢?

由於 InnoDB 使用了事務實現,而事務的設計使用了多版本併發控制,即便是在同一時間進行查詢,獲得的結果也可能不相同,因此 InnoDB 不能把結果直接保存下來,由於這樣是不許確的。

可否使用 show table status 中的錶行數做爲表的總行數直接使用?爲何?

不能,由於 show table status 是經過採樣統計估算出來的,官方文檔說偏差可能在 40% 左右,因此 show table status 中的錶行數不能直接使用。

如下哪一個 SQL 的查詢性能最高?

A. select count(*) from t where time>1000 and time<4500 B. show table status where name='t' C. select count(id) from t where time>1000 and time<4500 D. select count(name) from t where time>1000 and time<4500

答:B 題目解析:由於 show table status 的錶行數是估算出來,而其餘的查詢由於添加了 where 條件,即便是 MyISAM 引擎也不能直接使用已經存儲的總條數,因此 show table status 的查詢性能最高。

InnoDB 和 MyISAM 執行 select count(*) from t,哪一個效率更高?爲何?

MyISAM 效率最高,由於 MyISAM 內部維護了一個計數器,直接返回總條數,而 InnoDB 要逐行統計。

在 MySQL 中有對 count(*) 作優化嗎?作了哪些優化?

MySQL 有對 count() 進行優化,以 InnoDB 爲例,在 InnoDB 中主鍵索引數的葉子節點是主鍵值,而普通索引的葉子節點則是主鍵值,因此普通索引數比主鍵索引數要小不少,而對於 count 查詢來講,每一個索引樹的查詢結果都是同樣的,因此 MySQL 會選擇最小的那顆樹來遍歷,以此來優化 count() 的查詢。

在 InnoDB 引擎中 count(*)、count(1)、count(主鍵)、count(字段) 哪一個性能最高?

count(字段)<count(主鍵 id)<count(1)≈count(*) 題目解析:

  • 對於 count(主鍵 id) 來講,InnoDB 引擎會遍歷整張表,把每一行的 id 值都取出來,返回給 server 層。server 層拿到 id 後,判斷是不可能爲空的,就按行累加。
  • 對於 count(1) 來講,InnoDB 引擎遍歷整張表,但不取值。server 層對於返回的每一行,放一個數字「1」進去,判斷是不可能爲空的,按行累加。
  • 對於 count(字段) 來講,若是這個「字段」是定義爲 not null 的話,一行行地從記錄裏面讀出這個字段,判斷不能爲 null,按行累加;若是這個「字段」定義容許爲 null,那麼執行的時候,判斷到有多是 null,還要把值取出來再判斷一下,不是 null 才累加。
  • 對於 count() 來講,並不會把所有字段取出來,而是專門作了優化,不取值。count() 確定不是 null,按行累加。

因此最後得出的結果是:count(字段)<count(主鍵 id)<count(1)≈count(*)。

MySQL 中內鏈接、左鏈接、右鏈接有什麼區別?

  • 內連(inner join)— 把匹配的關聯數據顯示出來;
  • 左鏈接(left join)— 把左邊的表所有顯示出來,右邊的表顯示出符合條件的數據;
  • 右鏈接(right join)— 把右邊的表所有顯示出來,左邊的表顯示出符合條件的數據;

什麼是視圖?如何建立視圖?

視圖是一種虛擬的表,具備和物理表相同的功能,能夠對視圖進行增、改、查操做。視圖一般是一個表或者多個表的行或列的子集。 視圖建立腳本以下:

create view vname as select column_names from table_name where condition

視圖有哪些優勢?

  • 獲取數據更容易,相對於多表查詢來講;
  • 視圖可以對機密數據提供安全保護;
  • 視圖的修改不會影響基本表,提供了獨立的操做單元,比較輕量。

MySQL 中「視圖」的概念有幾個?分別表明什麼含義?

MySQL 中的「視圖」概念有兩個,它們分別是:

  • MySQL 中的普通視圖也是咱們最經常使用的 view,建立語法是 create view ...,它的查詢和普通表同樣;
  • InnoDB 實現 MVCC(Multi-Version Concurrency Control)多版本併發控制時用到的一致性讀視圖,它沒有物理結構,做用是事務執行期間定於能夠看到的數據。

使用 delete 誤刪數據怎麼找回?

能夠用 Flashback 工具經過閃回把數據恢復回來。

Flashback 恢復數據的原理是什麼?

Flashback 恢復數據的原理是是修改 binlog 的內容,拿回原庫重放,從而實現數據找回。

相關文章
相關標籤/搜索