MySQL小結

1 列舉常見的關係型數據庫和非關係型都有哪些?

1.1 關係型數據庫(須要有表結構)

表和表、表和字段、數據和數據存在着關係。經常使用的有MySQL、oracle、SQL server、db二、sybase等html

優勢:

  • 易於維護:都是使用表結構,格式一致;
  • 使用方便:SQL語言通用,可用於複雜查詢;
  • 複雜操做:支持SQL。可用一個表以及多個表之間很是複雜的查詢。

缺點:

  • 讀寫性能比較差,尤爲是海量數據的高效率讀寫;
  • 固定的表結構,靈活度稍欠;
  • 高併發讀寫需求,對傳統關係型數據庫來講,硬盤I/O是一個很大的麻煩

1.2 非關係數據庫

嚴格上不是一種數據庫,應該是一種數據結構化存儲方法的集合,能夠是文檔或者鍵值對等。java

優勢:

  • 格式靈活:存儲數據的格式能夠是key:value形式、文檔形式、圖片形式等等,使用靈活,應用場景普遍,而關係型數據庫則只支持基礎類型;
  • 速度快:nosql可使用硬盤或者隨機存儲器做爲載體,而關係數據庫只能使用硬盤;
  • 高擴展性;
  • 成本低:nosql數據庫部署簡單,基本都是開源軟件。

缺點:

  • 不提供SQL支持,學習和使用成本較高;
  • 無事務處理;
  • 數據結構相對複雜,複雜查詢方面稍欠。

非關係型數據庫的分類比較:

  • 文檔型 mysql

  • key-value型 面試

  • 列式數據庫 redis

  • 圖形數據庫 算法

2 什麼是數據庫,數據庫管理系統,數據庫系統,數據庫管理員?

  • 數據庫:數據庫(DataBase簡稱DB)就是信息的集合或者說數據庫是由數據庫管理系統管理的數據的集合。
  • 數據庫管理系統 : 數據庫管理系統(Database Management System 簡稱DBMS)是一種操縱和管理數據庫的大型軟件,一般用語用於創建、使用和維護數據庫。
  • 數據庫系統 : 數據庫系統(Data Base System,簡稱DBS)一般由軟件、數據庫和數據管理員(DBA)組成。
  • 數據庫管理員 : 數據庫管理員(Database Administrator,簡稱DBA)負責全面管理和控制數據庫系統。 數據庫系統基本構成以下圖所示:

3 什麼是元組,碼,候選碼,主碼,外碼,主屬性,非主屬性?

  • 元組 : 元組(tuple)是關係數據庫中的基本概念,關係是一張表,表中的每行(即數據庫中的每條記錄)就是一個元組,每列就是一個屬性。 在二維表裏,元組也稱爲行。 碼 :碼就是能惟一標識實體的屬性,對應表中的列。
  • 候選碼 : 若關係中的某一屬性或屬性組的值能惟一的標識一個元組,而其任何、子集都不能再標識,則稱該屬性組爲候選碼。例如:在學生實體中,「學號」是能惟一的區分學生實體的,同時又假設「姓名」、「班級」的屬性組合足以區分學生實體,那麼{學號}和{姓名,班級}都是候選碼。
  • 主碼 : 主碼也叫主鍵。主碼是從候選碼中選出來的。 一個實體集中只能有一個主碼,但能夠有多個候選碼。
  • 外碼 : 外碼也叫外鍵。若是一個關係中的一個屬性是另一個關係中的主碼則這個屬性爲外碼。
  • 主屬性 : 候選碼中出現過的屬性稱爲主屬性。好比關係 工人(工號,身份證號,姓名,性別,部門).顯然工號和身份證號都可以惟一標示這個關係,因此都是候選碼。工號、身份證號這兩個屬性就是主屬性。若是主碼是一個屬性組,那麼屬性組中的屬性都是主屬性。
  • 非主屬性: 不包含在任何一個候選碼中的屬性稱爲非主屬性。好比在關係——學生(學號,姓名,年齡,性別,班級)中,主碼是「學號」,那麼其餘的「姓名」、「年齡」、「性別」、「班級」就均可以稱爲非主屬性。

