Mysql大廠高頻面試題

前言

  • 前幾天有讀者找到我,說想要一套全面的Mysql面試題,今天陳某特意爲她寫了一篇。
  • 文章的目錄以下: ![思惟導圖](https://user-gold-cdn.xitu.io/2020/4/20/1719809b4d450b3d?w=1313&h=1727&f=png&s=415025)

Mysql面試題

什麼是SQL?

  • 結構化查詢語言(Structured Query Language)簡稱SQL,是一種數據庫查詢語言。
  • 做用:用於存取數據、查詢、更新和管理關係數據庫系統。

什麼是MySQL?

  • MySQL是一個關係型數據庫管理系統,由瑞典MySQL AB 公司開發,屬於 Oracle 旗下產品。MySQL 是最流行的關係型數據庫管理系統之一,在 WEB 應用方面,MySQL是最好的 RDBMS (Relational Database Management System,關係數據庫管理系統) 應用軟件之一。在Java企業級開發中很是經常使用,由於 MySQL 是開源免費的,而且方便擴展。

數據庫三大範式是什麼?

  • `第一範式`:每一個列都不能夠再拆分。
  • `第二範式`:在第一範式的基礎上,非主鍵列徹底依賴於主鍵,而不能是依賴於主鍵的一部分。
  • `第三範式`:在第二範式的基礎上,非主鍵列只依賴於主鍵,不依賴於其餘非主鍵。
  • 在設計數據庫結構的時候,要儘可能遵照三範式,若是不遵照,必須有足夠的理由。好比性能。事實上咱們常常會爲了性能而妥協數據庫的設計。

mysql有關權限的表都有哪幾個?

  • MySQL服務器經過權限表來控制用戶對數據庫的訪問,權限表存放在mysql數據庫裏,由mysql_install_db腳本初始化。這些權限表分別user,db,table_priv,columns_priv和host。下面分別介紹一下這些表的結構和內容:
    1. `user權限表`:記錄容許鏈接到服務器的用戶賬號信息,裏面的權限是全局級的。
    2. `db權限表`:記錄各個賬號在各個數據庫上的操做權限。
    3. `table_priv權限表`:記錄數據表級的操做權限。
    4. `columns_priv權限表`:記錄數據列級的操做權限。
    5. `host權限表`:配合db權限表對給定主機上數據庫級操做權限做更細緻的控制。這個權限表不受GRANT和REVOKE語句的影響。

MySQL的binlog有有幾種錄入格式?分別有什麼區別?

  • 有三種格式,statement,row和mixed。
    • statement模式下,每一條會修改數據的sql都會記錄在binlog中。不須要記錄每一行的變化,減小了binlog日誌量,節約了IO,提升性能。因爲sql的執行是有上下文的,所以在保存的時候須要保存相關的信息,同時還有一些使用了函數之類的語句沒法被記錄複製。
    • row級別下,不記錄sql語句上下文相關信息,僅保存哪條記錄被修改。記錄單元爲每一行的改動,基本是能夠所有記下來可是因爲不少操做,會致使大量行的改動(好比alter table),所以這種模式的文件保存的信息太多,日誌量太大。
    • mixed,一種折中的方案,普通操做使用statement記錄,當沒法使用statement的時候使用row。
  • 此外,新版的MySQL中對row級別也作了一些優化,當表結構發生變化的時候,會記錄語句而不是逐行記錄。

mysql有哪些數據類型?

  • 一、整數類型,包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分別表示1字節、2字節、3字節、4字節、8字節整數。任何整數類型均可以加上UNSIGNED屬性,表示數據是無符號的,即非負整數。
    • 長度:整數類型能夠被指定長度,例如:INT(11)表示長度爲11的INT類型。長度在大多數場景是沒有意義的,它不會限制值的合法範圍,只會影響顯示字符的個數,並且須要和UNSIGNED ZEROFILL屬性配合使用纔有意義。
    • 例子:假定類型設定爲INT(5),屬性爲UNSIGNED ZEROFILL,若是用戶插入的數據爲12的話,那麼數據庫實際存儲數據爲00012。
  • 二、實數類型,包括FLOAT、DOUBLE、DECIMAL。DECIMAL能夠用於存儲比BIGINT還大的整型,能存儲精確的小數。而FLOAT和DOUBLE是有取值範圍的,並支持使用標準的浮點進行近似計算。計算時FLOAT和DOUBLE相比DECIMAL效率更高一些,DECIMAL你能夠理解成是用字符串進行處理。
  • 三、字符串類型,包括VARCHAR、CHAR、TEXT、BLOB
    • VARCHAR用於存儲可變長字符串,它比定長類型更節省空間。
    • VARCHAR使用額外1或2個字節存儲字符串長度。列長度小於255字節時,使用1字節表示,不然使用2字節表示。
    • VARCHAR存儲的內容超出設置的長度時,內容會被截斷。
    • CHAR是定長的,根據定義的字符串長度分配足夠的空間。
    • CHAR會根據須要使用空格進行填充方便比較。
    • CHAR適合存儲很短的字符串,或者全部值都接近同一個長度。
    • CHAR存儲的內容超出設置的長度時,內容一樣會被截斷。
  • 四、枚舉類型(ENUM),把不重複的數據存儲爲一個預約義的集合。
    • 有時可使用ENUM代替經常使用的字符串類型。
    • ENUM存儲很是緊湊,會把列表值壓縮到一個或兩個字節。
    • ENUM在內部存儲時,其實存的是整數。
    • 儘可能避免使用數字做爲ENUM枚舉的常量,由於容易混亂。
    • 排序是按照內部存儲的整數
  • 五、日期和時間類型,儘可能使用timestamp,空間效率高於datetime,
    • 用整數保存時間戳一般不方便處理。
    • 若是須要存儲微妙,可使用bigint存儲。
    • 看到這裏,這道真題是否是就比較容易回答了。

MyISAM索引與InnoDB索引的區別?

  • InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。
  • InnoDB的主鍵索引的葉子節點存儲着行數據,所以主鍵索引很是高效。
  • MyISAM索引的葉子節點存儲的是行數據地址,須要再尋址一次才能獲得數據。
  • InnoDB非主鍵索引的葉子節點存儲的是主鍵和其餘帶索引的列數據,所以查詢時作到覆蓋索引會很是高效。

InnoDB引擎的4大特性

  • 插入緩衝(insert buffer)
  • 二次寫(double write)
  • 自適應哈希索引(ahi)
  • 預讀(read ahead)

什麼是索引?

  • 索引是一種特殊的文件(InnoDB數據表上的索引是表空間的一個組成部分),它們包含着對數據表裏全部記錄的引用指針。
  • 索引是一種數據結構。數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢、更新數據庫表中數據。索引的實現一般使用B樹及其變種B+樹。
  • 更通俗的說,索引就至關於目錄。爲了方便查找書中的內容,經過對內容創建索引造成目錄。索引是一個文件,它是要佔據物理空間的。

索引有哪些優缺點?

  • 索引的優勢:
    • 能夠大大加快數據的檢索速度,這也是建立索引的最主要的緣由。
    • 經過使用索引,能夠在查詢的過程當中,使用優化隱藏器,提升系統的性能。
  • 索引的缺點:
    • 時間方面:建立索引和維護索引要耗費時間,具體地,當對錶中的數據進行增長、刪除和修改的時候,索引也要動態的維護,會下降增/改/刪的執行效率;
    • 空間方面:索引須要佔物理空間。

索引有哪幾種類型?

  • `主鍵索引`: 數據列不容許重複,不容許爲NULL,一個表只能有一個主鍵。
  • `惟一索引`: 數據列不容許重複,容許爲NULL值,一個表容許多個列建立惟一索引。
    • 能夠經過 `ALTER TABLE table_name ADD UNIQUE (column);` 建立惟一索引
    • 能夠經過 `ALTER TABLE table_name ADD UNIQUE (column1,column2);` 建立惟一組合索引
  • `普通索引`: 基本的索引類型,沒有惟一性的限制,容許爲NULL值。
    • 能夠經過`ALTER TABLE table_name ADD INDEX index_name (column);`建立普通索引
    • 能夠經過`ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);`建立組合索引。
  • `全文索引`: 是目前搜索引擎使用的一種關鍵技術。
    • 能夠經過`ALTER TABLE table_name ADD FULLTEXT (column);`建立全文索引

索引的數據結構(b樹,hash)

  • 索引的數據結構和具體存儲引擎的實現有關,在MySQL中使用較多的索引有Hash索引,B+樹索引等,而咱們常用的InnoDB存儲引擎的默認索引實現爲:B+樹索引。對於哈希索引來講,底層的數據結構就是哈希表,所以在絕大多數需求爲單條記錄查詢的時候,能夠選擇哈希索引,查詢性能最快;其他大部分場景,建議選擇BTree索引。

1. B樹索引mysql

  • mysql經過存儲引擎取數據,基本上90%的人用的就是InnoDB了,按照實現方式分,InnoDB的索引類型目前只有兩種:BTREE(B樹)索引和HASH索引。B樹索引是Mysql數據庫中使用最頻繁的索引類型,基本全部存儲引擎都支持BTree索引。一般咱們說的索引不出意外指的就是(B樹)索引(實際是用B+樹實現的,由於在查看錶索引時,mysql一概打印BTREE,因此簡稱爲B樹索引) ![B樹索引](https://user-gold-cdn.xitu.io/2020/4/20/1719809b4cb9c229?w=624&h=300&f=webp&s=17494)

2. B+tree性質web

  • n棵子tree的節點包含n個關鍵字,不用來保存數據而是保存數據的索引。
  • 全部的葉子結點中包含了所有關鍵字的信息,及指向含這些關鍵字記錄的指針,且葉子結點自己依關鍵字的大小自小而大順序連接。
  • 全部的非終端結點能夠當作是索引部分,結點中僅含其子樹中的最大(或最小)關鍵字。
  • B+ 樹中,數據對象的插入和刪除僅在葉節點上進行。
  • B+樹有2個頭指針,一個是樹的根節點,一個是最小關鍵碼的葉節點。

3. 哈希索引面試

  • 簡要說下,相似於數據結構中簡單實現的HASH表(散列表)同樣,當咱們在mysql中用哈希索引時,主要就是經過Hash算法(常見的Hash算法有直接定址法、平方取中法、摺疊法、除數取餘法、隨機數法),將數據庫字段數據轉換成定長的Hash值,與這條數據的行指針一併存入Hash表的對應位置;若是發生Hash碰撞(兩個不一樣關鍵字的Hash值相同),則在對應Hash鍵下以鏈表形式存儲。固然這只是簡略模擬圖。 ![哈希索引](https://user-gold-cdn.xitu.io/2020/4/20/1719809b4d5f6f96?w=451&h=216&f=webp&s=8500)

索引的基本原理

  • 索引用來快速地尋找那些具備特定值的記錄。若是沒有索引,通常來講執行查詢時遍歷整張表。
  • 索引的原理很簡單,就是把無序的數據變成有序的查詢
    1. 把建立了索引的列的內容進行排序
    2. 對排序結果生成倒排表
    3. 在倒排表內容上拼上數據地址鏈
    4. 在查詢的時候,先拿到倒排表內容,再取出數據地址鏈,從而拿到具體數據

索引算法有哪些?

  • 索引算法有 BTree算法和Hash算法

1. BTree算法redis

  • BTree是最經常使用的mysql數據庫索引算法,也是mysql默認的算法。由於它不只能夠被用在=,>,>=,<,<=和between這些比較操做符上,並且還能夠用於like操做符,只要它的查詢條件是一個不以通配符開頭的常量。

2. Hash算法算法

  • Hash Hash索引只能用於對等比較,例如=,<=>(至關於=)操做符。因爲是一次定位數據,不像BTree索引須要從根節點到枝節點,最後才能訪問到頁節點這樣屢次IO訪問,因此檢索效率遠高於BTree索引。

索引設計的原則?

  • 適合索引的列是出如今where子句中的列,或者鏈接子句中指定的列。
  • 基數較小的類,索引效果較差,沒有必要在此列創建索引
  • 使用短索引,若是對長字符串列進行索引,應該指定一個前綴長度,這樣可以節省大量索引空間
  • 不要過分索引。索引須要額外的磁盤空間,並下降寫操做的性能。在修改表內容的時候,索引會進行更新甚至重構,索引列越多,這個時間就會越長。因此只保持須要的索引有利於查詢便可。

建立索引的原則

  • 索引雖好,但也不是無限制的使用,最好符合一下幾個原則
    • 最左前綴匹配原則,組合索引很是重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就中止匹配,好比a = 1 and b = 2 and c > 3 and d = 4 若是創建(a,b,c,d)順序的索引,d是用不到索引的,若是創建(a,b,d,c)的索引則均可以用到,a,b,d的順序能夠任意調整。
    • 較頻繁做爲查詢條件的字段纔去建立索引
    • 更新頻繁字段不適合建立索引
    • 如果不能有效區分數據的列不適合作索引列(如性別,男女未知,最多也就三種,區分度實在過低)
    • 儘可能的擴展索引,不要新建索引。好比表中已經有a的索引,如今要加(a,b)的索引,那麼只須要修改原來的索引便可。
    • 定義有外鍵的數據列必定要創建索引。
    • 對於那些查詢中不多涉及的列,重複值比較多的列不要創建索引。
    • 對於定義爲text、image和bit的數據類型的列不要創建索引。

建立索引時須要注意什麼?

  • 非空字段:應該指定列爲NOT NULL,除非你想存儲NULL。在mysql中,含有空值的列很難進行查詢優化,由於它們使得索引、索引的統計信息以及比較運算更加複雜。你應該用0、一個特殊的值或者一個空串代替空值;
  • 取值離散大的字段:(變量各個取值之間的差別程度)的列放到聯合索引的前面,能夠經過count()函數查看字段的差別值,返回值越大說明字段的惟一值越多字段的離散程度高;
  • 索引字段越小越好:數據庫的數據存儲以頁爲單位一頁存儲的數據越多一次IO操做獲取的數據越大效率越高。

使用索引查詢必定能提升查詢的性能嗎?

  • 一般,經過索引查詢數據比全表掃描要快。可是咱們也必須注意到它的代價。
  • 索引須要空間來存儲,也須要按期維護, 每當有記錄在表中增減或索引列被修改時,索引自己也會被修改。 這意味着每條記錄的INSERT,DELETE,UPDATE將爲此多付出4,5 次的磁盤I/O。 由於索引須要額外的存儲空間和處理,那些沒必要要的索引反而會使查詢反應時間變慢。使用索引查詢不必定能提升查詢性能,索引範圍查詢(INDEX RANGE SCAN)適用於兩種狀況:
  • 基於一個範圍的檢索,通常查詢返回結果集小於表中記錄數的30%
  • 基於非惟一性索引的檢索

百萬級別或以上的數據如何刪除?

  • 關於索引:因爲索引須要額外的維護成本,由於索引文件是單獨存在的文件,因此當咱們對數據的增長,修改,刪除,都會產生額外的對索引文件的操做,這些操做須要消耗額外的IO,會下降增/改/刪的執行效率。因此,在咱們刪除數據庫百萬級別數據的時候,查詢MySQL官方手冊得知刪除數據的速度和建立的索引數量是成正比的。
    1. 因此咱們想要刪除百萬數據的時候能夠先刪除索引(此時大概耗時三分多鐘)
    2. 而後刪除其中無用數據(此過程須要不到兩分鐘)
    3. 刪除完成後從新建立索引(此時數據較少了)建立索引也很是快,約十分鐘左右。
    4. 與以前的直接刪除絕對是要快速不少,更別說萬一刪除中斷,一切刪除會回滾。那更是坑了。

什麼是最左前綴原則?什麼是最左匹配原則?

  • 顧名思義,就是最左優先,在建立多列索引時,要根據業務需求,where子句中使用最頻繁的一列放在最左邊。
  • 最左前綴匹配原則,很是重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就中止匹配,好比a = 1 and b = 2 and c > 3 and d = 4 若是創建(a,b,c,d)順序的索引,d是用不到索引的,若是創建(a,b,d,c)的索引則均可以用到,a,b,d的順序能夠任意調整。
  • =和in能夠亂序,好比a = 1 and b = 2 and c = 3 創建(a,b,c)索引能夠任意順序,mysql的查詢優化器會幫你優化成索引能夠識別的形式

B樹和B+樹的區別

  • 在B樹中,你能夠將鍵和值存放在內部節點和葉子節點;但在B+樹中,內部節點都是鍵,沒有值,葉子節點同時存放鍵和值。
  • B+樹的葉子節點有一條鏈相連,而B樹的葉子節點各自獨立。 ![B樹和B+樹的區別](https://user-gold-cdn.xitu.io/2020/4/20/1719809b508da704?w=1540&h=566&f=jpeg&s=156402)

使用B樹的好處

  • B樹能夠在內部節點同時存儲鍵和值,所以,把頻繁訪問的數據放在靠近根節點的地方將會大大提升熱點數據的查詢效率。這種特性使得B樹在特定數據重複屢次查詢的場景中更加高效。

使用B+樹的好處

  • 因爲B+樹的內部節點只存放鍵,不存放值,所以,一次讀取,能夠在內存頁中獲取更多的鍵,有利於更快地縮小查找範圍。 B+樹的葉節點由一條鏈相連,所以,當須要進行一次全數據遍歷的時候,B+樹只須要使用O(logN)時間找到最小的一個節點,而後經過鏈進行O(N)的順序遍歷便可。而B樹則須要對樹的每一層進行遍歷,這會須要更多的內存置換次數,所以也就須要花費更多的時間

什麼是聚簇索引?什麼時候使用聚簇索引與非聚簇索引?

  • 聚簇索引:將數據存儲與索引放到了一塊,找到索引也就找到了數據
  • 非聚簇索引:將數據存儲於索引分開結構,索引結構的葉子節點指向了數據的對應行,myisam經過key_buffer把索引先緩存到內存中,當須要訪問數據時(經過索引訪問數據),在內存中直接搜索索引,而後經過索引找到磁盤相應數據,這也就是爲何索引不在key buffer命中時,速度慢的緣由。

非聚簇索引必定會回表查詢嗎?

  • 不必定,這涉及到查詢語句所要求的字段是否所有命中了索引,若是所有命中了索引,那麼就沒必要再進行回表查詢。
  • 舉個簡單的例子,假設咱們在員工表的年齡上創建了索引,那麼當進行select age from employee where age < 20的查詢時,在索引的葉子節點上,已經包含了age信息,不會再次進行回表查詢。

聯合索引是什麼?爲何須要注意聯合索引中的順序?

  • MySQL可使用多個字段同時創建一個索引,叫作聯合索引。在聯合索引中,若是想要命中索引,須要按照創建索引時的字段順序挨個使用,不然沒法命中索引。
  • MySQL使用索引時須要索引有序,假設如今創建了"name,age,school"的聯合索引,那麼索引的排序爲: 先按照name排序,若是name相同,則按照age排序,若是age的值也相等,則按照school進行排序。
  • 當進行查詢時,此時索引僅僅按照name嚴格有序,所以必須首先使用name字段進行等值查詢,以後對於匹配到的列而言,其按照age字段嚴格有序,此時可使用age字段用作索引查找,以此類推。所以在創建聯合索引的時候應該注意索引列的順序,通常狀況下,將查詢需求頻繁或者字段選擇性高的列放在前面。此外能夠根據特例的查詢或者表結構進行單獨的調整。

什麼是數據庫事務?

  • 事務是一個不可分割的數據庫操做序列,也是數據庫併發控制的基本單位,其執行的結果必須使數據庫從一種一致性狀態變到另外一種一致性狀態。事務是邏輯上的一組操做,要麼都執行,要麼都不執行。

事物的四大特性(ACID)介紹一下?

  • `原子性`: 事務是最小的執行單位,不容許分割。事務的原子性確保動做要麼所有完成,要麼徹底不起做用;
  • `一致性`: 執行事務先後,數據保持一致,多個事務對同一個數據讀取的結果是相同的;
  • `隔離性`: 併發訪問數據庫時,一個用戶的事務不被其餘事務所幹擾,各併發事務之間數據庫是獨立的;
  • `持久性`: 一個事務被提交以後。它對數據庫中數據的改變是持久的,即便數據庫發生故障也不該該對其有任何影響。

什麼是髒讀?幻讀?不可重複讀?

  • `髒讀`(Drity Read):某個事務已更新一份數據,另外一個事務在此時讀取了同一份數據,因爲某些緣由,前一個RollBack了操做,則後一個事務所讀取的數據就會是不正確的。
  • `不可重複讀`(Non-repeatable read):在一個事務的兩次查詢之中數據不一致,這多是兩次查詢過程當中間插入了一個事務更新的原有的數據。
  • `幻讀`(Phantom Read):在一個事務的兩次查詢中數據筆數不一致,例若有一個事務查詢了幾列(Row)數據,而另外一個事務卻在此時插入了新的幾列數據,先前的事務在接下來的查詢中,就會發現有幾列數據是它先前所沒有的。

什麼是事務的隔離級別?MySQL的默認隔離級別是什麼?

  • 爲了達到事務的四大特性,數據庫定義了4種不一樣的事務隔離級別,由低到高依次爲Read uncommitted、Read committed、Repeatable read、Serializable,這四個級別能夠逐個解決髒讀、不可重複讀、幻讀這幾類問題。
  • SQL 標準定義了四個隔離級別:
    • `READ-UNCOMMITTED`(讀取未提交): 最低的隔離級別,容許讀取還沒有提交的數據變動,可能會致使髒讀、幻讀或不可重複讀。
    • `READ-COMMITTED`(讀取已提交): 容許讀取併發事務已經提交的數據,能夠阻止髒讀,可是幻讀或不可重複讀仍有可能發生。
    • `REPEATABLE-READ`(可重複讀): 對同一字段的屢次讀取結果都是一致的,除非數據是被自己事務本身所修改,能夠阻止髒讀和不可重複讀,但幻讀仍有可能發生。
    • `SERIALIZABLE`(可串行化): 最高的隔離級別,徹底服從ACID的隔離級別。全部的事務依次逐個執行,這樣事務之間就徹底不可能產生干擾,也就是說,該級別能夠防止髒讀、不可重複讀以及幻讀。
  • **Mysql 默認採用的 REPEATABLE_READ隔離級別 Oracle 默認採用的 READ_COMMITTED隔離級別**

隔離級別與鎖的關係

  • 在Read Uncommitted級別下,讀取數據不須要加共享鎖,這樣就不會跟被修改的數據上的排他鎖衝突
  • 在Read Committed級別下,讀操做須要加共享鎖,可是在語句執行完之後釋放共享鎖;
  • 在Repeatable Read級別下,讀操做須要加共享鎖,可是在事務提交以前並不釋放共享鎖,也就是必須等待事務執行完畢之後才釋放共享鎖。
  • SERIALIZABLE 是限制性最強的隔離級別,由於該級別鎖定整個範圍的鍵,並一直持有鎖,直到事務完成。

按照鎖的粒度分數據庫鎖有哪些?

  • `行級鎖`:行級鎖是Mysql中鎖定粒度最細的一種鎖,表示只針對當前操做的行進行加鎖。行級鎖能大大減小數據庫操做的衝突。其加鎖粒度最小,但加鎖的開銷也最大。行級鎖分爲共享鎖 和 排他鎖。特色:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的機率最低,併發度也最高。
  • `表級鎖`: 表級鎖是MySQL中鎖定粒度最大的一種鎖,表示對當前操做的整張表加鎖,它實現簡單,資源消耗較少,被大部分MySQL引擎支持。最常使用的MYISAM與INNODB都支持表級鎖定。表級鎖定分爲表共享讀鎖(共享鎖)與表獨佔寫鎖(排他鎖)。特色:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發出鎖衝突的機率最高,併發度最低。
  • `頁級鎖`:頁級鎖是MySQL中鎖定粒度介於行級鎖和表級鎖中間的一種鎖。表級鎖速度快,但衝突多,行級衝突少,但速度慢。因此取了折衷的頁級,一次鎖定相鄰的一組記錄。

從鎖的類別上分MySQL都有哪些鎖呢?

  • 從鎖的類別上來說,有共享鎖和排他鎖。
    • 共享鎖: 又叫作讀鎖。 當用戶要進行數據的讀取時,對數據加上共享鎖。共享鎖能夠同時加上多個。
    • 排他鎖: 又叫作寫鎖。 當用戶要進行數據的寫入時,對數據加上排他鎖。排他鎖只能夠加一個,他和其餘的排他鎖,共享鎖都相斥。

InnoDB存儲引擎的鎖的算法有哪三種?

  • Record lock:單個行記錄上的鎖
  • Gap lock:間隙鎖,鎖定一個範圍,不包括記錄自己
  • Next-key lock:record+gap 鎖定一個範圍,包含記錄自己

什麼是死鎖?怎麼解決?

  • 死鎖是指兩個或多個事務在同一資源上相互佔用,並請求鎖定對方的資源,從而致使惡性循環的現象。
  • 常見的解決死鎖的方法
    1. 若是不一樣程序會併發存取多個表,儘可能約定以相同的順序訪問表,能夠大大下降死鎖機會。
    2. 在同一個事務中,儘量作到一次鎖定所須要的全部資源,減小死鎖產生機率;
    3. 對於很是容易產生死鎖的業務部分,能夠嘗試使用升級鎖定顆粒度,經過表級鎖定來減小死鎖產生的機率;
  • 若是業務處理很差能夠用分佈式事務鎖或者使用樂觀鎖

數據庫的樂觀鎖和悲觀鎖是什麼?怎麼實現的?

  • 數據庫管理系統(DBMS)中的併發控制的任務是確保在多個事務同時存取數據庫中同一數據時不破壞事務的隔離性和統一性以及數據庫的統一性。樂觀併發控制(樂觀鎖)和悲觀併發控制(悲觀鎖)是併發控制主要採用的技術手段。
  • `悲觀鎖`:假定會發生併發衝突,屏蔽一切可能違反數據完整性的操做。在查詢完數據的時候就把事務鎖起來,直到提交事務。實現方式:使用數據庫中的鎖機制
  • `樂觀鎖`:假設不會發生併發衝突,只在提交操做時檢查是否違反數據完整性。在修改數據的時候把事務鎖起來,經過version的方式來進行鎖定。實現方式:樂通常會使用版本號機制或CAS算法實現。

大表數據查詢,怎麼優化?

  • 優化shema、sql語句+索引;
  • 第二加緩存,memcached, redis;
  • 主從複製,讀寫分離;
  • 垂直拆分,根據你模塊的耦合度,將一個大的系統分爲多個小的系統,也就是分佈式系統
  • 水平切分,針對數據量大的表,這一步最麻煩,最能考驗技術水平,要選擇一個合理的sharding key, 爲了有好的查詢效率,表結構也要改動,作必定的冗餘,應用也要改,sql中儘可能帶sharding key,將數據定位到限定的表上去查,而不是掃描所有的表

超大分頁怎麼處理?

  • 超大的分頁通常從兩個方向上來解決:
    • 數據庫層面,這也是咱們主要集中關注的(雖然收效沒那麼大),相似於select * from table where age > 20 limit 1000000,10這種查詢其實也是有能夠優化的餘地的. 這條語句須要load1000000數據而後基本上所有丟棄,只取10條固然比較慢. 當時咱們能夠修改成select * from table where id in (select id from table where age > 20 limit 1000000,10).這樣雖然也load了一百萬的數據,可是因爲索引覆蓋,要查詢的全部字段都在索引中,因此速度會很快. 同時若是ID連續的好,咱們還能夠select * from table where id > 1000000 limit 10,效率也是不錯的,優化的可能性有許多種,可是核心思想都同樣,就是減小load的數據
    • 從需求的角度減小這種請求…主要是不作相似的需求(直接跳轉到幾百萬頁以後的具體某一頁.只容許逐頁查看或者按照給定的路線走,這樣可預測,可緩存)以及防止ID泄漏且連續被人惡意***

爲何要儘可能設定一個主鍵?

  • 主鍵是數據庫確保數據行在整張表惟一性的保障,即便業務上本張表沒有主鍵,也建議添加一個自增加的ID列做爲主鍵。設定了主鍵以後,在後續的刪改查的時候可能更加快速以及確保操做數據範圍安全。

主鍵使用自增ID仍是UUID?

  • 推薦使用自增ID,不要使用UUID。
  • 由於在InnoDB存儲引擎中,主鍵索引是做爲聚簇索引存在的,也就是說,主鍵索引的B+樹葉子節點上存儲了主鍵索引以及所有的數據(按照順序),若是主鍵索引是自增ID,那麼只須要不斷向後排列便可,若是是UUID,因爲到來的ID與原來的大小不肯定,會形成很是多的數據插入,數據移動,而後致使產生不少的內存碎片,進而形成插入性能的降低。
  • 總之,在數據量大一些的狀況下,用自增主鍵性能會好一些。
  • 關於主鍵是聚簇索引,若是沒有主鍵,InnoDB會選擇一個惟一鍵來做爲聚簇索引,若是沒有惟一鍵,會生成一個隱式的主鍵。

字段爲何要求定義爲not null?

  • null值會佔用更多的字節,且會在程序中形成不少與預期不符的狀況。

若是要存儲用戶的密碼散列,應該使用什麼字段進行存儲?

  • 密碼散列,鹽,用戶身份證號等固定長度的字符串應該使用char而不是varchar來存儲,這樣能夠節省空間且提升檢索效率。

數據庫結構優化?

  • 一個好的數據庫設計方案對於數據庫的性能每每會起到事半功倍的效果。
  • 須要考慮數據冗餘、查詢和更新的速度、字段的數據類型是否合理等多方面的內容。
  • **將字段不少的表分解成多個表**:對於字段較多的表,若是有些字段的使用頻率很低,能夠將這些字段分離出來造成新表。由於當一個表的數據量很大時,會因爲使用頻率低的字段的存在而變慢。
  • **增長中間表**:對於須要常常聯合查詢的表,能夠創建中間表以提升查詢效率。經過創建中間表,將須要經過聯合查詢的數據插入到中間表中,而後將原來的聯合查詢改成對中間表的查詢。
  • **增長冗餘字段**:設計數據表時應儘可能遵循範式理論的規約,儘量的減小冗餘字段,讓數據庫設計看起來精緻、優雅。可是,合理的加入冗餘字段能夠提升查詢速度。表的規範化程度越高,表和表之間的關係越多,須要鏈接查詢的狀況也就越多,性能也就越差。

MySQL數據庫cpu飆升到500%的話他怎麼處理?

  • 當 cpu 飆升到 500%時,先用操做系統命令 top 命令觀察是否是 mysqld 佔用致使的,若是不是,找出佔用高的進程,並進行相關處理。
  • 若是是 mysqld 形成的, show processlist,看看裏面跑的 session 狀況,是否是有消耗資源的 sql 在運行。找出消耗高的 sql,看看執行計劃是否準確, index 是否缺失,或者實在是數據量太大形成。
  • 通常來講,確定要 kill 掉這些線程(同時觀察 cpu 使用率是否降低),等進行相應的調整(好比說加索引、改 sql、改內存參數)以後,再從新跑這些 SQL。
  • 也有多是每一個 sql 消耗資源並很少,可是忽然之間,有大量的 session 連進來致使 cpu 飆升,這種狀況就須要跟應用一塊兒來分析爲什麼鏈接數會激增,再作出相應的調整,好比說限制鏈接數等。

主從複製的做用?

  • 主數據庫出現問題,能夠切換到從數據庫。
  • 能夠進行數據庫層面的讀寫分離。
  • 能夠在從數據庫上進行平常備份。

MySQL主從複製解決的問題?

  • 數據分佈:隨意開始或中止複製,並在不一樣地理位置分佈數據備份
  • 負載均衡:下降單個服務器的壓力
  • 高可用和故障切換:幫助應用程序避免單點失敗
  • 升級測試:能夠用更高版本的MySQL做爲從庫

MySQL主從複製工做原理?

  • 在主庫上把數據更高記錄到二進制日誌
  • 從庫將主庫的日誌複製到本身的中繼日誌
  • 從庫讀取中繼日誌的事件,將其重放到從庫數據中。
相關文章
相關標籤/搜索