mysql面試題總結

  1. Mysql中的myisam與innodb的區別?
  2. InnoDB存儲引擎的四大特性?
  3. 什麼是事務?
  4. 數據庫事務的四大特性?
  5. 不考慮事務的隔離性,會發生幾種問題?
  6. MySQL數據庫提供的四種隔離級別?
  7. 有多少種日誌?
  8. 事務是如何經過日誌來實現的?
  9. 數據庫的樂觀鎖和悲觀鎖是什麼?
  10. 什麼是存儲過程?有哪些優缺點?
  11. 存儲過程與觸發器的區別?
  12. 索引是什麼?有什麼做用以及優缺點?
  13. 說一說MySQL數據庫幾個基本的索引類型?
  14. 使用索引查詢必定能提升查詢的性能嗎?爲何?
  15. 爲數據表創建索引的原則有哪些?
  16. 什麼狀況下應不建或少建索引?
  17. 什麼是mysql聯合索引?
  18. 說一說 B+樹索引、哈希索引?
  19. B樹和B+樹的區別?
  20. 爲何說B+比B樹更適合實際應用中操做系統的文件索引和數據庫索引?
  21. 彙集索引和非彙集索引區別?
  22. 說一說drop、deletetruncate的區別?
  23. drop、deletetruncate分別在什麼場景之下使用?
  24. 超鍵、候選鍵、主鍵、外鍵分別是什麼?
  25. mysql爲何用自增列做爲主鍵?
  26. MySQL中的varchar和char的區別以及varchar(50)中的50表明的涵義?
  27. 什麼是視圖?視圖的使用場景有哪些?
  28. 數據庫三大範式?
  29. sql優化
  30. 非關係型數據庫和關係型數據庫區別,優點比較?
  31. 什麼是 內鏈接、外鏈接、交叉鏈接、笛卡爾積等?
  32. SQL語言分類
  33. like %和-的區別
  34. count(*)、count(1)、count(column)的區別
  35. 大家數據庫是否支持emoji表情,若是不支持,如何操做?
  36. 你是如何監控大家的數據庫的?大家的慢日誌都是怎麼查詢的?

 

 

一、Mysql中的MyISAM與InnoDB的區別?

(1)InnoDB存儲引擎支持事務,而MyISAM不支持事務;html

(2)InnoDB支持行級鎖,而MyISAM只支持表級鎖;前端

( InnoDB行鎖是經過給索引加鎖實現的,即只有經過索引條件檢索數據,InnoDB才使用行級鎖,不然將使用表級鎖!行級鎖在每次獲取鎖和釋放鎖的操做須要比表級鎖消耗更多的資源。mysql

MySQL表級鎖有兩種模式:表共享讀鎖和表獨佔寫鎖。就是說對MyIASM表進行讀操做時,它不會阻塞其餘用戶對同一表的讀請求,但會阻塞對同一表的寫操做;而對MyISAM表的寫操做,會阻塞其餘用戶對同一表的讀和寫操做。)程序員

(3)InnoDB支持外鍵,而MyISAM不支持外鍵;面試

(4)InnoDB不保存數據庫表中表的具體行數,而MyISAM會保存;算法

( 也就是說,執行 select count(*) from table 時,InnoDB要掃描一遍整個表來計算有多少行,而MyISAM只須要讀出保存好的行數便可(內部維護了一個計算器,能夠直接調取)。【注】:當count(*)語句包含where條件時,兩種表的操做是同樣的。也就是上述介紹到的InnoDB使用表鎖的一種狀況。)sql

 

  對於select ,update ,insert ,delete 操做:mongodb

  若是執行大量的SELECT,MyISAM是更好的選擇(由於MyISAM不支持事務,使得MySQL能夠提供高速存儲和檢索,以及全文搜索能力)數據庫

  若是執行大量的INSERT或UPDATE,出於性能方面的考慮,應該使用InnoDB表(由於InnoDB支持事務,在一些列增刪改中只要哪一個出錯還能夠回滾還原,而MyISAM就不能夠了)編程

二、InnoDB存儲引擎的四大特性?

插入緩衝、二次寫、自適應哈希索引、預讀

(1)插入緩衝

  通常狀況下,主鍵是行惟一的標識符。一般應用程序中行記錄的插入順序是按照主鍵遞增的順序進行插入的。所以,插入彙集索引通常是順序的,不須要磁盤的隨機讀取。由於,對於此類狀況下的插入,速度仍是很是快的。

  若是索引是非彙集的且不惟一,在進行插入操做時,數據的存放對於非彙集索引葉子節點的插入不是順序的,這時須要離散地訪問非彙集索引頁,因爲隨機讀取的存在而致使了插入操做性能降低。(這是由於B+樹的特性決定了非彙集索引插入的離散性。)

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

    插入緩衝的使用要知足兩個條件

  • 索引是輔助索引
  • 索引不是惟一的
    • (輔助索引不能是惟一的,由於在把它插入到插入緩衝時,咱們並不去查找索引頁的狀況。若是去查找確定又會出現離散讀的狀況,插入緩衝就失去了意義。)

    存在的問題:

      在寫密集的狀況下,插入緩衝會過多的佔用緩衝池內存,默認狀況下最大能夠佔用1/2的緩衝池內存。

(2)二次寫

當數據庫宕機時,可能發生數據庫正在寫一個頁面,而這個頁只寫了一部分的狀況,咱們稱之爲部分寫失效。當寫入失效發生時,先經過頁的副原本還原該頁,再重作日誌,這就是兩次寫

doublewrite步驟:

  1. 當一系列機制(main函數觸發、checkpoint等)觸發數據緩衝池中的髒頁進行刷新時,並不直接寫磁盤,而是會經過memcpy函數將髒頁拷貝到內存中的doublewrite buffer,以後經過doublewrite buffer再分兩次、每次1MB順序寫入共享表空間的物理磁盤上。
  2. 而後立刻調用fsync函數,同步髒頁進磁盤。在這個過程當中,doublewrite頁的存儲是連續的,所以寫入磁盤爲順序寫,性能很高在完成doublewrite頁的寫入後,再將doublewrite buffer中的頁寫入到各個表空間文件中,此時的寫入則是離散的。

  若是操做系統在將頁寫入磁盤的過程當中崩潰了,在恢復過程當中,InnoDB存儲引擎能夠從共享表空間中的doublewrite中找到該頁的一個副本,將其拷貝到表空間文件,再應用重作日誌,就完成了恢復過程。由於有副本因此也不擔憂表空間中數據頁是否損壞。

(3)自適應哈希索引

  InnoDB存儲引擎會監控對錶上索引的查找,若是觀察到創建哈希索引能夠帶來速度的提高,則創建哈希索引,因此稱爲自適應的。自適應哈希索引經過緩衝池的B+樹構造而來,所以創建的速度很快,並且不須要將整個表都建哈希索引,InnoDB存儲引擎會自動根據訪問的頻率和模式來爲某些頁創建哈希索引。

  (4)預讀

  InnoDB 提供了兩種預讀的方式,一種是 Linear read ahead,由參數innodb_read_ahead_threshold控制,當你連續讀取一個 extent 的 threshold 個 page 的時候,會觸發下一個 extent 64個page的預讀。另一種是Random read-ahead,由參數innodb_random_read_ahead控制,當你連續讀取設定的數量的page後,會觸發讀取這個extent的剩餘page。
  InnoDB 的預讀功能是使用後臺線程異步完成的。

3. InnoDB如何保證事務的四大特性?

  MySQL的存儲引擎InnoDB使用重作日誌(redo log)保證一致性與持久性回滾日誌(undo log)保證原子性使用各類鎖來保證隔離性

4. MySQL中的重作日誌(redo log),回滾日誌(undo log),以及二進制日誌(binlog)?

MySQL中有六種日誌文件,分別是:

重作日誌(redo log)
回滾日誌(undo log)
二進制日誌(binlog)
錯誤日誌(errorlog)
慢查詢日誌(slow query log)
通常查詢日誌(general log)
中繼日誌(relay log)

其中重作日誌和回滾日誌與事務操做息息相關,二進制日誌也與事務操做有必定的關係。

事務是如何經過日誌來實現的?

  Undo 記錄某 數據 被修改 的值,能夠用來在事務失敗時進行 rollback;
  Redo 記錄某 數據塊 被修改 的值,能夠用來恢復未寫入 data file 的已成功事務更新的數據。
