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

數據庫面試知識點彙總

1、基本概念

1.主鍵、外鍵、超鍵、候選鍵

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

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

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

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

2.爲何用自增列做爲主鍵

若是咱們定義了主鍵(PRIMARY KEY),那麼InnoDB會選擇主鍵做爲彙集索引、面試

若是沒有顯式定義主鍵,則InnoDB會選擇第一個不包含有NULL值的惟一索引做爲主鍵索引、算法

若是也沒有這樣的惟一索引,則InnoDB會選擇內置6字節長的ROWID做爲隱含的彙集索引(ROWID隨着行記錄的寫入而主鍵遞增,這個ROWID不像ORACLE的ROWID那樣可引用,是隱含的)。sql

數據記錄自己被存於主索引(一顆B+Tree)的葉子節點上。這就要求同一個葉子節點內(大小爲一個內存頁或磁盤頁)的各條數據記錄按主鍵順序存放,所以每當有一條新的記錄插入時,MySQL會根據其主鍵將其插入適當的節點和位置,若是頁面達到裝載因子(InnoDB默認爲15/16),則開闢一個新的頁(節點)數據庫

若是表使用自增主鍵,那麼每次插入新的記錄,記錄就會順序添加到當前索引節點的後續位置,當一頁寫滿,就會自動開闢一個新的頁緩存

若是使用非自增主鍵(若是身份證號或學號等),因爲每次插入主鍵的值近似於隨機,所以每次新紀錄都要被插到現有索引頁得中間某個位置,此時MySQL不得不爲了將新記錄插到合適位置而移動數據,甚至目標頁面可能已經被回寫到磁盤上而從緩存中清掉,此時又要從磁盤上讀回來,這增長了不少開銷,同時頻繁的移動、分頁操做形成了大量的碎片,獲得了不夠緊湊的索引結構,後續不得不經過OPTIMIZE TABLE來重建表並優化填充頁面。安全

3.觸發器的做用?

觸發器是一種特殊的存儲過程,主要是經過事件來觸發而被執行的。它能夠強化約束,來維護數據的完整性和一致性,能夠跟蹤數據庫內的操做從而不容許未經許可的更新和變化。能夠聯級運算。如,某表上的觸發器上包含對另外一個表的數據操做,而該操做又會致使該表觸發器被觸發。

4.什麼是存儲過程?用什麼來調用?

存儲過程是一個預編譯的SQL語句,優勢是容許模塊化的設計,就是說只需建立一次,之後在該程序中就能夠調用屢次。若是某次操做須要執行屢次SQL,使用存儲過程比單純SQL語句執行要快。

調用:

1)能夠用一個命令對象來調用存儲過程。

2)能夠供外部程序調用,好比:java程序。

5.存儲過程的優缺點?

優勢:

1)存儲過程是預編譯過的,執行效率高。

2)存儲過程的代碼直接存放於數據庫中,經過存儲過程名直接調用,減小網絡通信。

3)安全性高,執行存儲過程須要有必定權限的用戶。

4)存儲過程能夠重複使用,可減小數據庫開發人員的工做量。

缺點:移植性差

6.存儲過程與函數的區別

7.什麼叫視圖?遊標是什麼?

視圖:

是一種虛擬的表,具備和物理表相同的功能。能夠對視圖進行增,改,查,操做,試圖一般是有一個表或者多個表的行或列的子集。對視圖的修改會影響基本表。它使得咱們獲取數據更容易,相比多表查詢。

遊標:

是對查詢出來的結果集做爲一個單元來有效的處理。遊標能夠定在該單元中的特定行,從結果集的當前行檢索一行或多行。能夠對結果集當前行作修改。通常不使用遊標,可是須要逐條處理數據的時候,遊標顯得十分重要。

8.視圖的優缺點

優勢:

1對數據庫的訪問,由於視圖能夠有選擇性的選取數據庫裏的一部分。

2)用戶經過簡單的查詢能夠從複雜查詢中獲得結果。

3)維護數據的獨立性,試圖可從多個表檢索數據。

4)對於相同的數據可產生不一樣的視圖。

缺點:

性能:查詢視圖時,必須把視圖的查詢轉化成對基本表的查詢,若是這個視圖是由一個複雜的多表查詢所定義,那麼,那麼就沒法更改數據

9.drop、truncate、 delete區別

最基本:

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

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

(2) 表和索引所佔空間。當表被TRUNCATE 後,這個表和索引所佔用的空間會恢復到初始大小,而DELETE操做不會減小表或索引所佔用的空間。drop語句將表所佔用的空間全釋放掉。

(3) 通常而言,drop > truncate > delete

(4) 應用範圍。TRUNCATE 只能對TABLE;DELETE能夠是table和view

(5) TRUNCATE 和DELETE只刪除數據,而DROP則刪除整個表(結構和數據)。

(6) truncate與不帶where的delete :只刪除數據,而不刪除表的結構(定義)drop語句將刪除表的結構被依賴的約束(constrain),觸發器(trigger)索引(index);依賴於該表的存儲過程/函數將被保留,但其狀態會變爲:invalid。

(7) delete語句爲DML(data maintain Language),這個操做會被放到 rollback segment中,事務提交後才生效。若是有相應的 tigger,執行的時候將被觸發。

(8) truncate、drop是DLL(data define language),操做當即生效,原數據不放到 rollback segment中,不能回滾。

(9) 在沒有備份狀況下,謹慎使用 drop 與 truncate。要刪除部分數據行採用delete且注意結合where來約束影響範圍。回滾段要足夠大。要刪除表用drop;若想保留表而將表中數據刪除,若是於事務無關,用truncate便可實現。若是和事務有關,或老師想觸發trigger,仍是用delete。

(10) Truncate table 表名 速度快,並且效率高,由於:?truncate table 在功能上與不帶 WHERE 子句的 DELETE 語句相同:兩者均刪除表中的所有行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系統和事務日誌資源少。DELETE 語句每次刪除一行,並在事務日誌中爲所刪除的每行記錄一項。TRUNCATE TABLE 經過釋放存儲表數據所用的數據頁來刪除數據,而且只在事務日誌中記錄頁的釋放。

(11) TRUNCATE TABLE 刪除表中的全部行,但表結構及其列、約束、索引等保持不變。新行標識所用的計數值重置爲該列的種子。若是想保留標識計數值,請改用 DELETE。若是要刪除表定義及其數據,請使用 DROP TABLE 語句。

(12) 對於由 FOREIGN KEY 約束引用的表,不能使用 TRUNCATE TABLE,而應使用不帶 WHERE 子句的 DELETE 語句。因爲 TRUNCATE TABLE 不記錄在日誌中,因此它不能激活觸發器。

10.什麼是臨時表,臨時表何時刪除?