4 主鍵和外鍵有什麼區別?

  • 主鍵(主碼) :主鍵用於惟一標識一個元組,不能有重複,不容許爲空。一個表只能有一個主鍵。
  • 外鍵(外碼) :外鍵用來和其餘表創建聯繫用,外鍵是另外一表的主鍵,外鍵是能夠有重複的,能夠是空值。一個表能夠有多個外鍵。

5 內鏈接與外鏈接

5.1 MySQL內鏈接(inner join on)

MySQL的內鏈接使用inner join on,它的效果跟使用where是同樣的,若是聯結的是兩個表,那麼須要左右的條件或者說字段是須要徹底匹配的。sql

5.2 MySQL外鏈接(left,right)

  • 外鏈接包含左右鏈接
  • 左鏈接的結果是除了匹配條件的數據還包含左邊表中的全部數據
  • 右鏈接的結果是除了匹配條件的數據還包含右邊表中的全部數據

6 什麼是ER圖?

E-R圖也稱實體-聯繫圖(Entity Relationship Diagram),提供了表示實體類型、屬性和聯繫的方法,用來描述現實世界的概念模型。 它是描述現實世界關係概念模型的有效方法。 是表示概念關係模型的一種方式。數據庫

下圖是一個學生選課的ER圖,每一個學生能夠選若干門課程,同一門課程也能夠被若干人選擇,因此它們之間的關係是多對多(M:N)。另外,還有其餘兩種關係是:1對1(1:1)、1對多(1:N)。 django

ER圖實例

咱們試着將上面的ER圖轉換成數據庫實際的關係模型(實際設計中,咱們一般會將任課教師也做爲一個實體來處理): 編程

7 數據庫範式瞭解嗎?

7.1 一些重要的概念:

  • 函數依賴(functional dependency)

    若在一張表中,在屬性(或屬性組)X的值肯定的狀況下,一定能肯定屬性Y的值,那麼就能夠說Y函數依賴於X,寫做 X → Y。

  • 部分函數依賴(partial functional dependency)

    若是X→Y,而且存在X的一個真子集X0,使得X0→Y,則稱Y對X部分函數依賴。好比學生基本信息表R中(學號,身份證號,姓名)固然學號屬性取值是惟一的,在R關係中,(學號,身份證號)->(姓名),(學號)->(姓名),(身份證號)->(姓名);因此姓名部分函數依賴與(學號,身份證號);

  • 徹底函數依賴(Full functional dependency)

    在一個關係中,若某個非主屬性數據項依賴於所有關鍵字稱之爲徹底函數依賴。好比學生基本信息表R(學號,班級,姓名)假設不一樣的班級學號有相同的,班級內學號不能相同,在R關係中,(學號,班級)->(姓名),可是(學號)->(姓名)不成立,(班級)->(姓名)不成立,因此姓名徹底函數依賴與(學號,班級);

  • 傳遞函數依賴

    在關係模式R(U)中,設X,Y,Z是U的不一樣的屬性子集,若是X肯定Y、Y肯定Z,且有X不包含Y,Y不肯定X,(X∪Y)∩Z=空集合,則稱Z傳遞函數依賴(transitive functional dependency) 於X。傳遞函數依賴會致使數據冗餘和異常。傳遞函數依賴的Y和Z子集每每同屬於某一個事物,所以可將其合併放到一個表中。好比在關係R(學號 ,姓名, 系名,系主任)中,學號 → 系名,系名 → 系主任,因此存在非主屬性系主任對於學號的傳遞函數依賴。

7.2 1NF(第一範式)

屬性(對應於表中的字段)不能再被分割,也就是這個字段只能是一個值,不能再分爲多個其餘的字段了。1NF是全部關係型數據庫的最基本要求 ,也就是說關係型數據庫中建立的表必定知足第一範式。

7.3 2NF(第二範式)

2NF在1NF的基礎之上,消除了非主屬性對於碼的部分函數依賴。以下圖所示,展現了第一範式到第二範式的過渡。第二範式在第一範式的基礎上增長了一個列,這個列稱爲主鍵,非主屬性都依賴於主鍵。