即,

  • Redo Log 保證事務的持久性
  • Undo Log 保證事務的原子性(在 InnoDB 引擎中,還用 Undo Log 來實現 MVCC)
  好比某一時刻數據庫 DOWN 機了,有兩個事務,一個事務已經提交,另外一個事務正在處理。數據庫重啓的時候就要根據日誌進行前滾及回滾,把已提交事務的更改寫到數據文件,未提交事務的更改恢復到事務開始前的狀態。即 經過 redo log 將全部已經在存儲引擎內部提交的事務應用 redo log 恢復全部已經 prepared 可是沒有 commit 的事務將會應用 undo log 作回滾

重作日誌(redo log):

  redo log在事務沒有提交前,會記錄每個修改操做變動後的數據。主要是防止在發生故障的時間點,尚有髒頁未寫入磁盤。在重啓mysql服務的時候,根據redo log進行重作,從而達到事務的持久性這一特性。(做用

  在事務提交前,只要將 Redo Log 持久化便可,不須要將數據持久化。當系統崩潰時,系統能夠根據redo Log的內容,將全部數據恢復到最新的狀態。(持久化:先將重作日誌寫入緩存,再刷新(fsync)到磁盤

  重作日誌是物理日誌,記錄的是對於每一個頁的修改。事務開始後Innodb存儲引擎先將重作日誌寫入緩存(innodb_log_buffer)中。而後會經過如下三種方式將innodb日誌緩衝區的日誌刷新到磁盤。

  1. Master Thread每秒一次執行刷新Innodb_log_buffer到重作日誌文件。
  2. 每一個事務提交時會將重作日誌刷新到重作日誌文件。
  3. 當重作日誌緩存可用空間少於一半時,重作日誌緩存被刷新到重作日誌文件

  當事務提交時,必須先將該事務的全部日誌寫入到重作日誌文件進行持久化

一、內容:

      物理格式的日誌,記錄的是物理數據頁面的修改的信息,其redo log是順序寫入redo log file的物理文件中去的。

二、redo log是何時寫盤的?

  是在事物開始以後逐步寫盤的。

  事務開始以後就產生redo log,redo log的寫盤並非隨着事務的提交才寫入的,而是在事務的執行過程當中,便開始寫入redo log文件中。(先將重作日誌寫入緩存,將日誌緩衝區的日誌刷新到磁盤,寫入磁盤的方式有上面3種)

【注】即便某個事務尚未提交,Innodb存儲引擎仍然每秒會將重作日誌緩存刷新到重作日誌文件。這一點是必需要知道的,由於這能夠很好地解釋再大的事務的提交(commit)的時間也是很短暫的。

三、何時釋放:

      當對應事務的髒頁寫入到磁盤以後,redo log的使命也就完成了,重作日誌佔用的空間就能夠重用(被覆蓋)。

回滾日誌(undo log):

  保存了事務發生以前的數據的一個版本,能夠用於回滾,同時能夠提供多版本併發控制下的讀(MVCC),也即非鎖定讀。(做用

  事務發生異常須要回滾,這時就須要回滾日誌。回滾日誌不一樣於重作日誌,它是邏輯日誌對數據庫的修改都邏輯的取消了。當事務回滾時,它實際上作的是與先前相反的工做。對於每一個INSERT,InnoDB存儲引擎都會完成一個DELETE;對於每一個UPDATE,InnoDB存儲引擎都會執行一個相反的UPDATE。

  未提交的事務和回滾了的事務也會產生重作日誌。InnoDB存儲引擎會重作全部事務包括未提交的事務和回滾了的事務,而後經過回滾日誌回滾那些未提交的事務。使用這種策略須要回滾日誌在重作日誌以前寫入磁盤,使得持久化變得複雜起來。爲了下降複雜度,InnoDB存儲引擎將回滾日誌做數據,記錄回滾日誌的操做也會記錄到重作日誌中。這樣回滾日誌就能夠像數據同樣緩存起來,而不用在重寫日誌以前寫入磁盤了。

一、內容

      邏輯格式的日誌在執行undo的時候,僅僅是將數據從邏輯上恢復至事務以前的狀態,而不是從物理頁面上操做實現的,這一點是不一樣於redo log的。

二、何時產生?

      事務開始以前,將當前是的版本生成undo log,undo 也會產生 redo 來保證undo log的可靠性

三、何時釋放?

      當事務提交以後,undo log並不能立馬被刪除,而是放入待清理的鏈表,由purge線程判斷是否由其餘事務在使用undo段中表的上一個事務以前的版本信息,決定是否能夠清理undo log的日誌空間

 

二進制日誌(bin log):

一、做用:

      用於複製,在主從複製中,從庫利用主庫上的binlog進行重播,實現主從同步。 用於數據庫的基於時間點的還原。

二、內容:

邏輯格式的日誌,能夠簡單認爲就是執行過的事務中的sql語句。

      但又不徹底是sql語句這麼簡單,而是包括了執行的sql語句(增刪改)反向的信息,也就意味着delete對應着delete自己和其反向的insert;update對應着update執行先後的版本的信息;insert對應着delete和insert自己的信息。

在使用mysqlbinlog解析binlog以後一些都會真相大白。
所以能夠基於binlog作到相似於oracle的閃回功能,其實都是依賴於binlog中的日誌記錄。

三、何時產生:

      事務提交的時候,一次性將事務中的sql語句(一個事物可能對應多個sql語句)按照必定的格式記錄到binlog中。這裏與redo log很明顯的差別就是redo log並不必定是在事務提交的時候刷新到磁盤,redo log是在事務開始以後就開始逐步寫入磁盤。

      所以對於事務的提交,即使是較大的事務,提交(commit)都是很快的,可是在開啓了bin_log的狀況下,對於較大事務的提交,可能會變得比較慢一些。這是由於binlog是在事務提交的時候一次性寫入的形成的,這些能夠經過測試驗證。

四、何時釋放:

binlog的默認是保持時間由參數expire_logs_days配置,也就是說對於非活動的日誌文件,在生成時間超過expire_logs_days配置的天數以後,會被自動刪除。

 

binlog與redolog的區別?

  在MySQL數據庫中還有一種二進制日誌,其用來基於時間點的還原及主從複製。從表面上來看其和重作日誌很是類似,都是記錄了對於數據庫操做的日誌。可是,從本質上來看有着很是大的不一樣。 首先重作日誌是在InnoDB存儲引擎層產生的,而二進制日誌是在MySQL數據庫的上層產生的。其次,兩種日誌記錄的內容形式不一樣。二進制日誌是一種邏輯日誌,其記錄的是對應的SQL語句。而重作日誌是物理日誌,記錄的是每一個頁的修改。此外,兩種日誌記錄寫入磁盤的時間點不一樣,二進制日誌只在事務提交完成後進行一次寫入,重作日誌在事務進行時不斷地寫入。

 
 
 

三、什麼是事務?

  事務就是一個操做序列,這些操做要麼都執行,要麼都不執行,它是一個不可分割的工做單位。事務是數據庫維護數據一致性的單位,在每一個事務結束時,都能保持數據一致性。

四、數據庫事務的四大特性?

  原子性、一致性、隔離性、持久性  (ACID)

  • 原子性:是指整個數據庫事務是不可分割的單位。只有使事務中的全部數據庫操做都成功,纔算整個事務成功。若是事務中任何一個sql語句執行失敗,那麼已經執行的sql語句也必須撤銷,事務狀態退回到執行事務以前的狀態。
  • 一致性:一致性是指事務必須使數據庫從一個一致性狀態變換到另外一個一致性狀態。在事務開始以前和事務結束以後,事務的完整性約束沒有被破壞。
  • 隔離性:一個事務的影響在該事務提交前對其餘事物都不可見。——這經過鎖來實現
  • 持久性:事務一旦提交,其結果就是永久性的。

(隔離性由鎖來實現;原子性、一致性和持久性經過數據庫的redo和undo來完成。)

五、不考慮事務的隔離性,會發生幾種問題?

  經過鎖能夠實現事務隔離性的要求,使得事務能夠併發地工做。由於事務隔離性的要求,鎖會帶來3種問題:丟失更新、髒讀、不可重複讀。

丟失更新:

  指一個事務正在訪問修改數據,與此同時另外一個事務也在訪問修改此數據,兩個事務互相不知道對方的存在。假如在是事務A修改數據前事務B已經修改過1次數據,那麼事務A最終只能查詢到假數據,丟失了更新操做。

解決方案:

悲觀鎖的方式: 加鎖,建議最後一步更新數據的時候加上排它鎖,不要在一開始就加鎖。執行到了最後一步更新,首先作一下加鎖的查詢確認數據有沒有沒改變,若是沒有被改變,則進行數據的更新,不然失敗。 必定要是作加鎖的查詢確認,由於若是你不加鎖的話,有可能你在作確認的時候數據又發生了改變。

樂觀鎖的方式:使用版本控制實現。

髒讀:

一個事務讀取了另外一個事務未提交的數據,那這個讀取就是髒讀。

解決方法 : 把數據庫的事務隔離級別調整到read commited。

不可重複讀:

  不可重複讀是指在一個事務內屢次讀同一數據,在這個事務尚未結束時,另一個事務也訪問並修改該同一數據,那麼在第一個事務的兩次讀數據之間,因爲第二個事務的修改,第一個事務兩次讀到的數據多是不同的。這樣就發生了在一個事務內兩次讀到的數據是不同的,所以稱爲不可重複讀。

  如何避免:InnoDB存儲引擎中,經過使用Next-Key Lock算法來避免不可重複讀的問題。在Next-Key Lock算法下,對於索引的掃描,不只僅是鎖住掃描到的索引,並且還能鎖住這些索引覆蓋的範圍。所以對於這個範圍內的插入都是不容許的。InnoDB存儲引擎的默認事務隔離級別是READ REPEATABLE,採用Next-Key Lock算法,就避免了不可重複讀的現象。

解決辦法:把數據庫的事務隔離級別調整到 REPEATABLE READ , 讀取時候不容許其餘事務修改該數據,無論數據在事務過程當中讀取多少次,數據都是一致的。

幻讀:

  是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的所有數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那麼,之後就會發生操做第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺同樣。

如何避免:Repeatable read及以上級別經過間隙鎖來防止幻讀的出現,即鎖定特定數據的先後間隙讓數據沒法被插入。

六、MySQL數據庫提供的四種隔離級別?

  • read uncommitted(讀未提交)
  • read committed(讀已提交)
  • repeatable read(可重複讀):InnoDB的默認隔離級別
  • serializable(串行)

  

七、有多少種日誌?

  • 錯誤日誌    :記錄出錯信息,也記錄一些警告信息或者正確的信息。
  • 查詢日誌    :記錄全部對數據庫請求的信息,不論這些請求是否獲得了正確的執行。
  • 慢查詢日誌:設置一個閾值,將運行時間超過該值的全部SQL語句都記錄到慢查詢的日誌文件中。
  • 二進制日誌:記錄對數據庫執行更改的全部操做。
  • 中繼日誌
  • 事務日誌

八、事務是如何經過日誌來實現的?

  • InnoDB中,事務日誌經過重作(redo)日誌文件和InnoDB存儲引擎的日誌緩衝來實現。當開始一個事務時,會記錄該事務的一個LSN(日誌序列號),當事務執行時,會往InnoDB的日誌緩衝裏插入事務日誌,當事務提交時,必須將innoDB存儲引擎的日誌緩衝寫入磁盤。也就是在寫數據前,須要先寫日誌。這種方式稱爲預寫日誌方式

 InnoDB經過預寫日誌的方式來保證事務的完整性。這意味着磁盤上存儲的數據頁和內存緩衝池中的數據頁是不一樣步的,對於內存緩衝池中頁的修改,先是寫入重作日誌文件,而後再寫入磁盤,所以是一種異步的方式

  • 事務有時還須要撤銷,這就須要undo。對數據庫進行修改時,數據庫不但會產生redo,並且會產生必定量的undo,若是你執行的事務或語句因爲某種緣由失敗了,或者若是你用一條rollback語句請求回滾,就能夠利用這些undo信息將數據回滾到修改以前的樣子。

九、數據庫的樂觀鎖和悲觀鎖是什麼?

樂觀併發控制(樂觀鎖)和悲觀併發控制(悲觀鎖)是併發控制主要採用的技術手段。

悲觀鎖:假定會發生併發衝突,屏蔽掉一切可能違反數據完整性的操做,在讀取的時候就對數據進行加鎖, 在該用戶讀取數據的期間,其餘任何用戶都不能來修改該數據,可是其餘用戶是能夠讀取該數據的, 只有當本身讀取完畢才釋放鎖。

樂觀鎖:假定不會發生併發衝突,只在提交的時候檢查是否發生併發衝突。

  事務和鎖的存在都是爲了更好地解決併發訪問形成的數據不一致性問題。樂觀鎖和悲觀鎖都是爲了解決併發控制問題,樂觀鎖能夠看作一種在最後提交時檢測衝突的手段,而悲觀鎖是一種避免衝突的手段。

(1)樂觀鎖:假設不會發生併發衝突,只在提交的時候檢查是否發生併發衝突。能夠使用版本號機制CAS算法實現。

  版本號機制:通常在數據表中加一個數據版本號version字段,表示數據被修改的次數,當數據被修改時version值加一。當線程A要更新數據值時,在讀取數據的同時也會讀取version值,在提交更新時,若當前讀取到的version值與第一次讀取到的數據庫version值相等時才更新,不然重試更新操做,直到更新成功。

  例子:

假設數據庫中賬戶信息表中有一個 version 字段,當前值爲 1 ;而當前賬戶餘額字段( balance )爲 100 。

  1. 操做員A此時將其讀出( version=1 ),並從其賬戶餘額中扣除 50(100-50 =50);
  2. 在操做員A操做的過程當中,操做員B也讀入此用戶信息( version=1 ),並從其賬戶餘額中扣除20 (100-20=80 )。
  3. 操做員A完成了修改工做,將數據版本號加一( version=2 ),連同賬戶扣除後餘額( balance=50 ),提交至數據庫更新,此時因爲提交數據版本大於數據庫記錄當前版本,數據被更新,數據庫記錄 version 更新爲 2 ;
  4. 操做員B完成了操做,也將版本號加一( version=2 )試圖向數據庫提交數據( balance=80 ),但此時比對數據庫記錄版本時發現,操做員 B 提交的數據版本號爲 2 ,數據庫記錄當前版本也爲 2 ,不知足 「 當前最後更新的version與操做員第一次的版本號相等 「 的樂觀鎖策略,所以,操做員B的提交被駁回。

  CAS機制:即compare and swap(比較與交換),無鎖編程,在不使用鎖的狀況下實現多線程之間的變量同步,也就是在沒有線程被阻塞的狀況下實現變量的同步,所以也叫非阻塞同步。

  CAS過程是這樣:它包含3個參數:內存值V(要更新變量的值),舊的預期值A,要修改的值B。當且僅當預期值A的值等於內存值V時,纔會將內存值V修改成B,不然不會執行任何操做(V值和A值不一樣,則說明已經有其餘線程作了更新)。通常狀況下是一個自旋操做,即不斷的重試。

  例子:

  1. 假設 t1,t2 線程同時更新同一變量56的值。
  2. 由於t1和t2線程都同時去訪問同一變量56,因此他們會把主內存的值徹底拷貝一份到本身的工做內存空間,因此t1和t2線程的預期值都爲56。
  3. 假設t1在與t2線程競爭中線程t1能去更新變量的值,而其餘線程都失敗。(失敗的線程並不會被掛起,而是被告知此次競爭中失敗,並能夠再次發起嘗試)。t1線程去更新變量值改成57,而後寫到內存中。此時對於t2來講,內存值變爲了57,與預期值56不一致,就操做失敗了(想改的值再也不是原來的值)。

樂觀鎖的優點和劣勢 :
優點:若是數據庫記錄始終處於悲觀鎖加鎖狀態,能夠想見,若是面對幾百上千個併發,那麼要不斷的加鎖減鎖,並且用戶等待的時間會很是的長, 樂觀鎖機制避免了長事務中的數據庫加鎖解鎖開銷,大大提高了大併發量下的系統總體性能表現。因此若是系統的併發很是大的話,悲觀鎖定會帶來很是大的性能問題,因此建議就要選擇樂觀鎖定的方法, 而若是併發量不大,徹底能夠使用悲觀鎖定的方法。樂觀鎖也適合於讀比較多的場景。
劣勢: 樂觀鎖只能在提交數據時才發現業務事務將要失敗,若是系統的衝突很是的多,並且一旦衝突就要由於從新計算提交而形成較大的代價的話,樂觀鎖也會帶來很大的問題。並且樂觀鎖也沒法解決髒讀的問題 。

(2)悲觀鎖:假定會發生併發衝突,在讀取的時候就對數據進行加鎖, 在該用戶讀取數據的期間,其餘任何用戶都不能來修改該數據,可是其餘用戶是能夠讀取該數據的, 只有當本身讀取完畢才釋放鎖。

  在數據庫中能夠使用Repeatable Read的隔離級別(可重複讀)來實現悲觀鎖,它徹底知足悲觀鎖的要求(加鎖)。Java中synchronizedReentrantLock等獨佔鎖就是悲觀鎖思想的實現。

     悲觀鎖的優點和劣勢 :
    優點:  能避免衝突的發生 。
    劣勢 :開銷較大,並且加鎖時間較長,對於併發的訪問性支持很差。

兩種鎖的使用場景:

  若是衝突不多,或者衝突的後果不會很嚴重,那麼一般狀況下應該選擇樂觀鎖,由於它能獲得更好的併發性;

  若是衝突太多或者衝突的結果對於用戶來講痛苦的,那麼就須要使用悲觀策略,它能避免衝突的發生。

  通常樂觀鎖適用於寫比較少的狀況下(多讀場景),即衝突真的不多發生的時候;悲觀鎖適用於多寫的狀況,多寫的狀況通常會常常產生衝突。

 

數據庫中的樂觀鎖,悲觀鎖

面試必備之樂觀鎖與悲觀鎖

9. 共享鎖與排它鎖?

  共享鎖和排它鎖是具體的鎖,是數據庫機制上的鎖。

  • 共享鎖(讀鎖): 在同一個時間段內,多個用戶能夠讀取同一個資源,讀取的過程當中數據不會發生任何變化。讀鎖之間相互不阻塞, 多個用戶能夠同時讀,可是不能容許有人修改。 
  • 排它鎖(寫鎖): 在任什麼時候候只能有一個用戶寫入資源,當進行寫鎖時會阻塞其餘的讀鎖或者寫鎖操做,只能由這一個用戶來寫,其餘用戶既不能讀也不能寫。

 

加鎖會有粒度問題,從粒度上從大到小能夠劃分爲

  • 表鎖:開銷較小,一旦有用戶訪問這個表就會加鎖,其餘用戶就不能對這個表操做了,應用程序的訪問請求遇到鎖等待的可能性比較高。
  • 頁鎖:是MySQL中比較獨特的一種鎖定級別,鎖定顆粒度介於行級鎖定與表級鎖之間,因此獲取鎖定所須要的資源開銷,以及所能提供的併發處理能力也一樣是介於上面兩者之間。另外,頁級鎖定和行級鎖定同樣,會發生死鎖。
  • 行鎖:開銷較大,能具體的鎖定到表中的某一行數據,可是能更好的支持併發處理, 會發生死鎖。

十、什麼是存儲過程?什麼是觸發器?

存儲過程:

(1)定義:

存儲過程是一組SQL命令集合,通過預編譯存放在系統中。也就是將經常使用的或很複雜的工做,預先用SQL語句寫好並用一個指定的名稱存儲起來,之後只要調用它就能夠完成相應的功能。 

(2)存儲過程的種類:

  存儲過程通常分爲「系統存儲過程」與「用戶存儲過程」。系統存儲過程通常以sp_開頭,用戶不能夠編輯修改,只能調用;用戶存儲過程是用戶編寫的處理數據的存儲過程。

(3)存儲過程的建立和使用: 

create procedure proc1 --建立一個存儲過程
as begin
    --在存儲過程當中處理SQL
    select * from bank
end

【注】若是有參數,存儲過程的參數是在as關鍵字以前,as以後的是局部變量,2種變量在存儲過程當中均可以使用,可是命名時不能夠衝突。例:

create procedure proc2
@mobile varchar(50),@sendMsg varchar(50)
as
begin
    print @mobile  ---輸出mobile這個參數
end

(4)存儲過程與通常的SQL語句有什麼區別呢? (存儲過程的優勢: )

  1. 存儲過程只在創造時進行編譯,之後每次執行存儲過程都不需再從新編譯,而通常SQL語句每執行一次就編譯一次,因此使用存儲過程可提升數據庫執行速度。 
  2. 當對數據庫進行復雜操做時(如對多個表進行Update,Insert,Query,Delete時),可將此複雜操做用存儲過程封裝起來與數據庫提供的事務處理結合一塊兒使用。 
  3. 存儲過程能夠重複使用,可減小數據庫開發人員的工做量 。
  4. 安全性高,可設定只有某此用戶才具備對指定存儲過程的使用權。

  缺點:對於簡單的sql語句不必使用存儲過程,存儲過程適合用於對數據庫進行復雜的操做。

觸發器:

(1)定義:

  觸發器(Trigger)是個特殊的存儲過程,它不是由用戶主動發起調用的,而是當發生某一事件而觸發,由系統自動調用。好比當用戶在數據庫中新增一條商品記錄,咱們但願同時在庫存中作登記,而庫存登記不是人工去錄入,是在發生新增商品記錄這一事件時發生,由系統自動完成錄入,這個工做就能夠交給一個特殊的存儲過程來完成,這個存儲過程就是觸發器。

(2)觸發器的工做機制: 

  觸發器是建在表上的,當這個表發生新增、修改、刪除操做時,若是這個表上有觸發器,就會被自動調用。在這個事件的過程當中,系統會產生一個臨時表,這個臨時表只有一行記錄:

  • 當執行新增操做時,臨時表的名字叫inserted
  • 當執行刪除操做時,臨時表的名字叫deleted
  • 當執行修改操做時,會同時產生2個臨時表,一個是inserted,存放的是新的數據,一個是deleted,存的是舊的數據

  當須要觸發器連帶操做登記庫存時就能夠從inserted表或者deleted表中得到變量,更新到庫存表中數據。

(3)做用:維護表的完整性,記錄表的修改來審計表的相關信息。分爲:

  • DML觸發器:當數據庫服務器中發生數據操做語言事件時執行的存儲過程,分爲:After觸發器和instead of觸發器。
  • DDL觸發器:特殊的觸發器,在響應數據定義語言(DDL)語句時觸發,通常用於數據庫中執行管理任務。DDL觸發器是響應create、after、或drop開頭的語句而激活。

觸發器用處仍是不少的,好比校內網、開心網、Facebook,你發一個日誌,自動通知好友,其實就是在增長日誌時作一個後觸發,再向通知表中寫入條目。由於觸發器效率高。

(4)建立觸發器的SQL語法:

create trigger 觸發器名稱   --觸發器名稱
on 表名                 --建在那個表上
for insert|update|delete    --是插入事件處理仍是修改事件處理仍是刪除事件處理
as                       --如下是觸發器基本格式
begin
end

調用存儲過程:call procedure_name(參數,參數...)

(5)觸發器優勢:

  • 自動執行:觸發器不用像存儲過程同樣須要手動調用,是自動觸發的,只有當對錶進行更新,刪除等操做的時候會當即觸發
  • 級聯更新:觸發器能夠經過數據庫中的相關表進行層疊更改,這比直接將代碼寫在前端的作法更安全合理。
  • 強化約束:觸發器能夠引用其餘表的列,可以實現比check約束更爲複雜的約束。
  • 跟蹤變化:觸發器能夠阻止數據庫中未經容許的指定更新和變化。
  • 強制業務邏輯:觸發器可用於執行管理任務,並強制影響數據庫的複雜業務規則。

  缺點:不一樣數據庫,語法差異很大,移植困難,換了數據庫,須要從新編寫;很差管理,把過多業務邏輯寫在存儲過程很差維護,不利於分層管理,容易混亂,通常存儲過程適用於個別對性能要求較高的業務。

 

參考:什麼是存儲過程、觸發器的解釋

  sql的存儲過程與觸發器的區別,以及各自的優缺點

  SQL高級--儲存過程和觸發器

十一、存儲過程與觸發器的區別?與函數的區別?

存儲過程與觸發器:

它們都是sql語句集,不一樣的是:

存儲過程是須要用戶調用的(經過存儲過程名字直接調用),而觸發器不是由用戶主動發起調用的,而是當發生某一事件而觸發,由系統自動調用。在insert、delete和update命令以前或以後自動調用sql命令或者存儲過程。

 

函數:

 函數:MySQL中提供了許多內置函數,還能夠自定義函數(實現程序員須要sql邏輯處理)

自定義函數建立語法:

  建立:CREATE FUNCTION 函數名稱(參數列表)  

          RETURNS 返回值類型  函數體

   修改: ALTER FUNCTION 函數名稱 [characteristic ...]

   刪除:DROP FUNCTION [IF EXISTS] 函數名稱

   調用:SELECT 函數名稱(參數列表)

 

存儲過程和函數的區別:

  1.  通常來講,存儲過程實現的功能要複雜一點,而函數的實現的功能針對性比較強。
  2. 對於存儲過程來講能夠返回參數,而函數只能返回值或者表對象。
  3.  存儲過程通常是做爲一個獨立的部分來執行,而函數能夠做爲查詢語句的一個部分來調用,因爲函數能夠返回一個表對象,所以它能夠在查詢語句中位於FROM關鍵字的後面。

十二、索引是什麼?有什麼做用以及優缺點?

索引是對數據庫表中一或多個列的值進行排序的結構,利用索引可快速訪問數據庫表的特定信息。

  舉個例子:假設有一張數據表Emplyee,該表有三列:Employee_name,Employee_age,Employee_address,表中有幾萬條記錄。如今要執行下面這條查詢語句:Select * from Employee where Employee_name='Jesus'。

  若是沒有數據庫索引功能,數據庫系統會全表掃描,逐行的遍歷整張表,對於每一行都要檢查其Employee_Name字段是否等於「Jesus」。而數據庫索引功能索引的最大做用就是加快查詢速度,它能從根本上減小須要掃表的記錄/行的數量。

優勢:

  • 索引加快數據庫的檢索速度
  • 經過建立惟一性索引,能夠保證數據庫表中每一行數據的惟一性;
  • 加速表和表之間的鏈接;
  • 使用分組和排序子句進行數據檢索時,能夠顯著減小查詢中分組和排序的時間。

缺點:

  • 建立索引和維護索引須要耗費時間,這個時間隨着數據量的增長而增長;
  • 索引須要佔用物理空間,不光是表須要佔用數據空間,每一個索引也須要佔用物理空間;
  • 當對錶進行增、刪、改、的時候索引也要動態維護,這樣就下降了數據的維護速度。

1三、說一MySQL數據庫幾個基本的索引類型?

普通索引、惟一索引、主鍵索引、聯合索引、全文索引

  • 惟一索引:索引列的值必須惟一,但容許有空值。若是是組合索引,則列值的組合必須惟一。
  • 主鍵索引:是一種特殊的惟一索引,一個表只能有一個主鍵,不容許有空值。 爲表定義主鍵將自動建立主鍵索引。(數據庫表某列或列組合,其值惟一標識表中的每一行。該列稱爲表的主鍵。)
  • 聯合索引:指對錶上的多個列作索引。只有在查詢條件中使用了建立索引時的第一個字段,索引纔會被使用。使用組合索引時遵循最左前綴原則。
  • 全文索引:主要用來查找文本中的關鍵字,而不是直接與索引中的值相比較。目前只有char、varchar,text 列上能夠建立全文索引。

http://www.javashuo.com/article/p-kijtdxkb-k.html

1四、使用索引查詢必定能提升查詢的性能嗎?爲何?

一般,經過索引查詢數據比全表掃描要快。可是咱們也必須注意到它的代價:

  索引須要空間來存儲,也須要按期維護,每當有記錄在表中增減或索引列被修改時,索引自己也會被修改。這意味着每條記錄的INSERT、DELETE、UPDATE將爲此多付出4,5 次的磁盤I/O。由於索引須要額外的存儲空間和處理,那些沒必要要的索引反而會使查詢反應時間變慢。使用索引查詢不必定能提升查詢性能,索引範圍查詢(INDEX RANGE SCAN)適用於兩種狀況:

  • 若是某個字段的取值範圍很廣,幾乎沒有重複,即高選擇性,則此時使用B+樹索引是最適合的,例如姓名。
  • 基於一個範圍的檢索,通常查詢返回結果集小於表中記錄數的20%。(MySQL數據庫的優化器會預估查詢可能獲得的行,若是大於某一個值,則B+樹會選擇全表的掃描。這個值通常在20%(即當取出的數據量超過表中數據的20%,優化器就不會使用索引))

1五、爲數據表創建索引的原則有哪些?

  • 在最頻繁使用的、用以縮小查詢範圍的字段上創建索引。
  • 在頻繁使用的、須要排序的字段上創建索引。

1六、什麼狀況下應不建或少建索引?

  • 對於那些在查詢中不多使用或者參考的列不該該建立索引。(既然這些列不多使用到,所以有索引或者無索引並不能提升查詢速度。相反,因爲增長了索引,反而下降了系統的維護速度和增大了空間需求。)
  • 對於那些只有不多數據值的列也不該該增長索引。(因爲這些列的取值不多,例如人事表的性別列,在查詢的結果中,結果集的數據行佔了表中數據行的很大比例,即須要在表中搜索的數據行的比例很大。增長索引,並不能明顯加快檢索速度。)
  • 對於那些定義爲text, image和bit數據類型的列不該該增長索引。(這是由於,這些列的數據量要麼至關大,要麼取值不多。)
  • 當修改性能遠遠大於檢索性能時,不該該建立索引。(這是由於,修改性能和檢索性能是互相矛盾的。當增長索引時,會提升檢索性能,可是會下降修改性能。當減小索引時,會提升修改性能,下降檢索性能。)

1七、什麼是mysql聯合索引?

   聯合索引是指對錶上的多個列作索引。在mysql創建聯合索引時會遵循最左前綴匹配的原則,即最左優先,在檢索數據時從聯合索引的最左邊開始匹配。

最左前綴匹配原則

  最左優先,在檢索數據時從聯合索引的最左邊開始匹配。

 

  對列col一、列col2和列col3建一個聯合索引:KEY test_col1_col2_col3 on test(col1,col2,col3);

  聯合索引 test_col1_col2_col3 至關於創建了(col1)、(col1,col2)、(col,col2,col3)三個索引。

(1)SELECT * FROM test WHERE col1="1" AND clo2="2" AND clo4=|"4"

  上面這個查詢語句執行時會依照最左前綴匹配原則,檢索時會使用索引(col1,col2)進行數據匹配。

(2)索引的字段能夠是任意順序的,如:

  SELECT * FROM test WHERE col1=「1」 AND clo2=「2」   SELECT * FROM test WHERE col2=「2」 AND clo1=「1」

  這兩個查詢語句都會用到索引(col1,col2),mysql建立聯合索引的規則是首先會對聯合合索引的最左邊的,也就是第一個字段col1的數據進行排序,在第一個字段的排序基礎上,而後再對後面第二個字段col2進行排序。其實就至關於實現了相似 order by col1 col2這樣一種排序規則。

  有人會疑惑第二個查詢語句不符合最左前綴匹配:首先能夠確定是兩個查詢語句都保函索引(col1,col2)中的col一、col2兩個字段,只是順序不同,查詢條件同樣,最後所查詢的結果確定是同樣的。既然結果是同樣的,到底以何種順序的查詢方式最好呢?此時咱們能夠藉助mysql查詢優化器explain,explain會糾正sql語句該以什麼樣的順序執行效率最高,最後才生成真正的執行計劃。

(3)若是隻查詢col2:SELECT * FROM test WHERE col2=2;

  第一個col字段是絕對有序的,而第二字段就是無序的了。因此一般狀況下,直接使用第二個字段col2進行條件判斷是用不到索引的。固然是col2字段的索引數據也是有序的狀況下才能使用咯,何時纔是有序的呢?在col1字段是等值匹配的狀況下,cid纔是有序的。這也就是mysql索引規則中要求複合索引要想使用第二個索引,必須先使用第一個索引的緣由。(並且第一個索引必須是等值匹配)。

爲何要使用聯合索引?

  • 減小開銷。建一個聯合索引(col1,col2,col3),實際至關於建了(col1),(col1,col2),(col1,col2,col3)三個索引。每多一個索引,都會增長寫操做的開銷和磁盤空間的開銷。對於大量數據的表,使用聯合索引會大大的減小開銷!
  • 覆蓋索引。對聯合索引(col1,col2,col3),若是有以下的sql: select col1,col2,col3 from test where col1=1 and col2=2。那麼MySQL能夠直接經過遍歷索引取得數據,而無需回表,這減小了不少的隨機io操做。減小io操做,特別的隨機io實際上是dba主要的優化策略。因此,在真正的實際應用中,覆蓋索引是主要的提高性能的優化手段之一。
  • 效率高。索引列越多,經過索引篩選出的數據越少。有1000W條數據的表,有以下sql:select from table where col1=1 and col2=2 and col3=3,假設假設每一個條件能夠篩選出10%的數據,若是隻有單值索引,那麼經過該索引能篩選出1000W10%=100w條數據,而後再回表從100w條數據中找到符合col2=2 and col3= 3的數據,而後再排序,再分頁;若是是聯合索引,經過索引篩選出1000w10% 10% *10%=1w,效率提高可想而知!

http://www.javashuo.com/article/p-najgcbdi-ke.html

  從本質上來講,聯合索引仍是一顆B+樹,不一樣的是聯合索引的鍵值的數量不是1,而是大於等於2。

  對於查詢 SELECT * FROM TABLE WHERE a=xxx and b=xxx,顯然能夠使用(a,b)這個聯合索引。對於單個的a列查詢 SELECT * FROM TABLE WHERE a=xxx 也是能夠使用(a,b)索引。但對於b列的查詢 SELECT * FROM TABLE WHERE b=xxx 不能夠使用這顆B+樹索引。由於葉節點上的b值爲1,2,1,4,1,2,顯然不是排序的,所以對於b列的查詢使用不到(a,b)的索引。

   聯合索引的第二個好處是,能夠對第二個鍵值進行排序。例如,在不少狀況下咱們都須要查詢某個用戶的購物狀況,並按照時間排序,去除最近3次的購買記錄,這是使用聯合索引能夠避免多一次的排序操做,由於索引自己在葉節點已經排序了。

  【注】:對於相同的第一個鍵值的數據,第二個鍵值是排好序的。

      對於單個列a的查詢每每使用單個鍵的索引,由於其葉節點包含單個鍵值,能存放的記錄更多。

1八、說一說 B+樹索引、哈希索引?

Hash索引和B+樹索引的特色:

  • Hash索引結構的特殊性,其檢索效率很是高,索引的檢索能夠一次定位;

  • B+樹索引須要從根節點到枝節點,最後才能訪問到頁節點這樣屢次的IO訪問。

Hash索引與B+樹索引區別?

  • 若是是等值查詢,那麼哈希索引明顯有絕對優點,由於只須要通過一次算法便可找到相應的鍵值;固然了,這個前提是,鍵值都是惟一的。若是鍵值不是惟一的,就須要先找到該鍵所在位置,而後再根據鏈表日後掃描,直到找到相應的數據;
  • 從示意圖中也能看到,若是是範圍查詢檢索,這時候哈希索引就毫無用武之地了,由於原先是有序的鍵值,通過哈希算法後,有可能變成不連續的了,就沒辦法再利用索引完成範圍查詢檢索;
  • 同理,哈希索引也沒辦法利用索引完成排序,以及like ‘xxx%’ 這樣的部分模糊查詢(這種部分模糊查詢,其實本質上也是範圍查詢);
  • 哈希索引也不支持多列聯合索引的最左匹配規則
  • B+樹索引的關鍵字檢索效率比較平均,不像B樹那樣波動幅度大,在有大量重複鍵值狀況下,哈希索引的效率也是極低的,由於存在所謂的哈希碰撞問題
https://www.zhihu.com/question/263964996

1九、B樹和B+樹的區別?

B+樹是一種平衡查找樹在B+樹中,全部記錄節點都是按鍵值的大小順序存放在同一層的葉節點中,各葉結點指針進行鏈接。

(平衡二叉樹AVL:首先符合二叉查找樹的定義(最結點的值比根節點小,右結點的值比根結點大),其次必須知足任何節點的左右兩個子樹的高度最大差爲1。)

  • B樹  :每一個節點都存儲key和data,全部節點組成這棵樹,而且葉子節點指針爲nul,葉子結點不包含任何關鍵字信息
  • B+樹:全部的葉子結點中包含了所有關鍵字的信息,及指向含有這些關鍵字記錄的指針,且葉子結點自己依關鍵字的大小自小而大的順序連接,全部的非終端結點能夠當作是索引部分。

20、爲何說B+比B樹更適合實際應用中操做系統的文件索引和數據庫索引?

(1)B+的磁盤讀寫代價更低

  B+的內部結點並無指向關鍵字具體信息的指針。所以其內部結點相對B樹更小。若是把全部同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的須要查找的關鍵字也就越多。相對來講IO讀寫次數也就下降了。

(2)B+tree的查詢效率更加穩定

  因爲非終結點並非最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。因此任何關鍵字的查找必須走一條從根結點到葉子結點的路。全部關鍵字查詢的路徑長度相同,致使每個數據的查詢效率至關。

2一、彙集索引和非彙集索引區別?

  數據庫中的B+索引能夠分爲彙集索引和輔助彙集索引。無論是彙集索引仍是非彙集的索引,其內部都是B+樹的,即高度平衡的,葉節點存放着全部的數據,彙集索引與非彙集索引不一樣的是,葉節點存放的是不是一整行的信息

  • 彙集索引(clustered index):

  彙集索引就是按照每張表的主鍵構造一顆B+樹而且葉節點中存放着整張表的行記錄數據,所以也讓彙集索引的葉節點成爲數據頁。彙集索引的這個特性決定了索引組織表中數據也是索引的一部分。因爲實際的數據頁只能按照一顆B+樹進行排序,所以每張表只能擁有一個彙集索引

  彙集索引表記錄的排列順序和索引的排列順序一致,因此查詢效率快,只要找到第一個索引值記錄,其他就連續性的記錄在物理也同樣連續存放。彙集索引對應的缺點就是修改慢,由於爲了保證表中記錄的物理和索引順序一致,在記錄插入的時候,會對數據頁從新排序。

  • 非彙集索引(nonclustered index)(也叫輔助索引):

  對於輔助索引(非彙集索引),葉級別不包含行的所有數據。彙集索引鍵來告訴InnoDB存儲引擎,哪裏能夠找到與索引相對應的行數據。輔助索引的存在並不影響數據在彙集索引中的組織,所以每張表上能夠有多個輔助索引經過輔助索引來尋找數據時,InnoDB存儲引擎會遍歷輔助索引並經過葉級別的指針得到指向主鍵索引的主鍵,而後再經過主鍵索引來找到一個完整的行記錄

  非彙集索引指定了表中記錄的邏輯順序,可是記錄的物理和索引不必定一致,兩種索引都採用B+樹結構,非彙集索引的葉子層並不和實際數據頁相重疊,而採用葉子層包含一個指向表中的記錄在數據頁中的指針方式。非彙集索引層次多,不會形成數據重排。

根本區別:

彙集索引和非彙集索引的根本區別是表記錄的排列順序和與索引的排列順序是否一致。

2二、說一說drop、deletetruncate的區別?

  • drop直接刪掉表。
  • truncate刪除表中數據,再插入時自增加id又從1開始。
  • delete刪除表中數據,能夠加where字句。

(1)truncate和delete只刪除數據,而drop則刪除整個表(結構和數據)。

(2)delete語句執行刪除的過程是每次從表中刪除一行,而且同時將該行的刪除操做做爲事務記錄在日誌中保存以便進行進行回滾操做。truncate table則一次性地從表中刪除全部的數據並不把單獨的刪除操做記錄記入日誌保存,刪除行是不能恢復的。而且在刪除的過程當中不會激活與表有關的刪除觸發器。執行速度快。

(3)執行速度:drop> truncate >delete

(4)delete語句是dml,這個操做會放到rollback segement,事務提交以後才生效。若是有相應的trigger(觸發器),執行的時候將被觸發

   truncate、dropddl,操做當即生效,原數據不放到rollback segment,不能回滾,操做不觸發trigger

(5)當表被truncate後,這個表和索引所佔用的空間會恢復到初始大小, delete操做不會減小表或索引所佔用的空間。

(5)應用範圍:truncate只能對table;delete能夠是table和view

若是直接刪除一個表drop,對數據量很大的表,這個過程會佔用比較長的時間,若是先truncat後drop table:一、能夠下降操做失敗的風險;二、能夠下降數據字典鎖佔用的時間,下降系統開銷。

2三、drop、deletetruncate分別在什麼場景之下使用?

  • 再也不須要一張表的時候,用drop
  • 想刪除部分數據行時候,用delete,而且帶上where子句
  • 保留表而刪除全部數據的時候用truncate

2四、超鍵、候選鍵、主鍵、外鍵分別是什麼?

 超鍵   :在關係中能惟一標識元組的屬性集稱爲關係模式的超鍵。一個屬性能夠爲做爲一個超鍵,多個屬性組合在一塊兒也能夠做爲一個超鍵。超鍵包含候選鍵和主鍵。

候選鍵:是最小超鍵,即沒有冗餘元素的超鍵。

主鍵    :數據庫表中對存儲數據對象予以惟一和完整標識的數據列或屬性的組合。一個數據列只能有一個主鍵,且主鍵的取值不能缺失,即不能爲空值(Null)。

外鍵    :在一個表中存在的另外一個表的主鍵稱此表的外鍵。

2五、mysql爲何建議用自增列做爲主鍵?

  若是咱們定義了主鍵(PRIMARY KEY),那麼InnoDB會選擇主鍵做爲彙集索引、若是沒有顯式定義主鍵,則InnoDB會選擇第一個不包含有NULL值的惟一索引做爲主鍵索引、若是也沒有這樣的惟一索引,則InnoDB會選擇內置6字節長的ROWID做爲隱含的彙集索引(ROWID隨着行記錄的寫入而主鍵遞增,這個ROWID不像ORACLE的ROWID那樣可引用,是隱含的)。

  1. 使用自增列(INT/BIGINT類型)作主鍵,這時候寫入順序是自增的,和B+數葉子節點分裂順序一致;
  2. 該表不指定自增列作主鍵,同時也沒有能夠被選爲主鍵的惟一索引(上面的條件),這時候InnoDB會選擇內置的ROWID做爲主鍵,寫入順序和ROWID增加順序一致;
  3. 除此之外,若是一個InnoDB表又沒有顯示主鍵,又有能夠被選擇爲主鍵的惟一索引,但該惟一索引可能不是遞增關係時(例如字符串、UUID、多字段聯合惟一索引的狀況),該表的存取效率就會比較差。

2六、MySQL中的varchar和char的區別以及varchar(50)中的50表明的涵義?

  char是一種固定長度的類型,varchar是一種可變長度的類型。

varchar(50)中50的含義:
    最多存放50個字符,varchar(50)和(200)存儲hello所佔空間同樣,但後者在排序時會消耗更多內存,由於order by col採用fixed_length計算col長度。ppp-

int(20)中20的含義:

   是指顯示字符的長度
   但要加參數的,最大爲255,好比它是記錄行數的id,插入10筆資料,它就顯示00000000001 ~~~00000000010,當字符的位數超過11,它也只顯示11位,若是你沒有加那個讓它未滿11位就前面加0的參數,它不會在前面加0.
  20表示最大顯示寬度爲20,但仍佔4字節存儲,存儲範圍不變;

mysql爲何這麼設計:
   對大多數應用沒有意義,只是規定一些工具用來顯示字符的個數;int(1)和int(20)存儲和計算均同樣。

2七、什麼是視圖?視圖的使用場景有哪些?

   視圖(View)是一個命名的虛表,它由一個查詢來定義,能夠看成表使用。

視圖有什麼用(應用場景)

一、當一個查詢你須要頻頻的做爲子查詢使用時,視圖能夠簡化代碼,直接調用而不是每次都去重複寫這個東西。
二、系統的數據庫管理員,須要給他人提供一張表的某兩列數據,而不但願他能夠看到其餘任何數據,這時能夠建一個只有這兩列數據的視圖,而後把視圖公佈給他。

建立視圖sql語句:

CREATE VIEW view_name AS
SELECT column_name(s)
FROM table_name
WHERE condition

視圖與表的區別

      一、視圖是已經編譯好的sql語句,而表不是。
      二、視圖沒有實際的物理記錄,而表有。
      三、表是內容,視圖是窗口。
      四、表只用物理空間而視圖不佔用物理空間,視圖只是邏輯概念的存在,表能夠及時對它進行修改,但視圖只能由建立的語句來修改。
      五、視圖是查看數據表的一種方法,能夠查詢數據表中某些字段構成的數據,只是一些SQL語句的集合。從安全的角度說,視圖能夠不給用戶接觸數據表,從而不知道表結構。
      六、表屬於全局模式中的表,是實表;視圖屬於局部模式的表,是虛表。 
      七、視圖的創建和刪除隻影響視圖自己,不影響對應的基本表。
      八、不能對視圖進行update或者insert into操做。

2八、數據庫三大範式?

第一範式(1NF)
  (在任何一個關係數據庫中,第一範式(1NF)是對關係模式的基本要求,不知足第一範式(1NF)的數據庫就不是關係數據庫。)

  所謂第一範式(1NF)是指數據庫表的每一列都是不可分割的基本數據項第一範式就是無重複的列。強調的是列的原子性,即列不可以再分紅其餘幾列。

第二範式(2NF)
  知足第二範式(2NF)必須先知足第一範式(1NF)。另外包含兩部份內容,一是表必須有主鍵;二是沒有包含在主鍵中的列必須徹底依賴於主鍵,而不能只依賴於主鍵的一部分。

第三範式(3NF)
  知足第三範式(3NF)必須先知足第二範式(2NF)第三範式就是屬性不依賴於其它非主屬性。非主鍵列必須直接依賴於主鍵,不能存在傳遞依賴

2九、sql優化

 1. explain sql 分析sql語句,這個語句能夠打印出的各類item的意義:

  • select_type :表示查詢中每一個select子句的類型
  • type :表示MySQL在表中找到所需行的方式,又稱「訪問類型」
  • possible_keys :指出MySQL能使用哪一個索引在表中找到行,查詢涉及到的字段上若存在索引,則該索引將被列出,但不必定被查詢使用。
  • key :顯示MySQL在查詢中實際使用的索引,若沒有使用索引,顯示爲NULL。
  • key_len :表示索引中使用的字節數,可經過該列計算查詢中使用的索引的長度
  • ref :表示上述表的鏈接匹配條件,即哪些列或常量被用於查找索引列上的值 
  • Extra :包含不適合在其餘列中顯示但十分重要的額外信息

2. 查詢語句不一樣元素(where、jion、limit、group by、having等等)執行前後順序?

查詢中用到的關鍵詞主要包含6個,而且他們的順序依次爲 select--from--where--group by--having--order by--limit。

其中select和from是必須的,其餘關鍵詞是可選的。

(使用having字句對分組後的結果進行篩選,因此having只能用在group by以後;

 limit 起始記錄位置:取記錄的條數對記錄進行選取,主要用來實現分頁功能)

30、非關係型數據庫和關係型數據庫區別,優點比較?

非關係型數據庫的優點:

  • 性能:NOSQL是基於鍵值對的,能夠想象成表中的主鍵和值的對應關係,並且不須要通過SQL層的解析,因此性能很是高。
  • 可擴展性:一樣也是由於基於鍵值對,數據之間沒有耦合性,因此很是容易水平擴展。

關係型數據庫的優點:

  • 複雜查詢:能夠用SQL語句方便的在一個表以及多個表之間作很是複雜的數據查詢。
  • 事務支持:使得對於安全性能很高的數據訪問要求得以實現。

其餘:

1.對於這兩類數據庫,對方的優點就是本身的弱勢,反之亦然。

2.NOSQL數據庫慢慢開始具有SQL數據庫的一些複雜查詢功能,好比MongoDB。

3.對於事務的支持也能夠用一些系統級的原子操做來實現例如樂觀鎖之類的方法來曲線救國,好比Redis set nx。

3一、什麼是 內鏈接、外鏈接、交叉鏈接、笛卡爾積等?

  • 內鏈接: 只鏈接匹配的行
  • 左外鏈接: 包含左邊表的所有行(無論右邊的表中是否存在與它們匹配的行),以及右邊表中所有匹配的行
  • 右外鏈接: 包含右邊表的所有行(無論左邊的表中是否存在與它們匹配的行),以及左邊表中所有匹配的行

例如1:
SELECT a.,b. FROM luntan LEFT JOIN usertable as b ON a.username=b.username

例如2:
SELECT a.,b. FROM city as a FULL OUTER JOIN user as b ON a.username=b.username

  • 全外鏈接: 包含左、右兩個表的所有行,無論另一邊的表中是否存在與它們匹配的行。
  • 交叉鏈接: 生成笛卡爾積-它不使用任何匹配或者選取條件,而是直接將一個數據源中的每一個行與另外一個數據源的每一個行都一一匹配

例如:
SELECT type,pub_name FROM titles CROSS JOIN publishers ORDER BY type

1.以A,B兩張表爲例
A left join B
選出A的全部記錄,B表中沒有的以null 代替
right join 同理

2.inner join
A,B的全部記錄都選出,沒有的記錄以null代替

3.cross join (笛卡爾積)
A中的每一條記錄和B中的每一條記錄生成一條記錄
例如A中有4條,B中有4條,cross join 就有16條記錄

3二、SQL語言分類

  • 數據查詢語言DQL :基本結構是由SELECT子句、FROM子句、WHERE子句組成的查詢塊。
  • 數據操縱語言DML :1)插入INSERT 2) 更新:UPDATE 3) 刪除:DELETE
  • 數據定義語言DDL :用來建立數據庫中的各類對象-----表、視圖、索引、同義詞、聚簇等如:CREATE TABLE/VIEW/INDEX/SYN/CLUSTER
          • DDL操做是隱性提交的!不能rollback
  • 數據控制語言DCL :用來授予或回收訪問數據庫的某種特權,並控制數據庫操縱事務發生的時間及效果,對數據庫實行監視等。ROLLBACK/COMMIT
  • (1) 顯式提交
    • 用COMMIT命令直接完成的提交爲顯式提交。其格式爲:SQL>COMMIT;
  • (2) 隱式提交
    • 用SQL命令間接完成的提交爲隱式提交。這些命令是:ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME。
  • (3) 自動提交
    • 若把AUTOCOMMIT設置爲ON,則在插入、修改、刪除語句執行後,系統將自動進行提交。其格式爲:SQL>SET AUTOCOMMIT ON;

