數據庫面試相關

參考:https://juejin.im/post/5a9ca0d6518825555c1d1acd#heading-10

目錄

1. MySQL的語句執行順序

2. 數據庫的樂觀鎖和悲觀鎖是什麼?

3. SQL 約束有哪幾種?(列屬性-列約束)

4. 數據庫鎖

5. Mysql存儲引擎

6. 最左匹配原則


 

1. MySQL的語句執行順序

MySQL的語句一共分爲11步,如下圖所標註的那樣,最先執行的總是FROM操作最後執行的是LIMIT操作。其中每一個操作都會產生一張虛擬的表,這個虛擬的表作爲一個處理的輸入,只是這些虛擬的表對用戶來說是透明的,但是隻有最後一個虛擬的表纔會被作爲結果返回。如果沒有在語句中指定某一個子句,那麼將會跳過相應的步驟。

下面我們來具體分析一下查詢處理的每一個階段

  1. FORM: 對FROM的左邊的表和右邊的表計算笛卡爾積。產生虛表VT1

  2. ON: 對虛表VT1進行ON篩選,只有那些符合<join-condition>的行纔會被記錄在虛表VT2中。
  3. JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那麼保留表中未匹配的行就會作爲外部行添加到虛擬表VT2中,產生虛擬表VT3, rug from子句中包含兩個以上的表的話,那麼就會對上一個join連接產生的結果VT3和下一個表重複執行步驟1~3這三個步驟,一直到處理完所有的表爲止。
  4. WHERE: 對虛擬表VT3進行WHERE條件過濾。只有符合<where-condition>的記錄纔會被插入到虛擬表VT4中。
  5. GROUP BY: 根據group by子句中的列,對VT4中的記錄進行分組操作,產生VT5.
  6. CUBE | ROLLUP: 對錶VT5進行cube或者rollup操作,產生表VT6.
  7. HAVING: 對虛擬表VT6應用having過濾,只有符合<having-condition>的記錄纔會被 插入到虛擬表VT7中。
  8. SELECT: 執行select操作,選擇指定的列,插入到虛擬表VT8中。
  9. DISTINCT: 對VT8中的記錄進行去重。產生虛擬表VT9.
  10. ORDER BY: 將虛擬表VT9中的記錄按照<order_by_list>進行排序操作,產生虛擬表VT10.
  11. LIMIT:取出指定行的記錄,產生虛擬表VT11, 並將結果返回。

轉自:https://www.cnblogs.com/rollenholt/p/3776923.html

 

2. 數據庫的樂觀鎖和悲觀鎖是什麼?

數據的鎖定分爲兩種,第一種叫作悲觀鎖,第二種叫作樂觀鎖。

  1. 悲觀鎖:在多個事務同時存取數據庫中同一數據時,對數據的衝突採取一種悲觀的態度,也就是說假設數據肯定會衝突,所以在數據開始讀取的時候就把數據鎖定住。【數據鎖定:數據將暫時不會得到修改】
  2. 樂觀鎖:認爲數據一般情況下不會造成衝突,所以在數據進行提交更新的時候,纔會正式對數據的衝突與否進行檢測,如果發現衝突了,則讓用戶返回錯誤的信息。讓用戶決定如何去做。

實現

一、悲觀鎖
    1、排它鎖,當事務在操作數據時把這部分數據進行鎖定,直到操作完畢後再解鎖,其他事務操作纔可操作該部分數據。這將防止其他進程讀取或修改表中的數據。
    2、實現:大多數情況下依靠數據庫的鎖機制實現

     一般使用 select ...for update 對所選擇的數據進行加鎖處理,例如select * from account where name=”Max” for update, 這條sql 語句鎖定了account 表中所有符合檢索條件(name=”Max”)的記錄。本次事務提交之前(事務提交時會釋放事務過程中的鎖),外界無法修改這些記錄。

二、樂觀鎖
    1、如果有人在你之前更新了,你的更新應當是被拒絕的,可以讓用戶重新操作。
    2、實現:使用version版本或者時間戳

     具體可通過給表加一個版本號或時間戳字段實現,當讀取數據時,將version字段的值一同讀出,數據每更新一次,對此version值加一。當我們提交更新的時候,判斷當前版本信息與第一次取出來的版本值大小,如果數據庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認爲是過期數據,拒絕更新,讓用戶重新操作。

 

3. SQL 約束有哪幾種?(列屬性-列約束)

  1. PRIMARY KEY: 能唯一標識記錄的字段,可以作爲主鍵,在一個表只允許出現一個。
  2. UNIQUE: 控件字段內容不能重複,一個表允許有多個 Unique 約束。
  3. NULL:null不是數據類型,是列的一個屬性。表示當前列是否可以爲null,表示什麼都沒有。
    • null, 允許爲空。默認。
    • not null, 不允許爲空。
  4. DEFAULT:默認值屬性
  5. AUTO_INCREMENT:自動增長約束
  6. COMMENT:註釋
  7. FOREIGN KEY: 用於預防破壞表之間連接的動作,也能防止非法數據插入外鍵列,因爲它必須是它指向的那個表中的值之一。

4. 數據庫鎖

參看:數據庫兩大神器【索引和鎖】

 

  • 表鎖
    • 開銷小,加鎖快;不會出現死鎖;鎖定力度大,發生鎖衝突概率高,併發度最低
  • 行鎖
    • 開銷大,加鎖慢;會出現死鎖;鎖定粒度小,發生鎖衝突的概率低,併發度高