7.4 3NF(第三範式)

3NF在2NF的基礎之上,消除了非主屬性對於碼的傳遞函數依賴 。符合3NF要求的數據庫設計,基本上解決了數據冗餘過大,插入異常,修改異常,刪除異常的問題。好比在關係R(學號 ,姓名, 系名,系主任)中,學號 → 系名,系名 → 系主任,因此存在非主屬性系主任對於學號的傳遞函數依賴,因此該表的設計,不符合3NF的要求。

7.5 總結

  • 1NF:屬性不可再分。
  • 2NF:1NF的基礎之上,消除了非主屬性對於碼的部分函數依賴。
  • 3NF:3NF在2NF的基礎之上,消除了非主屬性對於碼的傳遞函數依賴 。

8 數據庫三大特性:

  • 實體 :表
  • 屬性:表中的數據(字段)
  • 關係 :表與表之間的關係

9 數據庫五大約束:

  • primary key:設置主鍵約束;
  • UNIQUE:設置惟一性約束,不能有重複值;
  • DEFAULT:默認值約束;
  • NOT NULL:設置非空約束,該字段你能爲空;
  • FOREIGN KEY:設置外鍵約束。

10 MySQL常見的數據庫引擎及比較?

  • InnoDB 支持事務;支持表鎖、行鎖(for update) 表鎖:select * from tb for update 行鎖:select id,name from tb where id=2 for update
  • Myisam:查詢速度快;全文索引;支持表鎖;
  • NDB: 高可用、高性能、高可擴展性的數據庫集羣系統;
  • Memory:默認使用的是哈希索引;
  • BDB: 可替代InnoDB的事務引擎,支持COMMIT、ROLLBACK和其餘事務特性;
  • Merge: 容許MySQL DBA或開發人員將一系列等同的MyISAM表以邏輯方式組合在一塊兒,並做爲一個對象引用他們。對於諸如數據倉儲等VLDB環境十分適合。
  • Achive:爲大量不多引用的歷史、歸檔、或安全設計信息的存儲和檢索提供了完美的解決方案;
  • Federated:可以將多個分離的MySQL服務器鏈接起來,從多個物理服務器建立一個邏輯數據庫。十分適合於分佈式環境或數據集市環境;
  • Cluster:MySQL的簇式數據庫引擎,尤爲適合於具備高性能查找要求的應用程序,這類查找需求還要求具備更高的正常工做時間和可用性;
  • Other: 其餘存儲引擎包括CSV(引用由逗號隔開的用做數據庫表的文件),Blackhole(用於臨時禁止對數據庫的應用程序輸入),以及Example引擎(可謂快速建立定製的插件式存儲引擎提供幫助)。

InnoDB和MyisSam對比

MyISAM是MySQL的默認數據庫引擎(5.5版以前),由早期的 ISAM (Indexed Sequential Access Method:有索引的順序訪問方法)所改良。雖然性能極佳,並且提供了大量的特性,包括全文索引、壓縮、空間函數等,但MyISAM不支持事務和行級鎖,並且最大的缺陷就是崩潰後沒法安全恢復。不過,5.5版本以後,MySQL引入了InnoDB(另外一種數據庫引擎)。

大多數時候咱們使用的都是InnoDB存儲引擎,可是在某些狀況下使用 MyISAM 也是合適的好比讀密集的狀況下。(若是你不介意 MyISAM 崩潰回覆問題的話)。

二者的對比:

  • 是否支持行級鎖 : MyISAM 只有表級鎖(table-level locking),而InnoDB 支持行級鎖(row-level locking)和表級鎖,默認爲行級鎖。
  • 是否支持事務和崩潰後的安全恢復: MyISAM 強調的是性能,每次查詢具備原子性,其執行數度比InnoDB類型更快,可是不提供事務支持。可是InnoDB 提供事務支持事務,外部鍵等高級數據庫功能。 具備事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。
  • 是否支持外鍵: MyISAM不支持,而InnoDB支持。
  • 是否支持MVCC :僅 InnoDB 支持。應對高併發事務, MVCC比單純的加鎖更高效;MVCC只在 READ COMMITTED 和 REPEATABLE READ 兩個隔離級別下工做;MVCC可使用 樂觀(optimistic)鎖 和 悲觀(pessimistic)鎖來實現;各數據庫中MVCC實現並不統一。(MVCC出門左轉)