3三、like %和-的區別

  % 通配符:表示任何字符出現任意次數 (能夠是0次)。
  _ 通配符:表示只能匹配單個字符,不能多也不能少,就是一個字符。

使用通配符進行模糊查詢須要用 like操做符,例:

  SELECT * FROM products WHERE products.prod_name like '%es%';

  SELECT * FROM products WHERE products.prod_name like '_es';

【注】若是在使用like操做符時,後面的沒有使用通用匹配符效果是和 = 是一致的。

   SELECT * FROM products WHERE products.prod_name like '1000':只能匹配的結果爲1000,而不能匹配像JetPack 1000這樣的結果。

3四、count(*)、count(1)、count(column)的區別

  • count(*)  :對行的數目進行計數,包含NULL
  • count(column) :對特定的列的值具備的行進行計數,不包含NULL值

  • count(1)這個用法和count(*)的結果是同樣的,包含null

性能問題:

  1. 任何狀況下SELECT COUNT(*) FROM tablename是最優選擇;
  2. 儘可能減小SELECT COUNT(*) FROM tablename WHERE COL = ‘value’ 這種查詢;
  3. 杜絕SELECT COUNT(COL) FROM tablename WHERE COL2 = ‘value’ 的出現。
  • 若是表沒有主鍵,那麼count(1)比count(*)快。
  • 若是有主鍵,那麼count(主鍵,聯合主鍵)比count(*)快。
  • 若是表只有一個字段,count(*)最快。

  count(1)跟count(主鍵)同樣,只掃描主鍵;count(*)跟count(非主鍵)同樣,掃描整個表。明顯前者更快一些。

