MySQL 總結#
一、事務四大特性 (ACID)#
原子性(Atomicity)
#
原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
一致性(Consistency)
#
如果事務執行之前資料庫是一個完整性的狀態,那麼事務結束後,無論事務是否執行成功,資料庫仍然是一個完整性狀態(資料庫的完整性狀態:當一個資料庫中的所有的資料都符合資料庫中所定義的所有的約束,此時可以稱資料庫是一個完整性狀態)
隔離性(Isolation)
#
事務的隔離性是指多個用戶並發訪問資料庫時,一個用戶的事務不能被其他用戶的事務所干擾,多個並發事務之間資料要相互隔離
持久性(durability)
#
持久性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響
擴展#
-
CAP 定理和 BASE 理論:參考:CAP 和 BASE 理論
dubbo+zookeeper
主要實現CP
springcloud eureka [hystrix]
主要實現AP
-
一次業務場景思考
事務已提交,資料卻丟了
二、資料庫隔離級別#
Read Uncommitted
#
讀取未提交內容,在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用於實際應用,因為它的性能也不比其他級別好多少。讀取未提交的資料,也被稱之為髒讀(Dirty Read)
Read Committed
#
讀取提交內容,這是大多數資料庫系統的默認隔離級別(但不是 MySQL 默認的)。它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。這種隔離級別可能會導致所謂的 不可重複讀(Nonrepeatable Read)
,因為同一事務的其他實例在該實例處理其間可能會有新的 commit,所以同一 select 可能返回不同結果
Repeatable Read
#
這是 MySQL 的默認事務隔離級別,它確保同一事務的多個實例在並發讀取資料時,會看到同樣的資料行。不過理論上,這會導致另一個棘手的問題:幻讀 (Phantom Read)
Serializable
#
序列化,這是最高的隔離級別,它通過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每個讀的資料行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭
髒讀 | 不可重複讀 | 幻讀 | |
---|---|---|---|
Read Uncommitted | ✔️ | ✔️ | ✔️ |
Read Committed | ✖️ | ✔️ | ✔️ |
Repeatable Read | ✖️ | ✖️ | ✔️ |
Serializable | ✖️ | ✖️ | ✖️ |
髒讀#
某個事務已更新一份資料,另一個事務在此時讀取了同一份資料,由於某些原因,前一個 RollBack 了操作,則後一個事務所讀取的資料就會是不正確的
幻讀#
在一個事務的兩次查詢中資料筆數不一致,例如有一個事務查詢了幾行 (Row) 資料,而另一個事務卻在此時插入了新的幾行資料,先前的事務在接下來的查詢中,就會發現有幾行資料是它先前所沒有的,InnoDB 和 Falcon 存儲引擎通過多版本並發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題
三、 Mysql 的鎖機制#
參考鏈接: MySQL 鎖總結
聯想記憶: Java 中的Happens Before
語義保證 (volatile
關鍵字)
共享鎖與排他鎖#
共享鎖(讀鎖)
:其他事務可以讀,但不能寫排他鎖(寫鎖)
:其他事務不能讀取,也不能寫
鎖的粒度#
-
表級鎖
- 開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的概率最高,並發度最低。
- 表級鎖更適合於以查詢為主,並發用戶少,只有少量按索引條件更新資料的應用,如 Web 應用
- 這些存儲引擎通過總是一次性同時獲取所有需要的鎖以及總是按相同的順序獲取表鎖來避免死鎖。
-
行級鎖
- 開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,並發度也最高。
- 最大程度的支持並發,同時也帶來了最大的鎖開銷。
- 行級鎖只在存儲引擎層實現,而 Mysql 伺服器層沒有實現。行級鎖更適合於有大量按索引條件並發更新少量不同資料,同時又有並發查詢的應用,如一些在線事務處理(OLTP)系統
-
頁面鎖
:開銷和加鎖時間介於表鎖和行鎖之間;會出現死鎖;鎖定粒度介於表鎖和行鎖之間,並發度一般默認情況下,表鎖和行鎖都是自動獲得的,不需要額外的命令。但是在有的情況下,用戶需要明確地進行鎖表或者進行事務的控制,以便確保整個事務的完整性,這樣就需要使用事務控制和鎖定語句來完成
各種引擎鎖#
MyISAM 和 MEMORY
存儲引擎採用的是表級鎖
(table-level locking)BDB
存儲引擎採用的是頁面鎖
(page-level locking),但也支持表級鎖InnoDB
存儲引擎既支持行級鎖
(row-level locking),也支持表級鎖,但默認情況下是採用行級鎖在 InnoDB 中,除單個 SQL 組成的事務外,鎖是逐步獲得的,這就決定了在 InnoDB 中發生死鎖是可能的。
MyISAM 表鎖#
MyISAM 表級鎖模式#
-
表共享讀鎖
(Table Read Lock):不會阻塞其他用戶對同一表的讀請求,但會阻塞對同一表的寫請求; -
表獨占寫鎖
(Table Write Lock):會阻塞其他用戶對同一表的讀和寫操作MyISAM 表的讀操作與寫操作之間,以及寫操作之間是串行的。當一個線程獲得對一個表的寫鎖後,只有持有鎖的線程可以對表進行更新操作。其他線程的讀、寫操作都會等待,直到鎖被釋放為止
默認情況下,寫鎖比讀鎖具有更高的優先級,當一個鎖釋放時,這個鎖會優先給寫鎖隊列中等候的獲取鎖請求,然後再給讀鎖隊列中等候的獲取鎖請求
這也正是 MyISAM 表不太適合於有大量更新操作和查詢操作應用的原因,因為,大量的更新操作會造成查詢操作很難獲得讀鎖,從而可能永遠阻塞
MyISAM 加表鎖方法#
在自動加鎖的情況下,MyISAM 總是一次獲得 SQL 語句所需要的全部鎖,這也正是 MyISAM 表不會出現死鎖(Deadlock Free)的原因
MyISAM 存儲引擎支持並發插入,以減少給定表的讀和寫操作之間的爭用:
如果 MyISAM 表在資料文件中間沒有空閒塊,則行始終插入資料文件的末尾。在這種情況下,你可以自由混合並發使用 MyISAM 表的 INSERT 和 SELECT 語句而不需要加鎖 —— 你可以在其他線程進行讀操作的時候,同時將行插入到 MyISAM 表中。文件中間的空閒塊可能是從表格中間刪除或更新的行而產生的。如果文件中間有空閒快,則並發插入會被禁用,但是當所有空閒塊都填充有新資料時,它又會自動重新啟用。要控制此行為,可以使用 MySQL 的 concurrent_insert 系統變數:
- 當 concurrent_insert 設置為 0 時,不允許並發插入。
- 當 concurrent_insert 設置為 1 時,如果 MyISAM 表中沒有空洞(即表的中間沒有被刪除的行),MyISAM 允許在一個線程讀表的同時,另一個線程從表尾插入記錄。這也是 MySQL 的默認設置。
- 當 concurrent_insert 設置為 2 時,無論 MyISAM 表中有沒有空洞,都允許在表尾並發插入記錄
查詢表級鎖爭用情況#
可以通過檢查 table_locks_waited 和 table_locks_immediate 狀態變數來分析系統上的表鎖的爭奪,如果 Table_locks_waited 的值比較高,則說明存在著較嚴重的表級鎖爭用情況:
mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name | Value |
+-----------------------+---------+
| Table_locks_immediate | 1151552 |
| Table_locks_waited | 15324 |
+-----------------------+---------+
InnoDB 行級鎖和表級鎖#
InnoDB 鎖模式#
InnoDB 實現了以下兩種類型的行鎖:
共享鎖(S)
:允許一個事務去讀一行,阻止其他事務獲得相同資料集的排他鎖。排他鎖(X)
:允許獲得排他鎖的事務更新資料,阻止其他事務取得相同資料集的共享讀鎖和排他寫鎖
為了允許行鎖和表鎖共存,實現多粒度鎖機制,InnoDB 還有兩種內部使用的意向鎖(Intention Locks),這兩種意向鎖都是表鎖:
意向共享鎖(IS)
:事務打算給資料行加行共享鎖,事務在給一個資料行加共享鎖前必須先取得該表的 IS 鎖意向排他鎖(IX)
:事務打算給資料行加行排他鎖,事務在給一個資料行加排他鎖前必須先取得該表的 IX 鎖
InnoDB 加鎖方法#
- 意向鎖是 InnoDB 自動加的,不需用戶干預。
- 對於 UPDATE、 DELETE 和 INSERT 語句, InnoDB 會自動給涉及資料集加排他鎖(X);
- 對於普通 SELECT 語句,InnoDB 不會加任何鎖;
- 事務可以通過以下語句顯式給記錄集加共享鎖或排他鎖:
(1) 共享鎖(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE (2) 排他鎖(X):SELECT * FROM table_name WHERE ... FOR UPDATE。
隱式鎖定#
InnoDB 在事務執行過程中,使用兩階段鎖協議(聯想記憶到 2pc 協議):
- 隨時都可以執行鎖定,InnoDB 會根據隔離級別在需要的時候自動加鎖;
- 鎖只有在執行 commit 或者 rollback 的時候才會釋放,並且所有的鎖都是在同一時刻被釋放
顯式鎖定#
select ... lock in share mode //共享鎖
select ... for update //排他鎖
select for update
- 在執行這個 select 查詢語句的時候,會將對應的索引訪問條目進行上排他鎖(X 鎖),也就是說這個語句對應的鎖就相當於 update 帶來的效果
- select *** for update 的使用場景:為了讓自己查到的資料確保是最新資料,並且查到後的資料只允許自己來修改的時候,需要用到 for update 子句
- 其他 session 可以查詢該記錄,但是不能對該記錄加共享鎖或排他鎖,而是等待獲得鎖
select lock in share mode
-
in share mode 子句的作用就是將查找到的資料加上一個 share 鎖,這個就是表示其他的事務只能對這些資料進行簡單的 select 操作,並不能夠進行 DML 操作
-
為了確保自己查到的資料沒有被其他的事務正在修改,也就是說確保查到的資料是最新的資料,並且不允許其他人來修改資料。但是自己不一定能夠修改資料,因為有可能其他的事務也對這些資料使用了 in share mode 的方式上了 S 鎖
-
其他 session 仍然可以查詢記錄,並也可以對該記錄加 share mode 的共享鎖。但是如果當前事務需要對該記錄進行更新操作,則很有可能造成死鎖
- 兩者區別:for update 是排他鎖(X 鎖),一旦一個事務獲取了這個鎖,其他的事務是沒法在這些資料上執行;lock in share mode 是共享鎖,多個事務可以同時的對相同資料執行
-
InnoDB 行鎖實現方式#
- InnoDB 行鎖是
通過給索引上的索引項加鎖
來實現的,這一點 MySQL 與 Oracle 不同,後者是通過在資料塊中對相應資料行加鎖來實現的。InnoDB 這種行鎖實現特點意味著:只有通過索引條件檢索資料,InnoDB 才使用行級鎖,否則,InnoDB 將使用表鎖! - 不論是使用主鍵索引、唯一索引或普通索引,InnoDB 都會使用行鎖來對資料加鎖。
- 只有執行計劃真正使用了索引,才能使用行鎖:即便在條件中使用了索引字段,但是否使用索引來檢索資料是由 MySQL 通過判斷不同執行計劃的代價來決定的,如果 MySQL 認為全表掃描效率更高,比如對一些很小的表,它就不會使用索引,這種情況下 InnoDB 將使用表鎖,而不是行鎖。因此,在分析鎖衝突時,
- 由於 MySQL 的行鎖是針對索引加的鎖,不是針對記錄加的鎖,所以
雖然多個session是訪問不同行的記錄,但是如果是使用相同的索引鍵,是會出現鎖衝突的
(後使用這些索引的 session 需要等待先使用索引的 session 釋放鎖後,才能獲取鎖)
MySQL 的鎖算法#
Record Lock
:單個行記錄上的鎖。Gap Lock
:間隙鎖,鎖定一個範圍,但不包括記錄本身。GAP 鎖的目的,是為了防止同一事務的兩次當前讀,出現幻讀的情況。Next-Key Lock:Record + Gap
,鎖定一個範圍,並且鎖定記錄本身。對於行的查詢,都是採用該方法,主要目的是解決幻讀的問題- 別廢話,各種 SQL 到底加了什麼鎖?
四、MySQL 的MVCC
機制#
MVCC
機制是什麼?#
其實就是在每一行記錄的後面增加兩個隱藏列,記錄創建版本號和刪除版本號,而每一個事務在啟動的時候,都有一個唯一的遞增的版本號。在InnoDB
中,給每行增加兩個隱藏字段來實現 MVCC,兩個列都用來存儲事務的版本號,每開啟一個新事務,事務的版本號就會遞增
一致性非鎖定讀#
consistent read (一致性讀)
,InnoDB 用多版本來提供查詢資料庫在某個時間點的快照。如果隔離級別是 REPEATABLE READ,那麼在同一個事務中的所有一致性讀都讀的是事務中第一個這樣的讀讀到的快照; 如果是 READ COMMITTED,那麼一個事務中的每一個一致性讀都會讀到它自己刷新的快照版本。Consistent read(一致性讀)是 READ COMMITTED 和 REPEATABLE READ 隔離級別下普通 SELECT 語句默認的模式。一致性讀不會給它所訪問的表加任何形式的鎖,因此其他事務可以同時並發的修改它們。
解決不可重複讀#
當一個 MVCC 資料庫需要更一條資料記錄的時候,它不會直接用新資料覆蓋舊資料,而是將舊資料標記為過時(obsolete)並在別處增加新版本的資料。這樣就會有存儲多個版本的資料,但是只有一個是最新的。這種方式允許讀者讀取在他讀之前已經存在的資料,即使這些在讀的過程中半路被別人修改、刪除了,也對先前正在讀的用戶沒有影響。保證了在同一個事務中多次讀取相同的資料返回的結果是一樣的,解決了不可重複讀的問題。
缺點在於:
這種多版本的方式避免了填充刪除操作在內存和磁碟存儲結構造成的空洞的開銷,但是需要系統周期性整理(sweep through)以真實刪除老的、過時的資料。
總結就是: MVCC是同一份資料臨時保留多版本的一種方式,進而實現並發控制
參考鏈接#
- 通過
etcd
學習MVCC
機制: ectd
五、MySQL 的存儲引擎#
InnoDB
#
簡介#
- 支持 ACID 的事務,支持事務的四種隔離級別;
- 支持行級鎖及外鍵約束:因此可以支持寫並發;
- 不存儲總行數;
- 一個 InnoDB 引擎存儲在一個文件空間(共享表空間,表大小不受操作系統控制,一個表可能分布在多個文件裡),也有可能為多個(設置為獨立表空間,表大小受操作系統文件大小限制,一般為 2G),受操作系統文件大小的限制;
- 主鍵索引採用聚集索引(索引的資料域存儲資料文件本身),輔索引的資料域存儲主鍵的值;因此從輔索引查找資料,需要先通過輔索引找到主鍵值,再訪問輔索引;
- 最好使用自增主鍵,防止插入資料時,為維持 B + 樹結構,文件的大調整;
- 適用 OLTP (聯機事務處理),實時性要求高
主要特性#
插入緩存(insert buffer)、兩次寫 (double write)、自適應哈希 (Adaptive Hash index)、異步 IO (Async IO)、刷新鄰接頁 (Flush Neighbor Page)
參考#
- InnoDB 關鍵特性
- InnoDB 架構,一幅圖秒懂!
- InnoDB 到底支不支持哈希索引
- InnoDB 並發如此高,原因竟然在這?
- InnoDB,5 項最佳實踐,知其所以然?
- 挖坑,InnoDB 的七種鎖
- InnoDB 並發插入,居然使用意向鎖?
- 插入 InnoDB 自增列,居然是表鎖
- 超讚,InnoDB 調試死鎖的方法!
- InnoDB,select 為啥會阻塞 insert?
- InnoDB,快照讀,在 RR 和 RC 下有何差異?
MyISAM
#
- 不支持事務,但是每次查詢都是原子的;
- 支持表級鎖,即每次操作是對整個表加鎖;
- 存儲表的總行數;
- 一個 MyISAM 表有三個文件:索引文件、表結構文件、資料文件;
- 採用非聚集索引,索引文件的資料域存儲指向資料文件的指針。輔索引與主索引基本一致,但是輔索引不用保證唯一性。
- 適用 OLAP (聯機分析處理),實時性要求不高但一般資料量大
MEMORY#
ARCHIVE#
參考鏈接#
六、MySQL 的索引#
主要有 B + 索引和 hash 索引,區別:#
- 如果是等值查詢,那麼哈希索引明顯有絕對優勢,因為只需要經過一次算法即可找到相應的鍵值;當然了,這個前提是,鍵值都是唯一的。如果鍵值不是唯一的,就需要先找到該鍵所在位置,然後再根據鏈表往後掃描,直到找到相應的資料;
- 如果是範圍查詢檢索,這時候哈希索引就毫無用武之地了,因為原先是有序的鍵值,經過哈希算法後,有可能變成不連續的了,就沒辦法再利用索引完成範圍查詢檢索;
- 同理,哈希索引也沒辦法利用索引完成排序,以及 like ‘xxx%’ 這樣的部分模糊查詢(這種部分模糊查詢,其實本質上也是範圍查詢);
- 哈希索引也不支持多列聯合索引的最左匹配規則;
- B + 樹索引的關鍵字檢索效率比較平均,不像 B 樹那樣波動幅度大,在有大量重複鍵值情況下,哈希索引的效率也是極低的,因為存在所謂的哈希碰撞問題
B + 索引資料結構,和 B 樹的區別#
-
B 樹:有序數組 + 平衡多叉樹
它的特點是:
(1) 不再是二叉搜索,而是 m 叉搜索;
(2) 葉子節點,非葉子節點,都存儲資料;
(3) 中序遍歷,可以獲得所有節點; -
B + 樹:有序數組鏈表 + 平衡多叉樹,在 B 樹的基礎上,做了一些改進
(1) 非葉子節點不再存儲資料,資料只存儲在同一層的葉子節點上
(2) 葉子之間,增加了鏈表,獲取所有節點,不再需要中序遍歷 -
B + 樹改進後更優的特性
(1) 範圍查找,定位 min 與 max 之後,中間葉子節點,就是結果集,不用中序回溯
(2) 葉子節點存儲實際記錄行,記錄行相對比較緊密的存儲,適合大資料量磁碟存儲;非葉子節點存儲記錄的 PK,用於查詢加速,適合內存存儲;
(3) 非葉子節點,不存儲實際記錄,而只存儲記錄的 KEY 的話,那麼在相同內存的情況下,B + 樹能夠存儲更多索引
為什麼 B + 樹適合作為索引的結構#
- 不同於二叉搜索樹,B 樹是 m 分叉的,樹高度能大大降低,所以能夠存儲大量資料
- 很適合磁碟存儲,能夠充分利用局部性原理,磁碟預讀
(1) 內存讀寫塊,磁碟讀寫慢,而且慢很多;
(2) 磁碟預讀:磁碟讀寫並不是按需讀取,而是按頁預讀,一次會讀一頁 (一頁資料是 4K) 的資料,每次加載更多的資料,如果未來要讀取的資料就在這一頁中,可以避免未來的磁碟 IO,提高效率;
(3) 局部性原理:軟體設計要盡量遵循 “資料讀取集中” 與 “使用到一個資料,大概率會使用其附近的資料”,這樣磁碟預讀能充分提高磁碟 IO - MyISAM 和 InnoDB 都使用了 B + 樹作為索引存儲結構,但是葉子上資料的存儲方式不同。前者索引文件和資料文件是分離的,索引文件僅保存記錄所在頁的指針(物理位置),而後者直接存儲資料,或者存儲主鍵值(存儲主鍵值並檢索輔助索引,此時實際上進行了二次查詢,增加 IO 次數
索引分類#
- 普通索引:最基本的索引,沒有任何限制。
- 唯一索引:與 “普通索引” 類似,不同的就是:索引列的值必須唯一,但允許有空值。
- 主鍵索引:它 是一種特殊的唯一索引,不允許有空值。
- 全文索引:僅可用於 MyISAM 表,針對較大的資料,生成全文索引很耗時耗空間。(MATCH... AGAINST...)
- 組合索引:為了更多的提高 MySQL 效率可建立組合索引,遵循 “最左前綴” 原則。
- 覆蓋索引:包含(覆蓋)所有需要查詢的字段的值的索引
explain 模擬 SQL 查詢計劃#
explain 執行計劃包含的信息#
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
---|
對應含義詳解#
-
id
: select 查詢的序列號,包含一組數字,表示查詢中執行 select 子句或操作表的順序 -
select_type
: 查詢的類型,分為:- SIMPLE:簡單的 select 查詢,查詢中不包含子查詢或者 union
- PRIMARY:查詢中包含任何複雜的子部分,最外層查詢則被標記為 primary
- SUBQUERY:在 select 或 where 列表中包含了子查詢
- DERIVED:在 from 列表中包含的子查詢被標記為 derived(衍生),mysql 或遞歸執行這些子查詢,把結果放在零時表裡
- UNION:若第二個 select 出現在 union 之後,則被標記為 union;若 union 包含在 from 子句的子查詢中,外層 select 將被標記為 derived
- UNION RESULT:從 union 表獲取結果的 select
-
type
: 訪問類型,sql 查詢優化中一個很重要的指標,結果值從好到壞依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般來說,好的 sql 查詢至少達到range
級別,最好能達到ref
system
:表只有一行記錄(等於系統表),這是 const 類型的特例,平時不會出現,可以忽略不計const
:表示通過索引一次就找到了,const 用於比較 primary key 或者 unique 索引。因為只需匹配一行資料,所有很快。如果將主鍵置於 where 列表中,mysql 就能將該查詢轉換為一個 consteq_ref
:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵 或 唯一索引掃描。ref
:非唯一性索引掃描,返回匹配某個單獨值的所有行。本質是也是一種索引訪問,它返回所有匹配某個單獨值的行,然而他可能會找到多個符合條件的行,所以它應該屬於查找和掃描的混合體range
:只檢索給定範圍的行,使用一個索引來選擇行。key 列顯示使用了那個索引。一般就是在 where 語句中出現了 bettween、<、>、in 等的查詢index
:Full Index Scan,index 與 ALL 區別為 index 類型只遍歷索引樹。這通常為 ALL 塊,應為索引文件通常比資料文件小。(Index 與 ALL 雖然都是讀全表,但 index 是從索引中讀取,而 ALL 是從硬碟讀取)ALL
:Full Table Scan,遍歷全表以找到匹配的行
-
possible_keys
: 查詢涉及到的字段上存在索引,則該索引將被列出,但不一定被查詢實際使用 -
key
: 實際使用的索引,如果為 NULL,則沒有使用索引。查詢中如果使用了覆蓋索引,則該索引僅出現在 key 列表中 -
key_len
: 表示索引中使用的字節數,查詢中使用的索引的長度(最大可能長度),並非實際使用長度,理論上長度越短越好。key_len 是根據表定義計算而得的,不是通過表內檢索出的 -
ref
: 顯示索引的那一列被使用了,如果可能,是一個常量 const -
rows
: 根據表統計信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數 -
Extra
: 不適合在其他字段中顯示,但是十分重要的額外信息Using filesort
對資料使用一個外部的索引排序,而不是按照表內的索引進行排序讀取。也就是說 mysql 無法利用索引完成的排序操作成為 “文件排序”Using temporary
: 使用臨時表保存中間結果,也就是說 mysql 在對查詢結果排序時使用了臨時表,常見於 order by 和 group byUsing index
: 表示相應的 select 操作中使用了覆蓋索引(Covering Index),避免了訪問表的資料行,效率高;如果同時出現 Using where,表明索引被用來執行索引鍵值的查找;如果沒同時出現 Using where,表明索引用來讀取資料而非執行查找動作Using Where
: 使用了 where 過濾Using join buffer
: 使用了連接緩存Impossible WHERE
: where 子句的值總是 false,不能用來獲取任何元組select tables optimized away
: 在沒有 group by 子句的情況下,基於索引優化 MIN/MAX 操作或者對於 MyISAM 存儲引擎優化 COUNT(*)操作,不必等到執行階段在進行計算,查詢執行計劃生成的階段即可完成優化distinct
: 優化 distinct 操作,在找到第一個匹配的元組後即停止找同樣值得動作
參考鏈接#
聚集索引和非聚集索引區別#
聚集(clustered)索引,也叫聚簇索引#
定義:資料行的物理順序與列值(一般是主鍵的那一列)的邏輯順序相同,一個表中只能擁有一個聚集索引。
如果沒定義主鍵,會選擇一個唯一的非空索引代替,如果沒有這樣的索引,則會隱式定義一個主鍵作為聚簇索引
非聚集(unclustered)索引#
定義:該索引中索引的邏輯順序與磁碟上行的物理存儲順序不同,一個表中可以擁有多個非聚集索引
參考#
七、資料庫的主從複製#
- 就算 MySQL 拆成了多個,也必須分出主和從,所有的寫操作都必須要在主 MySQL 上完成;
- 所有的從 MySQL 的資料都來自於 (同步於) 主 MySQL
- 在 MySQL 主從時,如果一個業務 (service 中的一個方法) 中,如果既有 R 操作,又有 W 操作,因為 W 操作一定要在主 MySQL 上,所以在一個事務中所有的資料來
拓展#
八、範式設計#
- 第一範式(1NF)是對關係模式的基本要求,不滿足第一範式(1NF)的資料庫就不是關係資料庫,是指資料庫表的每一列都是不可分割的基本資料項,同一列中不能有多個值;
- 第二範式(2NF)要求資料庫表中的每個實例或行必須可以被惟一區分。 即各字段和主鍵之間不存在部分依賴
- 第三範式(3NF)要求一個資料庫表中不包含已在其他表中已包含的非主關鍵字信息。即在第二範式的基礎上,不存在傳遞依賴 (不允許有冗餘資料)