11 事務相關

事務用於將某些操做的多個SQL做爲原子性操做,一旦有某一個出現錯誤,便可滾回到原來的狀態,從而保證數據庫的數據完整性。

11.1 事務的特性:

  • 原子性(Atomicity):事務包含的全部操做要麼所有成功,要麼所有失敗回滾,所以事務的操做若是成功必須所有應用到數據庫,若是數據操做失敗則不能對數據庫有任何的影響;
  • 一致性(Consistency):是指事務必須使數據庫從一個一致性狀態變換到另外一個一致性狀態,也就是說一個事務執行以前和執行以後都必須處於一致狀態(確保數據庫正確地改變狀態後,成功提交事務);
  • 隔離性(Isolation):是當多個用戶併發訪問數據庫時,數據庫爲每個用戶開啓的事務不能被其餘事務的操做所幹擾,多個併發事務之間要相互隔離(使事務操做彼此獨立和透明的);
  • 持久性(Durability):是指一個事務一旦被提交了,那麼對數據庫中的數據的改變就是永久性的,即使是數據庫系統遇到故障的狀況下也不會丟失提交事務的操做(確保提交的事務的結果或效果的系統出現故障的狀況下仍然存在);

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

在典型的應用程序中,多個事務併發運行,常常會操做相同的數據來完成各自的任務(多個用戶對統一數據進行操做)。併發雖然是必須的,但可能會致使如下的問題。

  • 髒讀(Dirty read): 當一個事務正在訪問數據而且對數據進行了修改,而這種修改尚未提交到數據庫中,這時另一個事務也訪問了這個數據,而後使用了這個數據。由於這個數據是尚未提交的數據,那麼另一個事務讀到的這個數據是「髒數據」,依據「髒數據」所作的操做多是不正確的。
  • 丟失修改(Lost to modify): 指在一個事務讀取一個數據時,另一個事務也訪問了該數據,那麼在第一個事務中修改了這個數據後,第二個事務也修改了這個數據。這樣第一個事務內的修改結果就被丟失,所以稱爲丟失修改。 例如:事務1讀取某表中的數據A=20,事務2也讀取A=20,事務1修改A=A-1,事務2也修改A=A-1,最終結果A=19,事務1的修改被丟失。
  • 不可重複讀(Unrepeatableread): 指在一個事務內屢次讀同一數據。在這個事務尚未結束時,另外一個事務也訪問該數據。那麼,在第一個事務中的兩次讀數據之間,因爲第二個事務的修改致使第一個事務兩次讀取的數據可能不太同樣。這就發生了在一個事務內兩次讀到的數據是不同的狀況,所以稱爲不可重複讀。
  • 幻讀(Phantom read): 幻讀與不可重複讀相似。它發生在一個事務(T1)讀取了幾行數據,接着另外一個併發事務(T2)插入了一些數據時。在隨後的查詢中,第一個事務(T1)就會發現多了一些本來不存在的記錄,就好像發生了幻覺同樣,因此稱爲幻讀。

不可重複度和幻讀區別:

不可重複讀的重點是修改,幻讀的重點在於新增或者刪除。

11.3 事務隔離級別有哪些?MySQL的默認隔離級別是?