3五、大家數據庫是否支持emoji表情,若是不支持,如何操做?

若是是utf8字符集的話,須要升級至utf8_mb4方可支持。

3六、你是如何監控大家的數據庫的?大家的慢日誌都是怎麼查詢的?

監控的工具備不少,例如zabbix,lepus,我這裏用的是lepus。

  • slow_query_log        :慢查詢開啓狀態。
  • slow_query_log_file :慢查詢日誌存放的位置(這個目錄須要MySQL的運行賬號的可寫權限,通常設置爲MySQL的數據存放目錄)。
  • long_query_time      :查詢超過多少秒才記錄。

 

 開啓慢日誌查詢:set global slow_query_log='ON';

那麼開啓了慢查詢日誌後,什麼樣的SQL纔會記錄到慢查詢日誌裏面呢? 

  這個是由參數long_query_time控制,默認狀況下long_query_time的值爲10秒,能夠使用命令修改,也能夠在my.cnf參數裏面修改。運行時間大於long_query_time(非大於等於),纔會記錄到慢查詢日誌裏。

 

3三、談談mongodb,mysql的區別和具體應用場景

MongoDB是神馬?

  MongoDB是非關係型數據庫,是一個基於分佈式文件存儲的數據庫。(文檔型數據庫:能夠存放xml、json、bson類型的數據。)同時MongoDB是由C++語言編寫。旨在爲WEB應用提供可擴展的高性能數據存儲解決方案。 是非關係數據庫當中功能最豐富,最像關係數據庫的。

  MongoDB 將數據存儲爲一個文檔,數據結構由鍵值(key=>value)對組成。MongoDB 文檔相似於 JSON 對象。字段值能夠包含其餘文檔,數組及文檔數組。

  它能夠存儲比較複雜的數據類型。Mongo最大的特色是它支持的查詢語言很是強大,其語法有點相似於面向對象的查詢語言,幾乎能夠實現相似關係數據庫單表查詢的絕大部分功能,並且還支持對數據創建索引。

  mongodb與mysql不一樣,mysql的每一次更新操做都會直接寫入硬盤,可是mongo不會,做爲內存型數據庫,數據操做會先寫入內存,而後再會持久化到硬盤中去 ,但MongoDB採用的預分配空間的方式來防止文件碎片,因此MongoDB的數據文件很大。

  MongoDB的特色是:

  (1)面向文檔(2)高性能(3)高可用(4)易擴展(5)豐富的查詢語言

  MongoDB 缺點:

    ① MongoDB 不支持事務操做(最主要的缺點)
    ② MongoDB 佔用空間過大
    ③ MongoDB 沒有如 MySQL 那樣成熟的維護工具,這對於開發和IT運營都是個值得注意的地方

  存儲方式:虛擬內存+持久化。

  持久化方式:MongoDB 的全部數據其實是存放在硬盤的,全部要操做的數據經過 mmap 的方式映射到內存某個區域內。而後,MongoDB 就在這塊區域裏面進行數據修改,避免了零碎的硬盤操做。

