文章目錄
一. 視圖
1. 視圖的基本概念:
- 視圖是從一個或幾個基本表(或視圖)中導出的虛擬的表。
- 視圖看上去非常像數據庫的物理表,對它的操作同任何其它的表一樣。當通過視圖修改數據時,實際上是在改變基表中的數據;相反地,基表數據的改變也會自動反映在由基表產生的視圖中。
2. 視圖的作用:
- 1、視圖能夠簡化用戶的操作
- 2、視圖使用戶能以多鍾角度看待同一數據
- 3、視圖對重構數據庫提供了一定程度的邏輯獨立性
- 4、視圖能夠對機密數據提供安全保護
- 5、適當的利用視圖可以更清晰的表達查詢
- 簡單性。看到的就是需要的。視圖不僅可以簡化用戶對數據的理解,也可以簡化他們的操作。那些被經常使用的查詢可以被定義爲視圖,從而使得用戶不必爲以後的操作每次指定全部的條件。
- 安全性。通過視圖用戶只能查詢和修改他們所能見到的數據。數據庫中的其它數據則既看不見也取不到。數據庫授權命令可以使每個用戶對數據庫的檢索限制到特定的數據庫對象上,但不能授權到數據庫特定行和特定的列上。通過視圖,用戶可以被限制在數據的不同子集上。
--- 創建計算機系學生的視圖 create view_tatal_students as select id, name, sex from students where sdept = 'CS'
3. 視圖和表的區別是什麼?
- 表直接將數據存儲在磁盤上,視圖是將
SQL
語句存儲到磁盤上; - 視圖是建立在表的基礎上,表存儲數據庫中的數據,而視圖顯示已經在表中的數據的外觀;
- 視圖本身沒有數據,只保存了
SQL
語句; - 次使用視圖時會去執行
SQL
語句在它的基表中查詢數據,而表卻是實實在在的保存着數據 - 刪除視圖,表不受影響,而刪除表,視圖不再起作用。
二. 數據庫事務
1. 什麼是數據庫事務:
- 數據庫事務是構成單一邏輯工作單元的操作集合,要麼全部執行成功,要麼全部不執行。
2. 數據庫事務的特性:(ACID)
- ① 原子性:是指事務中的所有操作作爲一個整體像原子一樣不可分割,要麼全部成功,要麼全部失敗。
- ② 一致性:事務的執行成果必須使數據庫從一個一致性狀態到另一個一致性狀態。一致性狀態是指:Ⅰ. 系統的狀態必須滿足數據的完整性約束(主碼,參照完整性,check 約束等);Ⅱ. 系統的狀態反應數據庫本應描述的現實世界的真實狀態,比如轉賬前後兩個賬戶的金額總和應該保持不變;
- ③ 隔離性:併發執行的事務不會相互影響,其對數據庫的影響和它們串行執行時一樣。比如多個賬戶同時往一個賬戶轉賬,左後賬戶的結果應該和它們按先後順序轉賬的結果一樣;
- ④ 持久性:事務一旦提交,其對數據庫的更新就是持久的,任何事務或故障都不會導致數據丟失。
3. 原子性是通過什麼機制實現的:
- 通過日誌來實現的,比如
MySQL
中的InnoDB
引擎使用undo log
。 - 在操作任何數據之前,首先將數據被分到一個地方,這個存儲數據備份的地方稱爲
undo log
,然後進行數據的修改,如果出現了錯誤或者用於執行了rollback
語句,系統可以利用undo log
中的備份數據將數據恢復到事務開始前的狀態。 undo log
是邏輯日誌- ①:當
delete
一條記錄時,undo log
中會記錄一條對應的insert
記錄; - ②:當
insert
一條記錄時,undo log
中會記錄一條對應的delete
記錄; - ③:當
update
一條記錄時,undo log
中會記錄一條對應的update
記錄;
4. 持久性是通過什麼機制實現的:
- 通過日誌來實現的,比如
MySQL
中的InnoDB
引擎使用redo log
。 - 和
undo log
相反,redo log
記錄的是新數據的備份,在事務提交之前,只要將redo log
持久化即可,不需要將數據持久化; - 當系統奔潰時,雖然數據沒有持久化,但是
redo log
已經持久化,系統可以根據redo log
中的內容,將所有數據恢復到最新的狀態;
5. 隔離性是通過什麼機制實現的:
- 通過鎖來實現的,在
MySQL
的InnoDB
中,鎖可以分爲兩類,共享鎖和排他鎖。 - ① 共享鎖:共享鎖將數據變爲只讀形式,不能進行更新,所以也稱爲讀取鎖定。
- ② 排他鎖:
6. 一致性是通過什麼機制實現的:
ACID
中,一致性是事務的根本追求,而某些情況下,比如事務的併發執行或者事務故障或系統奔潰等,會對事務的一致性造成破壞。- 數據庫系統通過併發控制技術和日誌恢復技術來避免這種情況的發生。
- 併發控制技術保證了事務的隔離性,使數據庫的一致性不會因併發執行的操作而破壞;
- 日誌恢復技術包括了事務的原子性,使一致性不會因爲事務故障而被破壞,同時也使已提交的數據庫的修改不會因系統奔潰而丟失,即保證了事務的持久性。
- 換句話說,事務的一致性是通過原子性,持久性,隔離性來實現的。
7. MySQL 的隔離級別:
- 事務具有隔離性,理論上來說事務之間的執行不應該相互產生影響,其對數據庫的影響應該和它們串行執行時一樣,然而完全的隔離性會導致系統的併發性很低,降低對資源的利用率,因而實際上對隔離性的要求會有所放寬。
SQL
標準爲事務定義了不同的隔離級別,從低到高分別是:
- 髒讀/不可重複讀/幻讀的概念:
- ①:髒讀:對於兩個事務
T1
與T2
,T1
讀取了已經被T2
更新但是還沒有提交的字段之後,若此時T2
回滾,T1
讀取的內容就是臨時並且無效的。或者簡單來說,髒讀就是指一個線程中的事務讀取到了另外一個線程中未提交的數據。 - ②:不可重複讀:不可重複讀: 對於兩個事務
T1
和T2
,T1
讀取了一個字段,然後T2
更新了該字段並提交之後,T1
再次提取同一個字段,值便不相等了。 - ③:幻讀:對於兩個事務
T1
、T2
,T1
從表中讀取數據,然後T2
進行了INSERT
操作並提交,當T1
再次讀取的時候,結果不一致的情況發生。 - 不同的隔離級別可能導致不同的併發異常,如下表:
事務的隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
讀未提交 | 可能 | 可能 | 可能 |
讀已提交 | 不可能 | 可能 | 可能 |
可重複讀 | 不可能 | 不可能 | 可能 |
串行化 | 不可能 | 不可能 | 不可能 |
-
其中,
MySQL
默認的隔離級別是可重複讀。 -
級別越高,數據越安全,但性能越低。
-
創建事務的
MySQL
語法: -
①:隱式事務:事務沒有明顯的開啓或者結束的標誌,
MySQL
中,默認是開啓自動提交的,可以通過以下語句查看:select @@autocommit;
-
在
autocommit = 1
的情況下,針對SELECT、UPDATE、DELETE、INSERT
等DQL
及DML
語句的執行,MySQL
會自動提交該事務,如果關閉就需要手動提交或者回滾來完成操作。 -
②:顯式事務:與隱式事務想反,有明顯的開啓或結束標誌。可以通過以下語句來設置:
set autocommit = 0;
-
在
autocommit = 0
的情況下,在事務未結束之前,操作是有效的且更改了數據實體,那麼如果有多個事務參與, 肯定會出現各種各樣的數據不一致的情況,這就類似多個線程在沒有鎖的情況下修改同一個全局變量。 -
Serializable
級別就類似加鎖的方式,同一時刻支持多個事務併發,但是針對DML(Update\Insert\Delete)
操作時,當前發起操作的事務會被阻塞,直到其他事務Commit
或者Rollback
纔會繼續執行事務語句。可見效率十分低下。
三. 索引
1. 索引的概念:
- 索引是幫助
MySQL
高效獲取數據的排好序的數據結構。 - 索引底層的數據結構常見的有以下幾種:二叉樹,紅黑樹,Hash 表,B-Tree;
- 常見的
MySQL
主要有兩種結構:Hash索引
和B+ Tree索引
,我們使用的是InnoDB
引擎,默認的是B+樹
。
2. B+Tree索引和Hash索引區別?
- 哈希索引適合等值查詢,但是無法進行範圍查詢
+哈希索引沒辦法利用索引完成排序
哈希索引不支持多列聯合索引的最左匹配規則
如果有大量重複鍵值的情況下,哈希索引的效率會很低,因爲存在哈希碰撞問題
3. MyISAM 存儲引擎實現:
- ①:實現結構:B+ 樹;
- ②:B+ 樹的葉子節點是
<key, value>
形式,其中,key
是索引,value
是索引所在那一行的磁盤文件地址。 - ③:索引文件和數據文件分開存儲,即MyISAM
是非聚集索引
,有xxx.frm
文件,xxx.MYD
文件,xxx.MYI
文件。 InnoDB
的數據文件本身就是索引文件。MyISAM
索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。而在InnoDB
中,表數據文件本身就是按B+Tree
組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key
是數據表的主鍵,因此InnoDB
表數據文件本身就是主索引。葉節點包含了完整的數據記錄。這種索引叫做聚集索引。因爲InnoDB
的數據文件本身要按主鍵聚集,所以InnoDB
要求表必須有主鍵(MyISAM
可以沒有),如果沒有顯式指定,則MySQL
系統會自動選擇一個可以唯一標識數據記錄的列作爲主鍵,如果不存在這種列,則MySQL
自動爲InnoDB
表生成一個隱含字段作爲主鍵,這個字段長度爲6個字節,類型爲長整形
。第二個與MyISAM
索引的不同是InnoDB
的輔助索引data
域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB
的所有輔助索引都引用主鍵作爲data
域。
4. InnoDB 存儲引擎實現:
- ①:表數據文件本身就是按B+ 樹組織的一個索引結構文件,
xxx.IBD
文件; - ②:聚集索引葉節點,包含了完整的數據記錄;
- ③:這也就是爲什麼
InnoDB
必須要有主鍵,且推薦使用自增的整型主鍵。
5. 爲什麼 InnoDB 必須要有主鍵?並且推薦用整型的自增主鍵?
- 因爲
InnoDB
本身的文件組織形式就是按照B+ 樹組織的一個索引結構文件,所以必須需要一個主鍵纔可以組織起來,如果用戶使用InnoDB
存儲引擎建立表的時候,沒有指定主鍵,則MySQL
會自動的幫你找到一個合適的唯一索引作爲主鍵,若找不到符合條件唯一索引條件的字段時,會生成類似於ROW_ID的
虛擬列充當該InnoDB
表的主鍵; - 整型的存儲比字段類型要小,而且應爲是
InnoDB
存儲引擎使用的是B+Tree
數據結構,在進行查詢數據是需要對每個元素進行比較,而整型的對比效率是高於其他數據結構的,字符串等。 InnoDB
使用聚集索引,數據記錄本身被存於主索引(一顆B+Tree
)的葉子節點上。這就要求同一個葉子節點內(大小爲一個內存頁或磁盤頁)的各條數據記錄按主鍵順序存放,因此每當有一條新的記錄插入時,MySQL
會根據其主鍵將其插入適當的節點和位置,如果頁面達到裝載因子(InnoDB
默認爲15/16
),則開闢一個新的頁(節點)。- 如果表使用自增主鍵,那麼每次插入新的記錄,記錄就會順序添加到當前索引節點的後續位置,當一頁寫滿,就會自動開闢一個新的頁。這樣就會形成一個緊湊的索引結構,近似順序填滿。由於每次插入時也不需要移動已有數據,因此效率很高,也不會增加很多開銷在維護索引上。
4. 索引的設計原則?
5. 什麼情況下索引會失效?
- ①:如果條件中有
or
,即使其中有條件帶索引也不會使用 (這也是爲什麼儘量少用or
的原因);要想使用or
,又想讓索引生效,只能將or
條件中的每個列都加上索引;
四. 數據庫引擎
- 數據庫三大引擎:InnoDB、MyISAM、MEMORY;
五. 鎖
1. 概念:
- 鎖是計算機協調多個進程或線程併發訪問某一資源的機制。
MySQL
的鎖機制比較簡單,不同的搜索引擎支持不同的鎖機制。- 比如
MyISAM
支持表級鎖; InnoDB
既支持表級鎖,又支持行級鎖,但默認情況下使用行級鎖。
2. 表級鎖和行級鎖的概念:
- 表級鎖:開銷小,加鎖快,不會出現死鎖,發生鎖衝突的概率最高,併發度最低;
- 行級鎖:開銷大,加鎖慢,會出現死鎖,鎖粒度最小,發生鎖衝突的概率最低,併發成都也最高。
- 很難說哪種鎖更好,只能就具體應用的特點來說哪種鎖更合適。
- 表級鎖更適合於以查詢爲主,只有少量按索引條件更新數據的應用,如·web應用`;
- 行級鎖更適合有大量按索引條件併發更新少量不同數據,同時又有併發查詢的業務。
3. MyISAM 表級鎖
MyISAM
的表級鎖有兩種模式:
- 對於
MyISAM
表的讀鎖,不會阻塞其他用戶對同一表的讀請求,但會阻塞對同一表的寫請求; - 對於
MyISAM
表的寫鎖,則會堵塞其他用戶對同一表的讀和寫操作。 MyISAM
在執行查詢語句之前,會自動給涉及的所有表加讀鎖;在執行更新操作之前,會自動給涉及的表加寫鎖,這個過程並不需要用戶干預,因此用戶一般不需要使用命令來顯示加鎖。MyISAM
的讀操作於寫操作之間,以及寫寫操作之間是串行的。MyISAM
默認的鎖調度是寫優先,由於表鎖粒度大,讀寫之間又是串行的,因此,如果更新操作比較多,MyISAM
表可能會出現嚴重的表等待。
-
MyISAM
的寫操作示例: -
當一個線程獲得對一個表的寫鎖之後,只有持有鎖的線程可以對錶進行更新操作,其他線程的讀寫操作都會阻塞,知道鎖釋放爲止。
--- 寫鎖定 lock table student write; --- 執行操作 --- 釋放鎖 unlock tables;
MyISAM
的讀阻塞寫示例:- 一個
Session
使用lock table table_name read
給表加讀鎖,這個Session
可以鎖定表記錄中的記錄,但更新和訪問其他表都會提示錯誤,同時,另一個Session
可以查詢該表的記錄,但更新就會出現鎖等待。
4. InnoDB 行級鎖
共享鎖(S)
:又稱讀鎖,允許一個事務去讀一行,並阻止其他事務獲得相同數據集的排他鎖;- 若數據
T
對數據A
加上S
鎖,則事務T
可以讀A
但不能修改A
,其他事務只能再對A
加S
鎖,但不能加X
鎖,直到T
釋放A
上的S
鎖。這保證了其他事務可以讀A
,但在T
釋放A
上的S
鎖前不能對A
做任何修改。 排他鎖(X)
:又稱寫鎖,允許獲得排他鎖的事務更新數據,並阻止其他事務獲取對相同數據集的共享鎖和排他寫鎖。若事務T
對數據對象加上X
鎖,事務T
可以讀取A
也可以修改A
,但其他事務不能再對數據A
加上任何鎖,直到事務T
釋放A
上的X
鎖。MySQL
的InnoDB
引擎默認的修改數據語句Insert, Delete, Update
都會自動給涉及到的數據加上排他鎖,select
語句默認不會加任何鎖類型。
-
5. InnoDB 行級鎖的實現方式:
InnoDB
加鎖是通過給索引上的索引項加鎖來實現的;- 這一點於
Oracle
不同,Oracle
是通過在數據塊中對相應數據行加鎖來實現的; InnoDB
這種行鎖實現特點意味着:只有通過索引條件檢索數據,InnoDB
才使用行級鎖,否則默認使用表級鎖。
六. 存儲過程
1. 什麼是存儲過程?
- 存儲過程是一個預編譯的
SQL
語句,優點是允許模塊化的設計,就是說只需創建一次,以後在該程序中就可以調用多次。如果某次操作需要執行多次SQL
,使用存儲過程比單純SQL
語句執行要快。
2. 存儲過程的優缺點?
- 優點:
①:存儲過程是預編譯過的,執行效率高。
②:存儲過程的代碼直接存放於數據庫中,通過存儲過程名直接調用,減少網絡通訊。
③:安全性高,執行存儲過程需要有一定權限的用戶。
④:存儲過程可以重複使用,可減少數據庫開發人員的工作量。 - 缺點:移植性差
七. 數據庫範式
1. 第一範式
- 數據表中的每一列(字段),必須是不可拆分的最小單元,也就是確保每一列的原子性,而不是集合。比如:有一個列是
三年一班
,則可拆分爲三年
和一班
;
2. 第二範式
- 數據庫表中不存在非關鍵字段對任一候選關鍵字段的部分函數依賴,也即實體的每個非主鍵屬性完全函數依賴於主鍵屬性。
- 部分依賴:當主鍵由兩個或兩個以上字段構成,而表中的某些信息通過主鍵的一個字段就能唯一確定,我們稱這樣的依賴關係爲部分依賴。
- 學生課程表(學號,姓名,專業,課程號,課程名,成績),該表中一個學生可以選多門課,一門課有多個學生。學號和課程號可以唯一確定一條記錄,因此用學號和課程號做主鍵。
- 表中的姓名、專業通過主鍵中的學號就能唯一確定,而課程名通過課程號唯一確定,這就是部分依賴,這樣的設計不符合第二範式。
- 不符合第二範式會帶來以下問題:
- ①:數據信息冗餘,比如表中專業被存儲了很多次;
- ②:增刪改會出現問題,比如準耶名字更改了,要修改很多地方。
3. 第三範式
- 在滿足第二範式的基礎上,在實體中不存在非主鍵屬性傳遞函數依賴於主鍵屬性。(表中字段[非主鍵]不存在對主鍵的傳遞依賴)。
- 比如學生宿舍表(學號,姓名,性別,系號,系名,宿舍號,宿舍電話)。
學號–>姓名,性別
,系號–>決定系名
,宿舍號–>決定宿舍電話
,也有學號–>系名
,學號–>宿舍電話
。- 在這樣一張表中則存在着傳遞依賴。也就是系名依賴系號,系號依賴學號,那麼間接的系名依賴學號,宿舍號、宿舍電話和學號之間也有同樣的關係。這樣設計表的同樣會帶來數據冗餘,操作異常等問題。
- 同樣可以用關係分解的分解的方法來消除傳遞依賴,將這張表分成三張表。