臨時表能夠手動刪除:
DROP TEMPORARY TABLE IF EXISTS temp_tb;

臨時表只在當前鏈接可見,當關閉鏈接時,MySQL會自動刪除表並釋放全部空間。所以在不一樣的鏈接中能夠建立同名的臨時表,而且操做屬於本鏈接的臨時表。
建立臨時表的語法與建立表語法相似,不一樣之處是增長關鍵字TEMPORARY,

如:

CREATE TEMPORARY TABLE tmp_table (

NAME VARCHAR (10) NOT NULL,

time date NOT NULL
);

select * from tmp_table;

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

非關係型數據庫的優點:

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

關係型數據庫的優點:

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

其餘:

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

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

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

12.數據庫範式,根據某個場景設計數據表?

第一範式:(確保每列保持原子性)全部字段值都是不可分解的原子值。

第一範式是最基本的範式。若是數據庫表中的全部字段值都是不可分解的原子值,就說明該數據庫表知足了第一範式。
第一範式的合理遵循須要根據系統的實際需求來定。好比某些數據庫系統中須要用到「地址」這個屬性,原本直接將「地址」屬性設計成一個數據庫表的字段就行。可是若是系統常常會訪問「地址」屬性中的「城市」部分,那麼就非要將「地址」這個屬性從新拆分爲省份、城市、詳細地址等多個部分進行存儲,這樣在對地址中某一部分操做的時候將很是方便。這樣設計纔算知足了數據庫的第一範式,以下表所示。
上表所示的用戶信息遵循了第一範式的要求,這樣在對用戶使用城市進行分類的時候就很是方便,也提升了數據庫的性能。

第二範式:(確保表中的每列都和主鍵相關)在一個數據庫表中,一個表中只能保存一種數據,不能夠把多種數據保存在同一張數據庫表中。

第二範式在第一範式的基礎之上更進一層。第二範式須要確保數據庫表中的每一列都和主鍵相關,而不能只與主鍵的某一部分相關(主要針對聯合主鍵而言)。也就是說在一個數據庫表中,一個表中只能保存一種數據,不能夠把多種數據保存在同一張數據庫表中。
好比要設計一個訂單信息表,由於訂單中可能會有多種商品,因此要將訂單編號和商品編號做爲數據庫表的聯合主鍵。

第三範式:(確保每列都和主鍵列直接相關,而不是間接相關) 數據表中的每一列數據都和主鍵直接相關,而不能間接相關。

第三範式須要確保數據表中的每一列數據都和主鍵直接相關,而不能間接相關。
好比在設計一個訂單數據表的時候,能夠將客戶編號做爲一個外鍵和訂單表創建相應的關係。而不能夠在訂單表中添加關於客戶其它信息(好比姓名、所屬公司等)的字段。

BCNF:符合3NF,而且,主屬性不依賴於主屬性。

若關係模式屬於第二範式,且每一個屬性都不傳遞依賴於鍵碼,則R屬於BC範式。
一般BC範式的條件有多種等價的表述:每一個非平凡依賴的左邊必須包含鍵碼;每一個決定因素必須包含鍵碼。
BC範式既檢查非主屬性,又檢查主屬性。當只檢查非主屬性時,就成了第三範式。知足BC範式的關係都必然知足第三範式。
還能夠這麼說:若一個關係達到了第三範式,而且它只有一個候選碼,或者它的每一個候選碼都是單屬性,則該關係天然達到BC範式。
通常,一個數據庫設計符合3NF或BCNF就能夠了。

第四範式:要求把同一表內的多對多關係刪除。

第五範式:從最終結構從新創建原始結構。

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

內鏈接: 只鏈接匹配的行

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

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

例如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

注意:

不少公司都只是考察是否知道其概念,可是也有不少公司須要不只僅知道概念,還須要動手寫sql,通常都是簡單的鏈接查詢,具體關於鏈接查詢的sql練習,參見如下連接:

牛客網數據庫SQL實戰

leetcode中文網站數據庫練習

個人另外一篇文章,經常使用sql練習50題

14.varchar和char的使用場景?

1.char的長度是不可變的,而varchar的長度是可變的。

定義一個char[10]和varchar[10]。
若是存進去的是‘csdn’,那麼char所佔的長度依然爲10,除了字符‘csdn’外,後面跟六個空格,varchar就立馬把長度變爲4了,取數據的時候,char類型的要用trim()去掉多餘的空格,而varchar是不須要的。

2.char的存取數度仍是要比varchar要快得多,由於其長度固定,方便程序的存儲與查找。
char也爲此付出的是空間的代價,由於其長度固定,因此不免會有多餘的空格佔位符佔據空間,可謂是以空間換取時間效率。
varchar是以空間效率爲首位。

3.char的存儲方式是:對英文字符(ASCII)佔用1個字節,對一個漢字佔用兩個字節。
varchar的存儲方式是:對每一個英文字符佔用2個字節,漢字也佔用2個字節。

4.二者的存儲數據都非unicode的字符數據。

15.SQL語言分類

SQL語言共分爲四大類:

  • 數據查詢語言DQL
  • 數據操縱語言DML
  • 數據定義語言DDL
  • 數據控制語言DCL。

1. 數據查詢語言DQL

數據查詢語言DQL基本結構是由SELECT子句,FROM子句,WHERE子句組成的查詢塊:

SELECT
FROM
WHERE

2 .數據操縱語言DML

數據操縱語言DML主要有三種形式:

1) 插入:INSERT

2) 更新:UPDATE

3) 刪除:DELETE

3. 數據定義語言DDL

數據定義語言DDL用來建立數據庫中的各類對象-----表、視圖、索引、同義詞、聚簇等如:
CREATE TABLE/VIEW/INDEX/SYN/CLUSTER

表 視圖 索引 同義詞 簇

DDL操做是隱性提交的!不能rollback

4. 數據控制語言DCL

數據控制語言DCL用來授予或回收訪問數據庫的某種特權,並控制數據庫操縱事務發生的時間及效果,對數據庫實行監視等。如:

1) GRANT:受權。

2) ROLLBACK [WORK] TO [SAVEPOINT]:回退到某一點。回滾---ROLLBACK;回滾命令使數據庫狀態回到上次最後提交的狀態。其格式爲:
SQL>ROLLBACK;

3) COMMIT [WORK]:提交。

在數據庫的插入、刪除和修改操做時,只有當事務在提交到數據
庫時纔算完成。在事務提交前,只有操做數據庫的這我的纔能有權看
到所作的事情,別人只有在最後提交完成後才能夠看到。
提交數據有三種類型:顯式提交、隱式提交及自動提交。下面分
別說明這三種類型。