mongodb,mysql的區別?

  (1)MongoDB 非關係型數據庫,MySql是關係型數據庫

  (2)MongoDB存儲方式:虛擬內存+持久化; MySql在不一樣的引擎上有不一樣 的存儲方式。

  (3)MongoDB查詢語句:是獨特的Mongodb的查詢方式; MySqlMySql查詢語句是使用傳統的sql語句,擁有較爲成熟的體系,成熟度很高。

  (4)mysql的每一次更新操做都會直接寫入硬盤,可是mongo的數據操做會先寫入內存,而後再會持久化到硬盤中去 。(MongoDB數據是存儲在硬盤上的,只不過須要常常讀取的數據會被加載到內存中,將數據存儲在物理內存中,從而達到高速讀寫。)

  (5)mysql缺點就是在海量數據處理的時候效率會顯著變慢。在適量級的內存的Mongodb的性能是很是迅速的。

  (6)MongoDB 不支持事務操做,mysql的innodb和bdb存儲引擎支持事務。(注:myisam不支持事務)

 

34.一條sql語句的執行過程?

先簡單介紹一下一些組件的基本做用:

  • 鏈接器: 身份認證和權限相關(登陸 MySQL 的時候)。
  • 查詢緩存: 執行查詢語句的時候,會先查詢緩存(MySQL 8.0 版本後移除,由於這個功能不太實用)。
  • 分析器: 沒有命中緩存的話,SQL 語句就會通過分析器,分析器說白了就是要先看你的 SQL 語句要幹嗎,再檢查你的 SQL 語句語法是否正確。
  • 優化器: 按照 MySQL 認爲最優的方案去執行。
  • 執行器: 執行語句,而後從存儲引擎返回數據。

 