不同的存儲引擎支持的鎖粒度是不一樣的:

  • InnoDB:行鎖和表鎖都支持

InnoDB只有通過索引條件檢索數據才使用行級鎖,否則,InnoDB將使用表鎖

也就是說,InnoDB的行鎖是基於索引的

  • MyISAM:只支持表鎖

表鎖

表鎖下又分爲兩種模式

  • 表讀鎖(Table Read Lock)
  • 表寫鎖(Table Write Lock)

在表讀鎖和表寫鎖的環境下:讀讀不阻塞,讀寫阻塞,寫寫阻塞

  • 讀讀不阻塞:當前用戶在讀數據,其他的用戶也在讀數據,不會加鎖
  • 讀寫阻塞:當前用戶在讀數據,其他的用戶不能修改當前用戶讀的數據,會加鎖!
  • 寫寫阻塞:當前用戶在修改數據,其他的用戶不能修改當前用戶正在修改的數據,會加鎖!

行鎖:

我們使用Mysql一般是使用InnoDB存儲引擎的。InnoDB和MyISAM有兩個本質的區別:

  • InnoDB支持行鎖
  • InnoDB支持事務

從上面也說了:我們是很少手動加表鎖的。表鎖對我們程序員來說幾乎是透明的,即使InnoDB不走索引,加的表鎖也是自動的

InnoDB實現了以下兩種類型的行鎖。

  • 共享鎖(S鎖):允許一個事務去讀一行,阻止其他事務獲得相同數據集的排他鎖。
    • 也叫做讀鎖:讀鎖是共享的,多個客戶可以同時讀取同一個資源,但不允許其他客戶修改
  • 排他鎖(X鎖):允許獲得排他鎖的事務更新數據,阻止其他事務取得相同數據集的共享讀鎖和排他寫鎖。
    • 也叫做寫鎖:寫鎖是排他的,寫鎖會阻塞其他的寫鎖和讀鎖

爲了允許行鎖和表鎖共存,實現多粒度鎖機制,InnoDB還有兩種內部使用的意向鎖(Intention Locks),這兩種意向鎖都是表鎖

  • 意向共享鎖(IS):事務打算給數據行加行共享鎖,事務在給一個數據行加共享鎖前必須先取得該表的IS鎖。
  • 意向排他鎖(IX):事務打算給數據行加行排他鎖,事務在給一個數據行加排他鎖前必須先取得該表的IX鎖。
  • 意向鎖也是數據庫隱式幫我們做了,不需要程序員操心

 

5. Mysql存儲引擎

常用的存儲引擎有以下:

  • Innodb引擎,Innodb引擎提供了對數據庫ACID事務的支持。並且還提供了行級鎖外鍵的約束。它的設計的目標就是處理大數據容量的數據庫系統。
  • MyIASM引擎(原本Mysql的默認引擎),不提供事務的支持,也不支持行級鎖和外鍵

同一個數據庫也可以使用多種存儲引擎的表。如果一個表修改要求比較高的事務處理,可以選擇InnoDB。這個數據庫中可以將查詢要求比較高的表選擇MyISAM存儲。如果該數據庫需要一個用於查詢的臨時表,可以選擇MEMORY存儲引擎

 

6. 最左匹配原則

1.簡單說下什麼是最左匹配原則

顧名思義:最左優先,以最左邊的爲起點任何連續的索引都能匹配上。同時遇到範圍查詢(>、<、between、like)就會停止匹配(不實用索引)。

例如:b = 2 如果建立(a,b)順序的索引,是匹配不到(a,b)索引的;但是如果查詢條件是a = 1 and b = 2或者a=1(又或者是b = 2 and b = 1)就可以,因爲優化器會自動調整a,b的順序。再比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,因爲c字段是一個範圍查詢,它之後的字段會停止匹配。

2.最左匹配原則的原理

最左匹配原則都是針對聯合索引來說的,所以我們有必要了解一下聯合索引的原理。瞭解了聯合索引,那麼爲什麼會有最左匹配原則這種說法也就理解了。

我們都知道索引的底層是一顆B+樹,那麼聯合索引當然還是一顆B+樹,只不過聯合索引的健值數量不是一個,而是多個構建一顆B+樹只能根據一個值來構建,因此數據庫依據聯合索引最左的字段來構建B+樹

例子:假如創建一個(a,b)的聯合索引,那麼它的索引樹是這樣的


可以看到a的值是有順序的,1,1,2,2,3,3,而b的值是沒有順序的1,2,1,4,1,2。所以b = 2這種查詢條件沒有辦法利用索引,因爲聯合索引首先是按a排序的,b是無序的。

同時我們還可以發現在a值相等的情況下,b值又是按順序排列的,但是這種順序是相對的。所以最左匹配原則遇上範圍查詢就會停止,剩下的字段都無法使用索引。例如a = 1 and b = 2 a,b字段都可以使用索引,因爲在a值確定的情況下b是相對有序的,而a>1and b=2,a字段可以匹配上索引,但b值不可以,因爲a的值是一個範圍,在這個範圍中b是無序的。

 

7. Mysql實現full join

è¿éåå¾çæè¿°

oracle裏面有full join,但是在mysql中沒有full join。我們可以使用union來達到目的。

mysql> select * from t1 left join t2 on t1.id = t2.id
    -> union 
    -> select * from t1 right join t2 on t1.id = t2.id;

è¿éåå¾çæè¿°

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