11.3.1 四個隔離級別:

  • READ-UNCOMMITTED(讀取未提交): 最低的隔離級別,容許讀取還沒有提交的數據變動,可能會致使髒讀、幻讀或不可重複讀。
  • READ-COMMITTED(讀取已提交): 容許讀取併發事務已經提交的數據,能夠阻止髒讀,可是幻讀或不可重複讀仍有可能發生。
  • REPEATABLE-READ(可重複讀): 對同一字段的屢次讀取結果都是一致的,除非數據是被自己事務本身所修改,能夠阻止髒讀和不可重複讀,但幻讀仍有可能發生。
  • SERIALIZABLE(可串行化): 最高的隔離級別,徹底服從ACID的隔離級別。全部的事務依次逐個執行,這樣事務之間就徹底不可能產生干擾,也就是說,該級別能夠防止髒讀、不可重複讀以及幻讀。
隔離級別 髒讀 不可重複讀 幻讀
READ-UNCOMMITTED(讀取未提交)
READ-COMMITTED(讀取已提交) ×
REPEATABLE-READ(可重複讀) × ×
SERIALIZABLE(可串行化) × × ×

MySQL InnoDB 存儲引擎的默認支持的隔離級別是 REPEATABLE-READ(可重讀)。咱們能夠經過SELECT @@tx_isolation;命令來查看.

11.3.2 注意

與 SQL 標準不一樣的地方在於InnoDB 存儲引擎在 REPEATABLE-READ(可重讀)事務隔離級別下使用的是Next-Key Lock 鎖算法,所以能夠避免幻讀的產生,這與其餘數據庫系統(如 SQL Server)是不一樣的。因此說InnoDB 存儲引擎的默認支持的隔離級別是 REPEATABLE-READ(可重讀)** 已經能夠徹底保證事務的隔離性要求,即達到了 SQL標準的SERIALIZABLE(可串行化)隔離級別。

由於隔離級別越低,事務請求的鎖越少,因此大部分數據庫系統的隔離級別都是READ-COMMITTED(讀取提交內容):,可是你要知道的是InnoDB 存儲引擎默認使用 REPEATABLE-READ(可重讀)並不會有任何性能損失。

InnoDB 存儲引擎在 分佈式事務 的狀況下通常會用到SERIALIZABLE(可串行化)隔離級別。

12 簡述數據庫設計中一對多和多對多的應用場景?

  • FK(一對多):下拉框裏面的數據就須要用FK關聯另外一張表; 實例:一個學生只屬於一個班每個班有多個學生
  • M2M(多對多):多選的下拉框,或者CheckBox。 實例:一個學生能夠選多門課程,一門課程也有多名學生

13 簡述觸發器、函數、視圖、存儲過程

  • 觸發器:對數據庫某張表的增長、刪除、修改先後定義一些操做;
  • 函數
    • 觸發函數:select
    • 聚合函數:max/min/sum/avg
    • 時間格式化:date_format
    • 字符串拼接:concat
    • 截取字符串:substring
    • 返回字節個數:length
  • 存儲過程:將SQL語句保存到數據庫中,並命名,之後在代碼調用時,直接調用名稱便可;
    • 參數類型:
      1. in 只將參數穿進去
      2. out 只拿結果
      3. inout 既能夠傳,也能夠取

存儲過程在互聯網公司應用很少,由於存儲過程難以調試和擴展,並且沒有移植性,還會消耗數據庫資源。

  • 函數和存儲過程區別

本質上沒區別。只是函數有如:只能返回一個變量的限制。而存儲過程能夠返回多個。而函數是能夠嵌入SQL中使用的,能夠在select中調用,而存儲過程不行。

  • 視圖:視圖是一個虛擬表,不是真實存在的(只能查,不能改)

14 MySQL索引

因爲索引的知識點太多,後期我在單獨用寫一篇博客來詳細分析。

15 如何開啓慢日誌查詢?

  • 修改配置文件
slow_query_log = OFF  # 是否開啓慢日誌記錄
long_query_time = 2   # 時間限制,超過此時間,則記錄
slow_query_log_file = /usr/slow.log  # 日誌文件
log_queries_not_using_indexes = OFF  # 未使用索引的搜索是否記錄
複製代碼
  • 下面是開啓
slow_query_log = ON
long_query_time = 2
log_queries_not_using_indexes = OFF
log_queries_not_using_indexes = ON
複製代碼
  • 注意:
查看當前配置信息:show variables like '%query%'
修改當前配置:set global 變量名 = 值
複製代碼