一條查詢語句的執行順序:

1.客戶端經過TCP鏈接發送鏈接請求到mysql鏈接器,鏈接器會對該請求進行權限驗證及鏈接資源分配

2.創建鏈接後客戶端發送一條語句,mysql收到該語句後,經過命令分發器判斷其是不是一條select語句,若是是,在開啓查詢緩存的狀況下,先在查詢緩存中查找該SQL是否徹底匹配,若是徹底匹配,驗證當前用戶是否具有查詢權限,若是權限驗證經過,直接返回結果集給客戶端,該查詢也就完成了。若是不匹配繼續向下執行。

3.若是在查詢緩存中未匹配成功,則將語句交給分析器做語法分析,MySQL須要知道到底要查哪些東西,若是語法不對,就會返回語法錯誤中斷查詢。

4.分析器的工做完成後,將語句傳遞給預處理器,檢查數據表和數據列是否存在,解析別名看是否存在歧義等

5.語句解析完成後,MySQL就知道要查什麼了,以後會將語句傳遞給優化器進行優化(經過索引選擇最快的查找方式),並生成執行計劃。

6.以後交給執行器去具體執行該語句,在執行以前,會先檢查該用戶是否具備查詢權限,若是有,繼續執行該語句。執行器開始執行後,會逐漸將數據保存到結果集中,同時會逐步將數據緩存到查詢緩存中,最終將結果集返回給客戶端。(若是該SQL執行過程當中超過了慢查詢閥值,該SQL會被記錄到慢查詢日誌中) 

一條更新語句的執行順序:

 。。。。。

  有一條記錄須要更新的時候,InnoDB引擎就會先把記錄寫到 redo log(粉板)裏,並更新到內存,這個時候更新就算完成了,同時,InnoDB引擎會在適合的時候,將這個操做記錄更新到磁盤裏面,而這個更新每每實在系統比較空閒的時候作。

 

MySQL中一條SQL語句的執行過程

一條SQL更新語句是如何執行的

 

 

參考史上最全的數據庫面試題,不看絕對後悔

  【MySQL】20個經典面試題

  數據庫常見面試題(附答案)

相關文章
相關標籤/搜索