1.1 MySQL邏輯架構? *
No.1 客戶端、連接/線程處理
連接處理
授權認證
安全
No.2 解析器、查詢緩存
查詢解析、分析、優化、緩存
內置函數
跨存儲引擎:存儲過程、觸發器、視圖等
No.3 存儲引擎
通過api與服務器通信
響應上層服務器請求
數據的存儲和提取
MySQL存儲引擎(Storage Engine),是指數據的存儲/讀取相關的邏輯模塊。而存儲引擎API(table handler)是指Storage Engine與MySQL優化器間的接口。比如,新增一個存儲引擎,如何實現MySQL服務層對存儲存儲引擎訪問呢?MySQL服務訪問的存儲引擎是接口就是抽象存儲引擎API,新存儲引擎只需要實現相應的抽象存儲引擎API接口,就可以實現MySQL Service對存儲引擎的訪問。
MySQL插件式存儲引擎架構,促使MySQL以更加開放的姿態,接受更多的存儲引擎。抽象存儲引擎接口是在v3.22提升到v3.23時引入的設計。在快速集成InnoDB存儲引擎階段中起了很大的作用。
抽象存儲引擎API接口是通過抽象類handler來實現,handler類提供諸如打開/關閉table、掃表、查詢Key數據、寫記錄、刪除記錄等基礎操作方法。每一個存儲引擎通過繼承handler類,實現以上提到的方法,在方法里面實現對底層存儲引擎的讀寫接口的轉調。從5.0版本開始,為了避免在初始化、事務提交、保存事務點、回滾操作時需要操作one-table實例,引入了handlerton結構讓存儲引擎提供了發生上面提到操作時的鉤子操作。
作者:itopcat來源:CSDN原文:https://blog.csdn.net/itopcat/article/details/73614101
1.2 并發控制
只要有多個查詢需要在同一時刻修改數據,都會產生并發問題,我們一般用鎖來解決。
1.2.1 讀寫鎖
共享鎖:讀鎖(read lock)互相不阻塞
排他鎖:寫鎖(write lock)
寫鎖 > 讀鎖
1.2.2 鎖粒度
表鎖(table lock)
服務層? > 存儲引擎
行級鎖(row lock)
存儲引擎實現、服務層沒有必要
最大程度地支持并發處理(同時也帶來了鎖開銷)
1.3 事務
事務的特性(ACID):
原子性(atomicity)事務中所有操作要么全部成功,要不全部失敗回滾
一致性(consistency)一致性的狀態轉換到另一個一致性的狀態,不會因為其中一條語句崩潰而影響其他。
隔離性(isolation)通常來說,一個事務在最終提交之前,對其他事務是不可見的
持久性(durability)一旦事務提交,則其所做的修改就會永久保存到數據庫中。即使系統崩潰,修改的數據也不會丟失。
隔離級別:
read uncommitted?: 讀取尚未提交的數據 :哪個問題都不能解決2)
read committed:讀取已經提交的數據 :可以解決臟讀 ---- oracle默認的3)
repeatable read:重讀讀取:可以解決臟讀 和 不可重復讀 ---mysql默認的4)
serializable:串行化:可以解決 臟讀 不可重復讀 和 虛讀---相當于鎖表
查看MySQL隔離級別:
SELECT @@tx_isolation
設置MySQL隔離級別
用戶可以用SET TRANSACTION語句改變單個會話或者所有新進連接的隔離級別。它的語法如下:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
1、臟讀:事務A讀取了事務B更新的數據,然后B回滾操作,那么A讀取到的數據是臟數據
2、不可重復讀:事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新并提交,導致事務A多次讀取同一數據時,結果 不一致。
3、幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束后發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。
小結:不可重復讀的和幻讀很容易混淆,不可重復讀側重于修改,幻讀側重于新增或刪除。解決不可重復讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表
要查看詳情及例子可參考
https://www.cnblogs.com/huanongying/p/7021555.html
1.3.2 死鎖
死鎖是指兩個或者多個事務在同一資源上相互占用,并請求鎖定對方占用的資源,從而導致惡性循環的現象:
多個事務以不同順序鎖定資源
多個事務同時鎖定一個資源
避免死鎖的幾種方式:
設置加鎖順序:缺點需要事先知道哪些資源用到鎖,并知道他們之間獲取鎖的順序。
設置加鎖時限:缺點是枷鎖時限的閥值很難去判定
死鎖檢測:缺點是還是會出現和設置加鎖時限相同的問題
設置線程優先級、也可以嘗試隨機設置優先級
解決死鎖,常采用的方法有:
剝奪資源:從其它進程剝奪足夠數量的資源給死鎖進程,以解除死鎖狀態;
撤消進程:可以回滾死鎖進程或撤消代價最小的進程。
一條簡單SQL的加鎖實現分析:
但我自己的實驗 “?RR下的無索引?” 中并沒有出現作者提的MySQL作出優化,而是不提交的情況下一直在等待前者提交。
參考:http://hedengcheng.com/?p=771 作者:何登成
1.3.3 事務日志
事務日志可以幫助提高事務的效率。使用事務日志在修改表的數據時只需要修改其內容拷貝,再把該修改記錄到持久硬盤上的事務日志中,而不用每次都將修改的數據本身持久到磁盤。
事務日志采用的是追加的方式,因此寫日志的操作是磁盤順序I/O,而不像隨機I/O需要在磁盤的多個地方移動磁頭,所以采用事務日志的方式相對來說要快得多。
事務日志持久以后,內存中被修改的數據在后臺可以慢慢地刷回到磁盤。
1.3.4 MySQL 中的事務
1、MySQL提供了兩種事務型的存儲引擎:Innodb 和NDB Cluster;另外還有一些第三方存儲引擎也支持事務。
2、MySQL默認采用 自動提交 ,如果不是顯式地開始一個事務,則每個查詢都被當作一個事務執行提交操作:
show variables like 'AUTOCOMMIT’;????查看當前自動提交狀態
set? AUTOCOMMIT = 0;(0為關閉狀態,1為開啟狀態)臨時設置(僅對當前客戶端可用)
3、MySQL 服務器層不管理事務,事務是由下層的存儲引擎實現的。所以在事務中混合使用存儲引擎是不可靠的。
4.隱式和顯式鎖定。在執行事務過程中,執行鎖定都是隱式鎖定。一些特定的語句:
SELECT...LOCK IN SHARE MODE
SELECT...FOR UPDATE
LOCK TABLES?等都是顯示鎖定。
通常不建議使用這些語句,特別不建議使用LOCK TABLES,因為它和事務之間相互影響的話,情況會變得非常復雜。
1.4 多版本并發控制
MySQL 的大多數事務型存儲引擎實現的都不是簡單的行級鎖。基于提升并發性能的考慮,它們一般都同時實現了多版本并發控制(MVCC)。
可以認為MVCC是行級鎖的一個變種,它在很多情況下避免了加鎖操作,因此開銷更低。
MVCC的實現,是通過保存數據在某個時間點的快照來實現的。開始的時間不同,每個事務對同一資源看到的情況是可能不同的。
不同存儲引擎的MVCC的實現是不同的,典型的有 樂觀并發控制 和 悲觀并發控制。
InoDB的MVCC,是通過在每行記錄后面保存兩個隱藏的列來實現的。一個保存了行的創建時間,一個保存行的過期時間。當然存儲的并不是實際的時間,而是系統版本號。每開始一個新的事務,系統版本號就會遞增,作為事務的版本號,用來和查詢到的每行記錄的版本號進行比較。
以下看看MVCC具體是如何操作的:
SELECT:
a. InnoDB 只查找早于或者等于當前事務版本的數據行,這樣可以確保事務讀取的行,要么是在事務開始前存在的,要么是事務自身插入或者修改過的。
b.行的刪除版本要么未定義,要么大于當前事務版本號,確保事務讀取到的行,在事務開始之前未被刪除。
INSERT:
InnoDB 為新插入的每一行保存當前系統版本號作為行版本號。
DELETE
InnoDB 為刪除的每一行保存當前系統版本號作為行刪除標識。
UPDATE
InnoDB 為插入一行新記錄,保存當前系統版本號作為行版本號,同時保存當前系統版本號到原來的行作為行刪除標識。
保存這兩個額外的系統版本號,使大多數讀操作都可以不加鎖、操作簡單、性能號;不足之處就是需要額外的存儲空間,以及一些額外的維護工作。