(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;

參考文章:
http://www.javashuo.com/article/p-pyaoqqco-be.html

16.like %和-的區別

通配符的分類:

%百分號通配符:表示任何字符出現任意次數(能夠是0次).

**_下劃線通配符:**表示只能匹配單個字符,不能多也不能少,就是一個字符.

like操做符: LIKE做用是指示mysql後面的搜索模式是利用通配符而不是直接相等匹配進行比較.

注意: 若是在使用like操做符時,後面的沒有使用通用匹配符效果是和=一致的,SELECT * FROM products WHERE products.prod_name like '1000';
只能匹配的結果爲1000,而不能匹配像JetPack 1000這樣的結果.

  • %通配符使用: 匹配以"yves"開頭的記錄:(包括記錄"yves") SELECT FROM products WHERE products.prod_name like 'yves%';
    匹配包含"yves"的記錄(包括記錄"yves") SELECT
    FROM products WHERE products.prod_name like '%yves%';
    匹配以"yves"結尾的記錄(包括記錄"yves",不包括記錄"yves ",也就是yves後面有空格的記錄,這裏須要注意) SELECT * FROM products WHERE products.prod_name like '%yves';

  • _通配符使用: SELECT *FROM products WHERE products.prod_name like '_yves'; 匹配結果爲: 像"yyves"這樣記錄.
    SELECT* FROM products WHERE products.prodname like 'yves_'; 匹配結果爲: 像"yvesHe"這樣的記錄.(一個下劃線只能匹配一個字符,不能多也不能少)

注意事項:

  • 注意大小寫,在使用模糊匹配時,也就是匹配文本時,mysql是可能區分大小的,也多是不區分大小寫的,這個結果是取決於用戶對MySQL的配置方式.若是是區分大小寫,那麼像YvesHe這樣記錄是不能被"yves__"這樣的匹配條件匹配的.
  • 注意尾部空格,"%yves"是不能匹配"heyves "這樣的記錄的.
  • 注意NULL,%通配符能夠匹配任意字符,可是不能匹配NULL,也就是說SELECT * FROM products WHERE products.prod_name like '%;是匹配不到products.prod_name爲NULL的的記錄.

技巧與建議:

正如所見, MySQL的通配符頗有用。但這種功能是有代價的:通配符搜索的處理通常要比前面討論的其餘搜索所花時間更長。這裏給出一些使用通配符要記住的技巧。

  • 不要過分使用通配符。若是其餘操做符能達到相同的目的,應該 使用其餘操做符。
  • 在確實須要使用通配符時,除非絕對有必要,不然不要把它們用 在搜索模式的開始處。把通配符置於搜索模式的開始處,搜索起 來是最慢的。
  • 仔細注意通配符的位置。若是放錯地方,可能不會返回想要的數.

參考博文:http://www.javashuo.com/article/p-vdofimvp-ek.html

**17.count(*)、count(1)、count(column)的區別**

  • count(*)對行的數目進行計算,包含NULL

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

  • count()還有一種使用方式,count(1)這個用法和count(*)的結果是同樣的。

性能問題:

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(非主鍵)同樣,掃描整個表。明顯前者更快一些。

18.最左前綴原則

多列索引:

ALTER TABLE people ADD INDEX lname_fname_age (lame,fname,age);

爲了提升搜索效率,咱們須要考慮運用多列索引,因爲索引文件以B-Tree格式保存,因此咱們不用掃描任何記錄,便可獲得最終結果。

注:在mysql中執行查詢時,只能使用一個索引,若是咱們在lname,fname,age上分別建索引,執行查詢時,只能使用一個索引,mysql會選擇一個最嚴格(得到結果集記錄數最少)的索引。

最左前綴原則:顧名思義,就是最左優先,上例中咱們建立了lname_fname_age多列索引,至關於建立了(lname)單列索引,(lname,fname)組合索引以及(lname,fname,age)組合索引。

2、索引

1.什麼是索引?

何爲索引:

數據庫索引,是數據庫管理系統中一個排序的數據結構,索引的實現一般使用B樹及其變種B+樹。

在數據以外,數據庫系統還維護着知足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就能夠在這些數據結構上實現高級查找算法。這種數據結構,就是索引。

2.索引的做用?它的優勢缺點是什麼?

索引做用:

協助快速查詢、更新數據庫表中數據。

爲表設置索引要付出代價的:

  • 一是增長了數據庫的存儲空間
  • 二是在插入和修改數據時要花費較多的時間(由於索引也要隨之變更)。

    3.索引的優缺點?

建立索引能夠大大提升系統的性能(優勢):

1.經過建立惟一性索引,能夠保證數據庫表中每一行數據的惟一性。

2.能夠大大加快數據的檢索速度,這也是建立索引的最主要的緣由。

3.能夠加速表和表之間的鏈接,特別是在實現數據的參考完整性方面特別有意義。

4.在使用分組和排序子句進行數據檢索時,一樣能夠顯著減小查詢中分組和排序的時間。

5.經過使用索引,能夠在查詢的過程當中,使用優化隱藏器,提升系統的性能。

增長索引也有許多不利的方面(缺點):

1.建立索引和維護索引要耗費時間,這種時間隨着數據量的增長而增長。

2.索引須要佔物理空間,除了數據表佔數據空間以外,每個索引還要佔必定的物理空間,若是要創建聚簇索引,那麼須要的空間就會更大。

3.當對錶中的數據進行增長、刪除和修改的時候,索引也要動態的維護,這樣就下降了數據的維護速度。

4.哪些列適合創建索引、哪些不適合建索引?

索引是創建在數據庫表中的某些列的上面。在建立索引的時候,應該考慮在哪些列上能夠建立索引,在哪些列上不能建立索引。

通常來講,應該在這些列上建立索引:

(1)在常常須要搜索的列上,能夠加快搜索的速度;

(2)在做爲主鍵的列上,強制該列的惟一性和組織表中數據的排列結構;

(3)在常常用在鏈接的列上,這些列主要是一些外鍵,能夠加快鏈接的速度;

(4)在常常須要根據範圍進行搜索的列上建立索引,由於索引已經排序,其指定的範圍是連續的;

(5)在常常須要排序的列上建立索引,由於索引已經排序,這樣查詢能夠利用索引的排序,加快排序查詢時間;

(6)在常用在WHERE子句中的列上面建立索引,加快條件的判斷速度。

對於有些列不該該建立索引:

(1)對於那些在查詢中不多使用或者參考的列不該該建立索引。

這是由於,既然這些列不多使用到,所以有索引或者無索引,並不能提升查詢速度。相反,因爲增長了索引,反而下降了系統的維護速度和增大了空間需求。

(2)對於那些只有不多數據值的列也不該該增長索引。

這是由於,因爲這些列的取值不多,例如人事表的性別列,在查詢的結果中,結果集的數據行佔了表中數據行的很大比例,即須要在表中搜索的數據行的比例很大。增長索引,並不能明顯加快檢索速度。

(3)對於那些定義爲text, image和bit數據類型的列不該該增長索引。

這是由於,這些列的數據量要麼至關大,要麼取值不多。

(4)當修改性能遠遠大於檢索性能時,不該該建立索引。

這是由於,修改性能和檢索性能是互相矛盾的。當增長索引時,會提升檢索性能,可是會下降修改性能。當減小索引時,會提升修改性能,下降檢索性能。所以,當修改性能遠遠大於檢索性能時,不該該建立索引。

5.什麼樣的字段適合建索引

惟1、不爲空、常常被查詢的字段

6.MySQL B+Tree索引和Hash索引的區別?

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

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

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

爲何不都用Hash索引而使用B+樹索引?

  1. Hash索引僅僅能知足"=","IN"和""查詢,不能使用範圍查詢,由於通過相應的Hash算法處理以後的Hash值的大小關係,並不能保證和Hash運算前徹底同樣;

  2. Hash索引沒法被用來避免數據的排序操做,由於Hash值的大小關係並不必定和Hash運算前的鍵值徹底同樣;

  3. Hash索引不能利用部分索引鍵查詢,對於組合索引,Hash索引在計算Hash值的時候是組合索引鍵合併後再一塊兒計算Hash值,而不是單獨計算Hash值,因此經過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash索引也沒法被利用;

  4. Hash索引在任什麼時候候都不能避免表掃描,因爲不一樣索引鍵存在相同Hash值,因此即便取知足某個Hash鍵值的數據的記錄條數,也沒法從Hash索引中直接完成查詢,仍是要回表查詢數據;

  5. Hash索引遇到大量Hash值相等的狀況後性能並不必定就會比B+樹索引高。

補充:

1.MySQL中,只有HEAP/MEMORY引擎才顯示支持Hash索引。

2.經常使用的InnoDB引擎中默認使用的是B+樹索引,它會實時監控表上索引的使用狀況,若是認爲創建哈希索引能夠提升查詢效率,則自動在內存中的「自適應哈希索引緩衝區」創建哈希索引(在InnoDB中默認開啓自適應哈希索引),經過觀察搜索模式,MySQL會利用index key的前綴創建哈希索引,若是一個表幾乎大部分都在緩衝池中,那麼創建一個哈希索引可以加快等值查詢。
B+樹索引和哈希索引的明顯區別是:

3.若是是等值查詢,那麼哈希索引明顯有絕對優點,由於只須要通過一次算法便可找到相應的鍵值;固然了,這個前提是,鍵值都是惟一的。若是鍵值不是惟一的,就須要先找到該鍵所在位置,而後再根據鏈表日後掃描,直到找到相應的數據;

4.若是是範圍查詢檢索,這時候哈希索引就毫無用武之地了,由於原先是有序的鍵值,通過哈希算法後,有可能變成不連續的了,就沒辦法再利用索引完成範圍查詢檢索;
同理,哈希索引沒辦法利用索引完成排序,以及like ‘xxx%’ 這樣的部分模糊查詢(這種部分模糊查詢,其實本質上也是範圍查詢);

5.哈希索引也不支持多列聯合索引的最左匹配規則;

6.B+樹索引的關鍵字檢索效率比較平均,不像B樹那樣波動幅度大,在有大量重複鍵值狀況下,哈希索引的效率也是極低的,由於存在所謂的哈希碰撞問題。

7.在大多數場景下,都會有範圍查詢、排序、分組等查詢特徵,用B+樹索引就能夠了。

7.B樹和B+樹的區別

  1. B樹,每一個節點都存儲key和data,全部節點組成這棵樹,而且葉子節點指針爲nul,葉子結點不包含任何關鍵字信息。
  2. B+樹,全部的葉子結點中包含了所有關鍵字的信息,及指向含有這些關鍵字記錄的指針,且葉子結點自己依關鍵字的大小自小而大的順序連接,全部的非終端結點能夠當作是索引部分,結點中僅含有其子樹根結點中最大(或最小)關鍵字。 (而B 樹的非終節點也包含須要查找的有效信息)

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

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

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

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

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

9.彙集索引和非彙集索引區別?

聚合索引(clustered index):

彙集索引表記錄的排列順序和索引的排列順序一致,因此查詢效率快,只要找到第一個索引值記錄,其他就連續性的記錄在物理也同樣連續存放。彙集索引對應的缺點就是修改慢,由於爲了保證表中記錄的物理和索引順序一致,在記錄插入的時候,會對數據頁從新排序。
彙集索引相似於新華字典中用拼音去查找漢字,拼音檢索表於書記順序都是按照a~z排列的,就像相同的邏輯順序於物理順序同樣,當你須要查找a,ai兩個讀音的字,或是想一次尋找多個傻(sha)的同音字時,也許向後翻幾頁,或緊接着下一行就獲得結果了。

非聚合索引(nonclustered index):

非彙集索引指定了表中記錄的邏輯順序,可是記錄的物理和索引不必定一致,兩種索引都採用B+樹結構,非彙集索引的葉子層並不和實際數據頁相重疊,而採用葉子層包含一個指向表中的記錄在數據頁中的指針方式。非彙集索引層次多,不會形成數據重排。
非彙集索引相似在新華字典上經過偏旁部首來查詢漢字,檢索表也許是按照橫、豎、撇來排列的,可是因爲正文中是a~z的拼音順序,因此就相似於邏輯地址於物理地址的不對應。同時適用的狀況就在於分組,大數目的不一樣值,頻繁更新的列中,這些狀況即不適合彙集索引。

根本區別:

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

3、事務

1.什麼是事務?

事務是對數據庫中一系列操做進行統一的回滾或者提交的操做,主要用來保證數據的完整性和一致性。

2.事務四大特性(ACID)原子性、一致性、隔離性、持久性?

原子性(Atomicity):
原子性是指事務包含的全部操做要麼所有成功,要麼所有失敗回滾,所以事務的操做若是成功就必需要徹底應用到數據庫,若是操做失敗則不能對數據庫有任何影響。

一致性(Consistency):
事務開始前和結束後,數據庫的完整性約束沒有被破壞。好比A向B轉帳,不可能A扣了錢,B卻沒收到。

隔離性(Isolation):
隔離性是當多個用戶併發訪問數據庫時,好比操做同一張表時,數據庫爲每個用戶開啓的事務,不能被其餘事務的操做所幹擾,多個併發事務之間要相互隔離。同一時間,只容許一個事務請求同一數據,不一樣的事務之間彼此沒有任何干擾。好比A正在從一張銀行卡中取錢,在A取錢的過程結束前,B不能向這張卡轉帳。

持久性(Durability):
持久性是指一個事務一旦被提交了,那麼對數據庫中的數據的改變就是永久性的,即使是在數據庫系統遇到故障的狀況下也不會丟失提交事務的操做。

3.事務的併發?事務隔離級別,每一個級別會引起什麼問題,MySQL默認是哪一個級別?

從理論上來講, 事務應該彼此徹底隔離, 以免併發事務所致使的問題,然而, 那樣會對性能產生極大的影響, 由於事務必須按順序運行, 在實際開發中, 爲了提高性能, 事務會以較低的隔離級別運行, 事務的隔離級別能夠經過隔離事務屬性指定。
事務的併發問題

一、髒讀:事務A讀取了事務B更新的數據,而後B回滾操做,那麼A讀取到的數據是髒數據

二、不可重複讀:事務 A 屢次讀取同一數據,事務 B 在事務A屢次讀取的過程當中,對數據做了更新並提交,致使事務A屢次讀取同一數據時,結果所以本事務前後兩次讀到的數據結果會不一致。

三、幻讀:幻讀解決了不重複讀,保證了同一個事務裏,查詢的結果都是事務開始時的狀態(一致性)。

例如:事務T1對一個表中全部的行的某個數據項作了從「1」修改成「2」的操做 這時事務T2又對這個表中插入了一行數據項,而這個數據項的數值仍是爲「1」而且提交給數據庫。 而操做事務T1的用戶若是再查看剛剛修改的數據,會發現還有跟沒有修改同樣,其實這行是從事務T2中添加的,就好像產生幻覺同樣,這就是發生了幻讀。
小結:不可重複讀的和幻讀很容易混淆,不可重複讀側重於修改,幻讀側重於新增或刪除。解決不可重複讀的問題只需鎖住知足條件的行,解決幻讀須要鎖表。

事務的隔離級別

讀未提交:另外一個事務修改了數據,但還沒有提交,而本事務中的SELECT會讀到這些未被提交的數據髒讀

不可重複讀:事務 A 屢次讀取同一數據,事務 B 在事務A屢次讀取的過程當中,對數據做了更新並提交,致使事務A屢次讀取同一數據時,結果所以本事務前後兩次讀到的數據結果會不一致。

可重複讀:在同一個事務裏,SELECT的結果是事務開始時時間點的狀態,所以,一樣的SELECT操做讀到的結果會是一致的。可是,會有幻讀現象

串行化:最高的隔離級別,在這個隔離級別下,不會產生任何異常。併發的事務,就像事務是在一個個按照順序執行同樣

特別注意:

MySQL默認的事務隔離級別爲repeatable-read

MySQL 支持 4 中事務隔離級別.

事務的隔離級別要獲得底層數據庫引擎的支持, 而不是應用程序或者框架的支持.

Oracle 支持的 2 種事務隔離級別:READ_COMMITED , SERIALIZABLE

SQL規範所規定的標準,不一樣的數據庫具體的實現可能會有些差別

MySQL中默認事務隔離級別是「可重複讀」時並不會鎖住讀取到的行

事務隔離級別:未提交讀時,寫數據只會鎖住相應的行。

事務隔離級別爲:可重複讀時,寫數據會鎖住整張表。

事務隔離級別爲:串行化時,讀寫數據都會鎖住整張表。

隔離級別越高,越能保證數據的完整性和一致性,可是對併發性能的影響也越大,魚和熊掌不可兼得啊。對於多數應用程序,能夠優先考慮把數據庫系統的隔離級別設爲Read Committed,它可以避免髒讀取,並且具備較好的併發性能。儘管它會致使不可重複讀、幻讀這些併發問題,在可能出現這類問題的個別場合,能夠由應用程序採用悲觀鎖或樂觀鎖來控制。

4.事務傳播行爲

1.PROPAGATION_REQUIRED:若是當前沒有事務,就建立一個新事務,若是當前存在事務,就加入該事務,該設置是最經常使用的設置。

2.PROPAGATION_SUPPORTS:支持當前事務,若是當前存在事務,就加入該事務,若是當前不存在事務,就以非事務執行。

3.PROPAGATION_MANDATORY:支持當前事務,若是當前存在事務,就加入該事務,若是當前不存在事務,就拋出異常。

4.PROPAGATION_REQUIRES_NEW:建立新事務,不管當前存不存在事務,都建立新事務。

5.PROPAGATION_NOT_SUPPORTED:以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。

6.PROPAGATION_NEVER:以非事務方式執行,若是當前存在事務,則拋出異常。

7.PROPAGATION_NESTED:若是當前存在事務,則在嵌套事務內執行。若是當前沒有事務,則執行與PROPAGATION_REQUIRED相似的操做。

5.嵌套事務

什麼是嵌套事務?

嵌套是子事務套在父事務中執行,子事務是父事務的一部分,在進入子事務以前,父事務創建一個回滾點,叫save point,而後執行子事務,這個子事務的執行也算是父事務的一部分,而後子事務執行結束,父事務繼續執行。重點就在於那個save point。看幾個問題就明瞭了:

若是子事務回滾,會發生什麼?

父事務會回滾到進入子事務前創建的save point,而後嘗試其餘的事務或者其餘的業務邏輯,父事務以前的操做不會受到影響,更不會自動回滾。

若是父事務回滾,會發生什麼?

父事務回滾,子事務也會跟着回滾!爲何呢,由於父事務結束以前,子事務是不會提交的,咱們說子事務是父事務的一部分,正是這個道理。那麼:

事務的提交,是什麼狀況?

是父事務先提交,而後子事務提交,仍是子事務先提交,父事務再提交?答案是第二種狀況,仍是那句話,子事務是父事務的一部分,由父事務統一提交。

參考文章:http://www.javashuo.com/article/p-wzkmhkgi-dd.html

4、存儲引擎

1.MySQL常見的三種存儲引擎(InnoDB、MyISAM、MEMORY)的區別?

兩種存儲引擎的大體區別表如今:

1.InnoDB支持事務,MyISAM不支持, 這一點是很是之重要。事務是一種高級的處理方式,如在一些列增刪改中只要哪一個出錯還能夠回滾還原,而MyISAM就不能夠了。

2.MyISAM適合查詢以及插入爲主的應用。

3.InnoDB適合頻繁修改以及涉及到安全性較高的應用。

4.InnoDB支持外鍵,MyISAM不支持。

5.從MySQL5.5.5之後,InnoDB是默認引擎。

6.InnoDB不支持FULLTEXT類型的索引。

7.InnoDB中不保存表的行數,如select count() from table時,InnoDB須要掃描一遍整個表來計算有多少行,可是MyISAM只要簡單的讀出保存好的行數便可。注意的是,當count()語句包含where條件時MyISAM也須要掃描整個表。

8.對於自增加的字段,InnoDB中必須包含只有該字段的索引,可是在MyISAM表中能夠和其餘字段一塊兒創建聯合索引。

9.DELETE FROM table時,InnoDB不會從新創建表,而是一行一行的 刪除,效率很是慢。MyISAM則會重建表。

10.InnoDB支持行鎖(某些狀況下仍是鎖整表,如 update table set a=1 where user like '%lee%'。

2.MySQL存儲引擎MyISAM與InnoDB如何選擇

MySQL有多種存儲引擎,每種存儲引擎有各自的優缺點,能夠擇優選擇使用:MyISAM、InnoDB、MERGE、MEMORY(HEAP)、BDB(BerkeleyDB)、EXAMPLE、FEDERATED、ARCHIVE、CSV、BLACKHOLE。

雖然MySQL裏的存儲引擎不僅是MyISAM與InnoDB這兩個,但經常使用的就是兩個。
關於MySQL數據庫提供的兩種存儲引擎,MyISAM與InnoDB選擇使用:

  • 1.INNODB會支持一些關係數據庫的高級功能,如事務功能和行級鎖,MyISAM不支持。
  • 2.MyISAM的性能更優,佔用的存儲空間少,因此,選擇何種存儲引擎,視具體應用而定。

若是你的應用程序必定要使用事務,毫無疑問你要選擇INNODB引擎。但要注意,INNODB的行級鎖是有條件的。在where條件沒有使用主鍵時,照樣會鎖全表。好比DELETE FROM mytable這樣的刪除語句。

若是你的應用程序對查詢性能要求較高,就要使用MyISAM了。MyISAM索引和數據是分開的,並且其索引是壓縮的,能夠更好地利用內存。因此它的查詢性能明顯優於INNODB。壓縮後的索引也能節約一些磁盤空間。MyISAM擁有全文索引的功能,這能夠極大地優化LIKE查詢的效率。

有人說MyISAM只能用於小型應用,其實這只是一種偏見。若是數據量比較大,這是須要經過升級架構來解決,好比分表分庫,而不是單純地依賴存儲引擎。

如今通常都是選用innodb了,主要是MyISAM的全表鎖,讀寫串行問題,併發效率鎖表,效率低,MyISAM對於讀寫密集型應用通常是不會去選用的。
MEMORY存儲引擎

MEMORY是MySQL中一類特殊的存儲引擎。它使用存儲在內存中的內容來建立表,並且數據所有放在內存中。這些特性與前面的兩個很不一樣。
每一個基於MEMORY存儲引擎的表實際對應一個磁盤文件。該文件的文件名與表名相同,類型爲frm類型。該文件中只存儲表的結構。而其數據文件,都是存儲在內存中,這樣有利於數據的快速處理,提升整個表的效率。值得注意的是,服務器須要有足夠的內存來維持MEMORY存儲引擎的表的使用。若是不須要了,能夠釋放內存,甚至刪除不須要的表。

MEMORY默認使用哈希索引。速度比使用B型樹索引快。固然若是你想用B型樹索引,能夠在建立索引時指定。

注意,MEMORY用到的不多,由於它是把數據存到內存中,若是內存出現異常就會影響數據。若是重啓或者關機,全部數據都會消失。所以,基於MEMORY的表的生命週期很短,通常是一次性的。

3.MySQL的MyISAM與InnoDB兩種存儲引擎在,事務、鎖級別,各自的適用場景?

事務處理上方面

  • MyISAM:強調的是性能,每次查詢具備原子性,其執行數度比InnoDB類型更快,可是不提供事務支持。

  • InnoDB:提供事務支持事務,外部鍵等高級數據庫功能。 具備事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。

鎖級別

  • MyISAM:只支持表級鎖,用戶在操做MyISAM表時,select,update,delete,insert語句都會給表自動加鎖,若是加鎖之後的表知足insert併發的狀況下,能夠在表的尾部插入新的數據。

  • InnoDB:支持事務和行級鎖,是innodb的最大特點。行鎖大幅度提升了多用戶併發操做的新能。可是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的。

關於存儲引擎MyISAM和InnoDB的其餘參考資料以下:

MySQL存儲引擎中的MyISAM和InnoDB區別詳解

MySQL存儲引擎之MyISAM和Innodb總結性梳理

5、優化

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

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

其中select和from是必須的,其餘關鍵詞是可選的,這六個關鍵詞的執行順序 與sql語句的書寫順序並非同樣的,而是按照下面的順序來執行

from:須要從哪一個數據表檢索數據

where:過濾表中數據的條件

group by:如何將上面過濾出的數據分組

having:對上面已經分組的數據進行過濾的條件

select:查看結果集中的哪一個列,或列的計算結果

order by :按照什麼樣的順序來查看返回的數據

  • 2.from後面的表關聯,是自右向左解析 而where條件的解析順序是自下而上的。

也就是說,在寫SQL語句的時候,儘可能把數據量小的表放在最右邊來進行關聯(用小表去匹配大表),而把能篩選出小量數據的條件放在where語句的最左邊 (用小表去匹配大表)

其餘參考資源:
http://www.cnblogs.com/huminxxl/p/3149097.html

2.使用explain優化sql和索引?

對於複雜、效率低的sql語句,咱們一般是使用explain sql 來分析sql語句,這個語句能夠打印出,語句的執行。這樣方便咱們分析,進行優化

table:顯示這一行的數據是關於哪張表的

type:這是重要的列,顯示鏈接使用了何種類型。從最好到最差的鏈接類型爲const、eq_reg、ref、range、index和ALL

all:full table scan ;MySQL將遍歷全表以找到匹配的行;

index: index scan; index 和 all的區別在於index類型只遍歷索引;

range:索引範圍掃描,對索引的掃描開始於某一點,返回匹配值的行,常見與between ,等查詢;

ref:非惟一性索引掃描,返回匹配某個單獨值的全部行,常見於使用非惟一索引即惟一索引的非惟一前綴進行查找;

eq_ref:惟一性索引掃描,對於每一個索引鍵,表中只有一條記錄與之匹配,經常使用於主鍵或者惟一索引掃描;

const,system:當MySQL對某查詢某部分進行優化,並轉爲一個常量時,使用這些訪問類型。若是將主鍵置於where列表中,MySQL就能將該查詢轉化爲一個常量。

possible_keys:顯示可能應用在這張表中的索引。若是爲空,沒有可能的索引。能夠爲相關的域從WHERE語句中選擇一個合適的語句

key: 實際使用的索引。若是爲NULL,則沒有使用索引。不多的狀況下,MySQL會選擇優化不足的索引。這種狀況下,能夠在SELECT語句中使用USE INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MySQL忽略索引

key_len:使用的索引的長度。在不損失精確性的狀況下,長度越短越好

ref:顯示索引的哪一列被使用了,若是可能的話,是一個常數

rows:MySQL認爲必須檢查的用來返回請求數據的行數

Extra:關於MySQL如何解析查詢的額外信息。將在表4.3中討論,但這裏能夠看到的壞的例子是Using temporary和Using filesort,意思MySQL根本不能使用索引,結果是檢索會很慢。

3.MySQL慢查詢怎麼解決?

  • slow_query_log 慢查詢開啓狀態。

  • slow_query_log_file 慢查詢日誌存放的位置(這個目錄須要MySQL的運行賬號的可寫權限,通常設置爲MySQL的數據存放目錄)。

  • long_query_time 查詢超過多少秒才記錄。

6、數據庫鎖

1.mysql都有什麼鎖,死鎖斷定原理和具體場景,死鎖怎麼解決?

MySQL有三種鎖的級別:頁級、表級、行級。

  • 表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的機率最高,併發度最低。
  • 行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的機率最低,併發度也最高。
  • 頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度通常
    什麼狀況下會形成死鎖?

什麼是死鎖?

死鎖: 是指兩個或兩個以上的進程在執行過程當中。因爭奪資源而形成的一種互相等待的現象,若無外力做用,它們都將沒法推動下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等竺的進程稱爲死鎖進程。

表級鎖不會產生死鎖.因此解決死鎖主要仍是針對於最經常使用的InnoDB。

死鎖的關鍵在於:兩個(或以上)的Session加鎖的順序不一致。

那麼對應的解決死鎖問題的關鍵就是:讓不一樣的session加鎖有次序。

死鎖的解決辦法?

1.查出的線程殺死 kill
SELECT trx_MySQL_thread_id FROM information_schema.INNODB_TRX;

2.設置鎖的超時時間
Innodb 行鎖的等待時間,單位秒。可在會話級別設置,RDS 實例該參數的默認值爲 50(秒)。

生產環境不推薦使用過大的 innodb_lock_wait_timeout參數值
該參數支持在會話級別修改,方便應用在會話級別單獨設置某些特殊操做的行鎖等待超時時間,以下:
set innodb_lock_wait_timeout=1000; —設置當前會話 Innodb 行鎖等待超時時間,單位秒。

3.指定獲取鎖的順序

2.有哪些鎖(樂觀鎖悲觀鎖),select 時怎麼加排它鎖?

悲觀鎖(Pessimistic Lock):

悲觀鎖特色:先獲取鎖,再進行業務操做。

即「悲觀」的認爲獲取鎖是很是有可能失敗的,所以要先確保獲取鎖成功再進行業務操做。一般所說的「一鎖二查三更新」即指的是使用悲觀鎖。一般來說在數據庫上的悲觀鎖須要數據庫自己提供支持,即經過經常使用的select … for update操做來實現悲觀鎖。當數據庫執行select for update時會獲取被select中的數據行的行鎖,所以其餘併發執行的select for update若是試圖選中同一行則會發生排斥(須要等待行鎖被釋放),所以達到鎖的效果。select for update獲取的行鎖會在當前事務結束時自動釋放,所以必須在事務中使用。

補充:
不一樣的數據庫對select for update的實現和支持都是有所區別的,

  • oracle支持select for update no wait,表示若是拿不到鎖馬上報錯,而不是等待,MySQL就沒有no wait這個選項。
  • MySQL還有個問題是select for update語句執行中全部掃描過的行都會被鎖上,這一點很容易形成問題。所以若是在MySQL中用悲觀鎖務必要肯定走了索引,而不是全表掃描。

樂觀鎖(Optimistic Lock):

1.樂觀鎖,也叫樂觀併發控制,它假設多用戶併發的事務在處理時不會彼此互相影響,各事務可以在不產生鎖的狀況下處理各自影響的那部分數據。在提交數據更新以前,每一個事務會先檢查在該事務讀取數據後,有沒有其餘事務又修改了該數據。若是其餘事務有更新的話,那麼當前正在提交的事務會進行回滾。

2.樂觀鎖的特色先進行業務操做,不到萬不得已不去拿鎖。即「樂觀」的認爲拿鎖多半是會成功的,所以在進行完業務操做須要實際更新數據的最後一步再去拿一下鎖就好。
樂觀鎖在數據庫上的實現徹底是邏輯的,不須要數據庫提供特殊的支持。

3.通常的作法是在須要鎖的數據上增長一個版本號,或者時間戳

實現方式舉例以下:

樂觀鎖(給表加一個版本號字段) 這個並非樂觀鎖的定義,給表加版本號,是數據庫實現樂觀鎖的一種方式

  1. SELECT data AS old_data, version AS old_version FROM …;
  2. 根據獲取的數據進行業務操做,獲得new_data和new_version
  3. UPDATE SET data = new_data, version = new_version WHERE version = old_version

if (updated row > 0) {

// 樂觀鎖獲取成功,操做完成

} else {

// 樂觀鎖獲取失敗,回滾並重試

}

注意:

  • 樂觀鎖在不發生取鎖失敗的狀況下開銷比悲觀鎖小,可是一旦發生失敗回滾開銷則比較大,所以適合用在取鎖失敗機率比較小的場景,能夠提高系統併發性能
  • 樂觀鎖還適用於一些比較特殊的場景,例如在業務操做過程當中沒法和數據庫保持鏈接等悲觀鎖沒法適用的地方。

總結:
悲觀鎖和樂觀鎖是數據庫用來保證數據併發安全防止更新丟失的兩種方法,例子在select ... for update前加個事務就能夠防止更新丟失。悲觀鎖和樂觀鎖大部分場景下差別不大,一些獨特場景下有一些差異,通常咱們能夠從以下幾個方面來判斷。

  • 響應速度: 若是須要很是高的響應速度,建議採用樂觀鎖方案,成功就執行,不成功就失敗,不須要等待其餘併發去釋放鎖。'

  • 衝突頻率: 若是衝突頻率很是高,建議採用悲觀鎖,保證成功率,若是衝突頻率大,樂觀鎖會須要屢次重試才能成功,代價比較大。

  • 重試代價: 若是重試代價大,建議採用悲觀鎖。

7、其餘

1.數據庫的主從複製

主從複製的幾種方式:

同步複製:

所謂的同步複製,意思是master的變化,必須等待slave-1,slave-2,...,slave-n完成後才能返回。 這樣,顯然不可取,也不是MySQL複製的默認設置。好比,在WEB前端頁面上,用戶增長了條記錄,須要等待很長時間。

異步複製:

如同AJAX請求同樣。master只須要完成本身的數據庫操做便可。至於slaves是否收到二進制日誌,是否完成操做,不用關心,MySQL的默認設置。

半同步複製:

master只保證slaves中的一個操做成功,就返回,其餘slave無論。 這個功能,是由google爲MySQL引入的。

2.數據庫主從複製分析的 7 個問題?

問題1:master的寫操做,slaves被動的進行同樣的操做,保持數據一致性,那麼slave是否能夠主動的進行寫操做?

假設slave能夠主動的進行寫操做,slave又沒法通知master,這樣就致使了master和slave數據不一致了。所以slave不該該進行寫操做,至少是slave上涉及到複製的數據庫不能夠寫。實際上,這裏已經揭示了讀寫分離的概念。

問題2:主從複製中,能夠有N個slave,但是這些slave又不能進行寫操做,要他們幹嗎?

實現數據備份:
相似於高可用的功能,一旦master掛了,可讓slave頂上去,同時slave提高爲master。

異地容災:好比master在北京,地震掛了,那麼在上海的slave還能夠繼續。
主要用於實現scale out,分擔負載,能夠將讀的任務分散到slaves上。
【極可能的狀況是,一個系統的讀操做遠遠多於寫操做,所以寫操做發向master,讀操做發向slaves進行操做】

問題3:主從複製中有master,slave1,slave2,...等等這麼多MySQL數據庫,那好比一個JAVA WEB應用到底應該鏈接哪一個數據庫?

咱們在應用程序中能夠這樣,insert/delete/update這些更新數據庫的操做,用connection(for master)進行操做,

select用connection(for slaves)進行操做。那咱們的應用程序還要完成怎麼從slaves選擇一個來執行select,例如使用簡單的輪循算法。

這樣的話,至關於應用程序完成了SQL語句的路由,並且與MySQL的主從複製架構很是關聯,一旦master掛了,某些slave掛了,那麼應用程序就要修改了。能不能讓應用程序與MySQL的主從複製架構沒有什麼太多關係呢?
找一個組件,application program只須要與它打交道,用它來完成MySQL的代理,實現SQL語句的路由。
MySQL proxy並不負責,怎麼從衆多的slaves挑一個?能夠交給另外一個組件(好比haproxy)來完成。

這就是所謂的MySQL READ WRITE SPLITE,MySQL的讀寫分離。

問題4:若是MySQL proxy , direct , master他們中的某些掛了怎麼辦?

總統通常都會弄個副總統,以防不測。一樣的,能夠給這些關鍵的節點來個備份。

問題5:當master的二進制日誌每產生一個事件,都須要發往slave,若是咱們有N個slave,那是發N次,仍是隻發一次?若是隻發一次,發給了slave-1,那slave-2,slave-3,...它們怎麼辦?

顯 然,應該發N次。實際上,在MySQL master內部,維護N個線程,每個線程負責將二進制日誌文件發往對應的slave。master既要負責寫操做,還的維護N個線程,負擔會很重。能夠這樣,slave-1是master的從,slave-1又是slave-2,slave-3,...的主,同時slave-1再也不負責select。 slave-1將master的複製線程的負擔,轉移到本身的身上。這就是所謂的多級複製的概念。

問題6:當一個select發往MySQL proxy,可能此次由slave-2響應,下次由slave-3響應,這樣的話,就沒法利用查詢緩存了。

應該找一個共享式的緩存,好比memcache來解決。將slave-2,slave-3,...這些查詢的結果都緩存至mamcache中。

問題7:隨着應用的日益增加,讀操做不少,咱們能夠擴展slave,可是若是master知足不了寫操做了,怎麼辦呢?

scale on ?更好的服務器? 沒有最好的,只有更好的,太貴了。。。
scale out ? 主從複製架構已經知足不了。
能夠分庫【垂直拆分】,分表【水平拆分】。

3.mysql 高併發環境解決方案?

MySQL 高併發環境解決方案: 分庫 分表 分佈式 增長二級緩存。。。。。

需求分析:互聯網單位 天天大量數據讀取,寫入,併發性高。

現有解決方式:水平分庫分表,由單點分佈到多點數據庫中,從而下降單點數據庫壓力。

集羣方案:解決DB宕機帶來的單點DB不能訪問問題。

讀寫分離策略:極大限度提升了應用中Read數據的速度和併發量。沒法解決高寫入壓力。

4.數據庫崩潰時事務的恢復機制(REDO日誌和UNDO日誌)?

轉載:MySQL REDO日誌和UNDO日誌

Undo Log:

Undo Log是爲了實現事務的原子性,在MySQL數據庫InnoDB存儲引擎中,還用了Undo Log來實現多版本併發控制(簡稱:MVCC)。

事務的原子性(Atomicity)事務中的全部操做,要麼所有完成,要麼不作任何操做,不能只作部分操做。若是在執行的過程當中發生了錯誤,要回滾(Rollback)到事務開始前的狀態,就像這個事務歷來沒有執行過。
原理Undo Log的原理很簡單,爲了知足事務的原子性,在操做任何數據以前,首先將數據備份到一個地方(這個存儲數據備份的地方稱爲UndoLog)。而後進行數據的修改。若是出現了錯誤或者用戶執行了ROLLBACK語句,系統能夠利用Undo Log中的備份將數據恢復到事務開始以前的狀態。

之因此能同時保證原子性和持久化,是由於如下特色:

更新數據前記錄Undo log。
爲了保證持久性,必須將數據在事務提交前寫到磁盤。只要事務成功提交,數據必然已經持久化。
Undo log必須先於數據持久化到磁盤。若是在G,H之間系統崩潰,undo log是完整的, 能夠用來回滾事務。
若是在A-F之間系統崩潰,由於數據沒有持久化到磁盤。因此磁盤上的數據仍是保持在事務開始前的狀態。

缺陷:每一個事務提交前將數據和Undo Log寫入磁盤,這樣會致使大量的磁盤IO,所以性能很低。
若是可以將數據緩存一段時間,就能減小IO提升性能。可是這樣就會喪失事務的持久性。所以引入了另一種機制來實現持久化,即Redo Log。

Redo Log:

原理和Undo Log相反,Redo Log記錄的是新數據的備份。在事務提交前,只要將Redo Log持久化便可,不須要將數據持久化。當系統崩潰時,雖然數據沒有持久化,可是Redo Log已經持久化。系統能夠根據Redo Log的內容,將全部數據恢復到最新的狀態。

8、整理時參考的資料

java團長 數據庫整理

20個數據庫常見面試題講解 - 鵬磊 - 開源中國"

34個數據庫常見面試題講解

漫談數據庫索引知識庫博客園

Mysql| 使用通配符進行模糊查詢(like,%,_)

MySQL存儲引擎中的MyISAM和InnoDB區別詳解

MySQL存儲引擎之MyISAM和Innodb總結性梳理

http://www.javashuo.com/article/p-wzkmhkgi-dd.html

相關文章
相關標籤/搜索