16 數據庫導入導出命令(結構+數據)?

  • 導出現有數據庫數據:(當有提示輸入密碼,-p就不用加密碼)
mysqldump -u用戶名 -p密碼 數據庫名稱 > 導出文件路徑  # 結構+數據
mysqldump -u用戶名 -p密碼 -d 數據庫名稱 > 導出文件 路徑 # 結構
'--no-defaults':解決"unknown option --no-beep"錯誤
複製代碼
  • 導入現有數據庫數據:
mysqldump -uroot -p密碼 數據庫名稱 < 文件路徑
或者:進入數據庫; source + 要導入數據庫文件路徑
複製代碼

17 數據庫優化方案

  • 建立數據表時把固定長度的放在前面
  • 將固定數據放入內存:

例如 choice字段(django中有用到,數字一、二、3...對應相應內容)

  • char 和 varchar 的區別(char可變,varchar不可變)
  • 聯合索引遵循最左前綴(從最左側開始檢索)
  • 避免使用select *
  • 讀寫分離
    • 實現:兩臺服務器同步數據
    • 利用數據庫的主從分離:主,用於刪除、修改、更新;從,用於查;
  • 分庫

當數據庫中的表太多,將某些表分到不一樣的數據庫,例如:1w張表時;
代價:連表查詢

  • 分表
    • 水平分表:將某些列拆分到另外一張表,例如:博客+博客詳情;
    • 垂直分表:將某些歷史信息分到另一張表中,例如:支付寶帳單
  • 加緩存

利用redis、memcache(經常使用數據放到緩存裏,提升去取數據速度)

  • 若是隻想得到一條數據 select * from tb1 where name='alex' limit 1

下面補充一下數據庫分片的兩種常見方案:

  • 客戶端代理: 分片邏輯在應用端,封裝在jar包中,經過修改或者封裝JDBC層來實現。 噹噹網的 Sharding-JDBC 、阿里的TDDL是兩種比較經常使用的實現。
  • 中間件代理: 在應用和數據中間加了一個代理層。分片邏輯統一維護在中間件服務中。 咱們如今談的 Mycat 、360的Atlas、網易的DDB等等都是這種架構的實現。

18 簡述MySQL的執行計劃

explain + SQL語句
複製代碼
  • 查看有沒有命中索引,讓數據庫幫看看運行速度快不快
  • SQL在數據庫中的表現狀況,一般用於SQL性能分析、優化等場景

19 在對name作了惟一索引的前提下,簡述如下區別:

select * from tb1 where name = '小明' select * from tb1 where name = '小明' limit 1 沒作惟一索引的話,前者查詢會全表掃描,效率低些; limit 1,只要找到對應一條數據,就不繼續往下掃描; 然而name字段添加惟一索引了,加不加limit 1,意義都不大。

20 1000w條數據,使用limit offset分頁時,爲何越日後返越慢?如何解決?

例如:

limit 100000,20;  # 從第十萬開始日後取二十條,
limit 20 offset 100000; # limit 後面是取20條數據,offset後面是從10w條數據開始讀
複製代碼

由於當一個數據表過於龐大,LIMIT offset,length中的offset值過大,則SQL查詢語句會很是緩慢

  • 優化一:先看主鍵,再分頁:
select * from tb where id in (select id from tb where limit 10 offset 30)
複製代碼
  • 優化二: 記錄當前頁,數據、ID、最大值和最小值(用於where查詢) 在翻頁時,根據條件進行篩選,篩選完畢後,再根據limit offset 查詢
select * from (select * from tb where id > 2222) as B limit 10 offset 0;
複製代碼
  • 優化三: 能夠按照當前業務需求,看是否能夠設置只容許看前200頁; 通常狀況下,沒人會咔咔看個幾十上百頁的。

21 悲觀鎖和樂觀鎖

21.1 悲觀鎖和樂觀鎖的區別?

  • 悲觀鎖

