當年肥工的DB課講的其實還挺好的...就用當時的筆記叭html
(因此當年爲何不整理呢?仍是懶叭mysql
完整性:防止DB中存在不符合規定的數據(eg:性別只能是男或女)git
實體完整性:primary key中的屬性取值必須惟一且不能爲空github
參照完整性:若F是R的外碼(foreign key),K是S的主碼(primary key),F鏈接K。那麼對於R中的每一個元祖,R.F必須是 在S.K中出現過的值 或者 NULL算法
用戶定義的完整性:用戶本身在具體的DB中指定的約束(定義:NOT NULL / UNIQUE / CHECK)sql
觸發器:用於實現用戶定義的完整性 CREATE TRIGGER ON ... AFTER ...數據庫
存儲過程:用SQL語句實現一些用戶定義的業務邏輯緩存
關係模型服務器
(略)網絡
(略)
B+Tree
B Tree 指的是 Balance Tree,也就是平衡樹。平衡樹是一顆查找樹,而且全部葉子節點位於同一層。
B+ Tree 是基於 B Tree 和葉子節點順序訪問指針進行實現,它具備 B Tree 的平衡性,而且經過順序訪問指針來提升區間查詢的性能。
在 B+ Tree 中,一個節點中的 key 從左到右非遞減排列,若是某個指針的左右相鄰 key 分別是 keyi 和 keyi+1,且不爲 null,則該指針指向節點的全部 key 大於等於 keyi 且小於等於 keyi+1。
進行查找操做時,首先在根節點進行二分查找,找到一個 key 所在的指針,而後遞歸地在指針所指向的節點進行查找。直到查找到葉子節點,而後在葉子節點上進行二分查找,找出 key 所對應的 data。
插入刪除操做會破壞平衡樹的平衡性,所以在插入刪除操做以後,須要對樹進行一個分裂、合併、旋轉等操做來維護平衡性。
與紅黑樹的比較
紅黑樹等平衡樹也能夠用來實現索引,可是文件系統及數據庫系統廣泛採用 B+ Tree 做爲索引結構,主要有如下兩個緣由:
(一)更少的查找次數
平衡樹查找操做的時間複雜度和樹高 h 相關,O(h)=O(logdN),其中 d 爲每一個節點的出度。
紅黑樹的出度爲 2,而 B+ Tree 的出度通常都很是大,因此紅黑樹的樹高 h 很明顯比 B+ Tree 大很是多,查找的次數也就更多。
(二)利用磁盤預讀特性
爲了減小磁盤 I/O 操做,磁盤每每不是嚴格按需讀取,而是每次都會預讀。預讀過程當中,磁盤進行順序讀取,順序讀取不須要進行磁盤尋道,而且只須要很短的磁盤旋轉時間,速度會很是快。
操做系統通常將內存和磁盤分割成固定大小的塊,每一塊稱爲一頁,內存與磁盤以頁爲單位交換數據。數據庫系統將索引的一個節點的大小設置爲頁的大小,使得一次 I/O 就能徹底載入一個節點。而且能夠利用預讀特性,相鄰的節點也可以被預先載入。
B+ Tree、LSM Tree:http://www.javashuo.com/article/p-dozobccc-kc.html
MYSQL:http://blog.codinglabs.org/articles/theory-of-mysql-index.html
Hash:http://www.javashuo.com/article/p-tmiclehe-cv.html
紅黑樹:https://www.jianshu.com/p/e136ec79235c
索引的優勢
索引的使用條件
咱們在寫Java程序,遇到併發問題時,會想到用鎖來解決。數據庫遇到併發問題怎麼解決呢?答案就是事務,事務的本質就是鎖和併發的結合體(能夠理解成在數據庫系統上執行的一個函數。好比在銀行數據庫中,把A的100元錢轉給B)
事務指的是知足 ACID 特性的一組操做,能夠經過 Commit 提交一個事務,也可使用 Rollback 進行回滾。一個事務包含了多個命令,服務器在執行事務期間,不會改去執行其它客戶端的命令請求。事務是併發控制的基本單位。
事務中的多個命令被一次性發送給服務器,而不是一條一條發送,這種方式被稱爲流水線,它能夠減小客戶端與服務器之間的網絡通訊次數從而提高性能。
ACID特性:
恢復:
事務是併發控制的基本單位。
併發一致性問題
在併發環境下,事務的隔離性很難保證,所以會出現不少併發一致性問題。解決方法是經過併發控制來保證隔離性。併發控制能夠經過封鎖來實現,可是封鎖操做須要用戶本身控制,至關複雜。數據庫管理系統提供了事務的隔離級別,讓用戶以一種更輕鬆的方式處理併發一致性問題。
併發控制主要技術:封鎖、時間戳、樂觀控制法、多版本併發控制等。
封鎖:至關於分佈式中的加鎖/解鎖。基本封鎖類型:排他鎖(X 鎖 / 寫鎖)、共享鎖(S 鎖 / 讀鎖)。
封鎖協議:規定加鎖解鎖的規則
兩段鎖協議:全部事務必須分兩個階段對數據項加鎖/解鎖:
若併發執行的全部事務都遵循兩段鎖協議,則對這些事務的任何併發調度策略都是可串行化的。
可是對於分佈式事務,2pc有可能出現數據不一致的問題。若是要完全解決這一問題就要用paxos或者Raft了。
封鎖粒度:具體對哪一個對象加鎖
MySQL 中提供了兩種封鎖粒度:行級鎖以及表級鎖。
應該儘可能只鎖定須要修改的那部分數據,而不是全部的資源。鎖定的數據量越少,發生鎖爭用的可能就越小,系統的併發程度就越高。
可是加鎖須要消耗資源,鎖的各類操做(包括獲取鎖、釋放鎖、以及檢查鎖狀態)都會增長系統開銷。所以封鎖粒度越小,系統開銷就越大。
在選擇封鎖粒度時,須要在鎖開銷和併發程度之間作一個權衡。
活鎖:某個事務等待時間太長,可經過先來先服務的策略避免。
死鎖:事務永遠沒法完成,同OS中的死鎖
可串行化調度:可串行性是併發事務正確調度的準則。表示併發調度的結果和徹底串行執行的結果是一致的。
隔離級別事務具備隔離性,理論上來講事務之間的執行不該該相互產生影響,其對數據庫的影響應該和它們串行執行時同樣。然而徹底的隔離性會致使系統併發性能很低,下降對資源的利用率,於是實際上對隔離性的要求會有所放寬,這也會必定程度形成對數據庫一致性要求下降。事務的隔離級別越低,可能出現的併發異常越多,可是一般而言系統能提供的併發能力越強。
MVCC
在分佈式數據庫中,爲了提升事務執行的並行度,會使用MVCC進行併發控制。MYSQL中就用MVCC進行併發控制。
切分
水平切分:水平切分又稱爲 Sharding,它是將同一個表中的記錄拆分到多個結構相同的表中。
當一個表的數據不斷增多時,Sharding 是必然的選擇,它能夠將數據分佈到集羣的不一樣節點上,從而緩存單個數據庫的壓力。
垂直切分:將一張表按列切分紅多個表,一般是按照列的關係密集程度進行切分,也能夠利用垂直切分將常常被使用的列和不常常被使用的列切分到不一樣的表中。
在數據庫的層面使用垂直切分將按數據庫中表的密集程度部署到不一樣的庫中,例如將原來的電商數據庫垂直切分紅商品數據庫、用戶數據庫等。
Sharding 策略
哈希取模:hash(key) % N;
範圍:能夠是 ID 範圍也能夠是時間範圍;
映射表:使用單獨的一個數據庫來存儲映射關係。
Sharding 存在的問題
1. 事務問題 使用分佈式事務來解決,好比 XA 接口。
2. 鏈接 能夠將原來的鏈接分解成多個單表查詢,而後在用戶程序中進行鏈接。
3. ID 惟一性 使用全局惟一 ID(GUID)、爲每一個分片指定一個 ID 範圍、分佈式 ID 生成器 (如 Twitter 的 Snowflake 算法)
主從複製
主要涉及三個線程:binlog 線程、I/O 線程和 SQL 線程。
讀寫分離
主服務器處理寫操做以及實時性要求比較高的讀操做,而從服務器處理讀操做。讀寫分離能提升性能的緣由在於:
讀寫分離經常使用代理方式來實現,代理服務器接收應用層傳來的讀寫請求,而後決定轉發到哪一個服務器。
https://github.com/CyC2018/CS-Notes/blob/master/notes/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B3%BB%E7%BB%9F%E5%8E%9F%E7%90%86.md
https://github.com/huihut/interview#-%E6%95%B0%E6%8D%AE%E5%BA%93
https://github.com/CyC2018/CS-Notes/blob/master/notes/MySQL.md
https://github.com/CyC2018/CS-Notes/blob/master/notes/Redis.md