會從數據開始更改時就將數據鎖住,直到更改完成才釋放;
會形成數據庫訪問時間較長,併發性很差,特別是長事務。
傳統的關係型數據庫裏邊就用到了不少這種鎖機制,好比行鎖,表鎖等,讀鎖,寫鎖等,都是在作操做以前先上鎖。
Java中synchronized和ReentrantLock等獨佔鎖就是悲觀鎖思想的實現。

  • 樂觀鎖

直到修改完成,準備提交修改到數據庫時纔會鎖住數據,完成更改後釋放;
樂觀鎖適用於多讀的應用類型,這樣能夠提升吞吐量,像數據庫提供的相似於write_condition機制,其實都是提供的樂觀鎖。
在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實現方式CAS實現的。

21.2 兩種鎖的使用場景

從上面對兩種鎖的介紹,咱們知道兩種鎖各有優缺點,不可認爲一種好於另外一種,像樂觀鎖適用於寫比較少的狀況下(多讀場景),即衝突真的不多發生的時候,這樣能夠省去了鎖的開銷,加大了系統的整個吞吐量。但若是是多寫的狀況,通常會常常產生衝突,這就會致使上層應用會不斷的進行retry,這樣反卻是下降了性能,因此通常多寫的場景下用悲觀鎖就比較合適。

21.3 樂觀鎖常見的兩種實現方式

版本號機制

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

CAS算法

即compare and swap(比較與交換),是一種有名的無鎖算法。無鎖編程,即不使用鎖的狀況下實現多線程之間的變量同步,也就是在沒有線程被阻塞的狀況下實現變量的同步,因此也叫非阻塞同步(Non-blocking Synchronization)。CAS算法涉及到三個操做數

  • 須要讀寫的內存值 V
  • 進行比較的值 A
  • 擬寫入的新值 B

當且僅當 V 的值等於 A時,CAS經過原子方式用新值B來更新V的值,不然不會執行任何操做(比較和替換是一個原子操做)。通常狀況下是一個自旋操做,即不斷的重試。

21.4 樂觀鎖的缺點

  • ABA 問題

    • ABA 問題是樂觀鎖一個常見的問題。若是一個變量V初次讀取的時候是A值,而且在準備賦值的時候檢查到它仍然是A值,那咱們就能說明它的值沒有被其餘線程修改過了嗎?很明顯是不能的,由於在這段時間它的值可能被改成其餘值,而後又改回A,那CAS操做就會誤認爲它歷來沒有被修改過。這個問題被稱爲CAS操做的 "ABA"問題。
    • JDK 1.5 之後的 AtomicStampedReference 類就提供了此種能力,其中的 compareAndSet 方法就是首先檢查當前引用是否等於預期引用,而且當前標誌是否等於預期標誌,若是所有相等,則以原子方式將該引用和該標誌的值設置爲給定的更新值。
  • 循環時間長開銷大

    自旋CAS(也就是不成功就一直循環執行直到成功)若是長時間不成功,會給CPU帶來很是大的執行開銷。 若是JVM能支持處理器提供的pause指令那麼效率會有必定的提高,pause指令有兩個做用,第一它能夠延遲流水線執行指令(de-pipeline),使CPU不會消耗過多的執行資源,延遲的時間取決於具體實現的版本,在一些處理器上延遲時間是零。第二它能夠避免在退出循環的時候因內存順序衝突(memory order violation)而引發CPU流水線被清空(CPU pipeline flush),從而提升CPU的執行效率。

  • 只能保證一個共享變量的原子操做

    CAS 只對單個共享變量有效,當操做涉及跨多個共享變量時 CAS 無效。
    可是從 JDK 1.5開始,提供了AtomicReference類來保證引用對象之間的原子性,你能夠把多個變量放在一個對象裏來進行 CAS 操做.因此咱們可使用鎖或者利用AtomicReference類把多個共享變量合併成一個共享變量來操做。

22 鎖機制與InnoDB鎖算法

22.1 MyISAM和InnoDB存儲引擎使用的鎖:

  • MyISAM 採用表級鎖(table-level locking)。
  • InnoDB 支持行級鎖(row-level locking)和表級鎖,默認爲行級鎖

22.2 表級鎖和行級鎖對比:

  • 表級鎖

    Mysql中鎖定 粒度最大 的一種鎖,對當前操做的整張表加鎖,實現簡單,資源消耗也比較少,加鎖快,不會出現死鎖。其鎖定粒度最大,觸發鎖衝突的機率最高,併發度最低,MyISAM和 InnoDB引擎都支持表級鎖。

  • 行級鎖

    Mysql中鎖定 粒度最小 的一種鎖,只針對當前操做的行進行加鎖。 行級鎖能大大減小數據庫操做的衝突。其加鎖粒度最小,併發度高,但加鎖的開銷也最大,加鎖慢,會出現死鎖。

22.3 InnoDB存儲引擎的鎖的算法有三種:

  • Record lock:單個行記錄上的鎖
  • Gap lock:間隙鎖,鎖定一個範圍,不包括記錄自己
  • Next-key lock:record+gap 鎖定一個範圍,包含記錄自己
  • 相關知識點:
    • innodb對於行的查詢使用next-key lock
    • Next-locking keying爲了解決Phantom Problem幻讀問題
    • 當查詢的索引含有惟一屬性時,將next-key lock降級爲record key
    • Gap鎖設計的目的是爲了阻止多個事務將記錄插入到同一範圍內,而這會致使幻讀問題的產生
    • 有兩種方式顯式關閉gap鎖:(除了外鍵約束和惟一性檢查外,其他狀況僅使用record lock)

      A. 將事務隔離級別設置爲RC B. 將參數innodb_locks_unsafe_for_binlog設置爲1

23 drop、delete與truncate區別?

23.1 用法不一樣

  • drop(丟棄數據): drop table 表名 ,直接將表都刪除掉,在刪除表的時候使用。
  • truncate (清空數據) : truncate table 表名 ,只刪除表中的數據,再插入數據的時候自增加id又從1開始,在清空表中數據的時候使用。
  • delete(刪除數據) : delete from 表名 where 列名=值,刪除某一列的數據,若是不加 where 子句和truncate table 表名做用相似。

truncate 和不帶 where 子句的 delete、以及 drop 都會刪除表內的數據,可是 truncate 和 delete 只刪除數據不刪除表的結構(定義),執行drop語句,此表的結構也會刪除,也就是執行 drop 以後對應的表不復存在。

23.2 屬於不一樣的數據庫語言

truncate和drop 屬於DDL(數據定義語言)語句,操做當即生效,原數據不放到 rollback segment 中,不能回滾,操做不觸發 trigger。而 delete 語句是DML (數據庫操做語言)語句,這個操做會放到 rollback segement 中,事務提交以後才生效。

DML 語句和 DDL 語句區別:

  • DML是數據庫操做語言(Data Manipulation Language )的縮寫,是指對數據庫中表記錄的操做,主要包括表記錄的插入(insert)、更新(update)、刪除(delete)和查詢(select),是開發人員平常使用最頻繁的操做。
  • DDL是數據定義語言(Data Definition Language)的縮寫,簡單來講,就是對數據庫內部的對象進行建立、刪除、修改的操做語言。它和 DML 語言的最大區別是 DML 只是對錶內部數據的操做,而不涉及到表的定義、結構的修改,更不會涉及到其餘對象。DDL 語句更多的被數據庫管理員(DBA)所使用,通常的開發人員不多使用。

23.3 執行速度不一樣

通常來講:drop>truncate>delete。

24 數據庫設計一般分爲哪幾步?

  • 需求分析 : 分析用戶的需求,包括數據、功能和性能需求。
  • 概念結構設計 : 主要採用E-R模型進行設計,包括畫E-R圖。
  • 邏輯結構設計 : 經過將E-R圖轉換成表,實現從E-R模型到關係模型的轉換。
  • 物理結構設計 : 主要是爲所設計的數據庫選擇合適的存儲結構和存取路徑。
  • 數據庫實施 : 包括編程、測試和試運行
  • 數據庫的運行和維護 : 系統的運行與數據庫的平常維護。

參考:

相關文章
相關標籤/搜索