重溫《高效能MySQL》的第一章MySQL架構與歷史
1.1 MySQL邏輯架構
參考
圖1-1:MySQL伺服器邏輯架構圖
最上層的服務並不是MySQL所獨有的,大多數基於網路的客戶端/伺服器的工具或服務都有類似的架構。例如連線處理、授權認證、安全性等等。
第二層架構是MySQL比較有趣的部分。大多數MySQL的核心服務功能都在這一層,包括查詢解析、分析、最佳化、快取以及所有的內建函數(例如,日期、時間、數學和加密函數),所有跨儲存引擎的功能都在這一層實作:預存程序、觸發器、視圖等。
第三層包含了儲存引擎。儲存引擎負責MySQL中資料的儲存和提取。和GNU/Linux下的各種檔案系統一樣,每個儲存引擎都有它的優點和缺點。伺服器透過API與儲存引擎通訊。這些介面屏蔽了不同儲存引擎之間的差異,使得這些差異對上層的查詢流程變得透明。儲存引擎API包含數十個底層函數,用於執行諸如「開始一個交易」或「根據主鍵提取一行記錄」等操作。但儲存引擎不會去解析SQL,不同儲存引擎之間也不會互相通信,而只是簡單地回應上層伺服器的請求。
1.2 並發控制
1.2.1 讀寫鎖定
這兩種類型的鎖定通常稱為共享鎖定(shared lock)和排他鎖定(exclusive lock) ,也叫讀鎖(read lock)和寫鎖(write lock)。讀鎖是共享的,或者說是互相不阻塞的。多個客戶在同一時刻可以同時讀取同一個資源,而互不干擾。寫鎖則是排他的,也就是說一個寫鎖會阻塞其他的寫鎖和讀鎖。
1.2.2 鎖定粒度
兩個最重要的鎖定策略:表鎖定與行級鎖定
表格鎖定(table lock)
# 表鎖是MySQL中最基本的鎖定策略,也是開銷最小的策略。它會鎖定整張表。一個使用者在對錶進行寫入操作(插入、刪除、更新等)前,需要先取得寫鎖,這會阻塞其他使用者對該表的所有讀寫操作。只有沒有寫鎖時,其他讀取的使用者才能獲得讀鎖,讀鎖之間是不互相阻塞的。
在特定的場景中,表鎖也可能有良好的效能。例如,READ LOCAL表鎖支特某些類型的並發寫入操作。另外,寫鎖也比讀鎖有更高的優先權,因此一個寫鎖請求可能會被插入到讀鎖佇列的前面(寫鎖可以插入到鎖佇列中讀鎖的前面,反之讀鎖則不能插入到寫鎖的前面)。
行級鎖定( row lock)
行級鎖定可以最大程度地支援並發處理(同時也帶來了最大的鎖開銷)。眾所周知,在InnoDB和XtraDB,以及其他一些儲存引擎中實現了行級鎖定。行級鎖只在儲存引擎層實現,而MySQL伺服器層沒有實現。伺服器層完全不了解儲存引擎中的鎖實作。
1.3 事務
事務支援ACID原則。
原子性(atomicity)
一個交易必須被視為一個不可分割的最小工作單元。
一致性(consistency)
資料庫總是從一個一致性的狀態轉換到另一個一致性的狀態。
隔離性(isolation)
通常來說,一個事務所所做的修改在最終提交以前,對其他事務是不可見的。
持久性(durability)
一旦交易提交,則其所做的修改就會永久保存到資料庫中。
1.3.1 隔離等級
以下簡單介紹四種隔離等級。
READ UNCOMMITTED(未提交讀取)
在READ UNCOMMITTED級別,事務中的修改,即使沒有提交,對其他事務也都是可見的。事務可以讀取未提交的數據,這也被稱為髒讀(Dirty Read)。這個等級會導致很多問題,從效能上來說,READ UNCOMMITTED不會比其他的等級好太多,但卻缺乏其他等級的許多好處,除非真的有非常必要的理由,在實際應用中一般很少使用。
READ COMMITTED(提交讀取)
大多數資料庫系統的預設隔離等級都是READ COMMITTED(但MySQL不是)。一個事務從開始直到提交之前,所做的任何修改對其他事務都是不可見的。這個等級有時候也叫做不可重複讀(nonrepeatable read),因為兩次執行同樣的查詢,可能會得到不一樣的結果。
REPEATABLE READ(可重複讀取)
REPEATABLE READ解決了髒讀取的問題。此等級保證了在同一個事務中多次讀取同樣記錄的結果是一致的。但理論上,可重複讀取隔離等級還是無法解決另一個幻讀 (Phantom Read)的問題。所謂幻讀,指的是當某個事務在讀取某個範圍內的記錄時,另外一個事務又在該範圍內插入了新的記錄,當之前的事務再次讀取該範圍的記錄時,會產生幻行(Phantom Row)。 InnoDB和XtraDB儲存引擎透過多版本並發控制(MVCC,Multiversion Concurrency Control)解決了幻讀的問題。
可重複讀取是MySQL的預設交易隔離等級。
SERIALIZABLE(可串列化)
SERIALIZABLE是最高的隔離等級。它透過強制事務串列執行,避免了前面說的幻讀的問題。簡單來說,SERIALIZABLE會在謨取的每一行資料上都加鎖,所以可能會導致大量的逾時和鎖爭用的問題。實際應用中也很少用到這個隔離級別,只有在非常需要確保資料的一致性而且可以接受沒有並發的情況下,才考慮採用該級別。
1.3.2 死鎖
死鎖是指兩個或多個事務在同一資源上相互佔用,並請求鎖定對方佔用的資源,從而導致惡性循環的現象。當多個事務試圖以不同的順序鎖定資源時,就可能會產生死鎖。多個事務同時鎖定同一個資源時,也會產生死鎖。
為了解決這個問題,資料庫系統實作了各種死鎖偵測和死鎖逾時機制。越複雜的系統,例如InnoDB儲存引擎,越能偵測到死鎖的循環依賴,並立即回傳一個錯誤。這種解決方式很有效,否則死鎖會導致出現非常慢的查詢。還有一種解決方式,就是當查詢的時間達到鎖等待超時的設定後放棄鎖定請求,這種方式通常來說不太好。 InnoDB目前處理死鎖的方法是,將持有最少行級排他鎖的事務進行回滾(這是相對比較簡單的死鎖回滾演算法)。
鎖的行為和順序是和儲存引擎相關的。以同樣的順序執行語句,有些儲存引擎會產生死鎖,有些則不會。死鎖的產生有雙重原因:有些是因為真正的資料衝突,這種情況通常很難避免,但有些則完全是由於儲存引擎的實現方式導致的。
1.3.3 交易日誌
使用交易日誌,儲存引擎在修改表的資料時只需要修改其記憶體拷貝,再把該修改行為記錄到持久在硬碟上的交易日誌中,而不用每次都將修改的資料本身持久到磁碟。交易日誌採用的是追加的方式。交易日誌持久以後,記憶體中被修改的資料在後台可以慢慢地刷回到磁碟。目前大多數儲存引擎都是這樣實現的,我們通常稱為預寫式日誌(Write-Ahead Logging),而修改資料需要寫兩次磁碟。
如果資料的修改已經記錄到交易日誌並且持久化,但資料本身還沒有寫回磁碟,此時系統崩潰,儲存引擎在重新啟動時能夠自動恢復這部分修改的資料。具體的恢復方式則視儲存引擎而定。
1.3.4 MySQL中的交易
1.4 多版本並發控制
MVCC的實現,是透過保存資料在某個時間點的快照來實現的。也就是說,不管需要執行多長時間,每個事務看到的資料都是一致的。根據事務開始的時間不同,每個事務對同一張表,同一時刻看到的資料可能是不一樣的。下面我們透過InnoDB的簡化版行為來說明MVCC是如何運作的。
InnoDB的MVCC,是透過在每行記錄後面保存兩個隱藏的列來實現的。這兩個列,一個保存了行的建立時間,一個保存行的過期時間(或刪除時間)。當然儲存的並不是實際的時間值,而是系統版本號(system version number)。每開始一個新的事務,系統版本號就會自動遞增。事務開始時刻的系統版本號碼會作為事務的版本號,用來和查詢到的每行記錄的版本號進行比較。以下來看看在REPEATABLE READ隔離等級下,MVCC具體是如何操作的。
SELECT
InnoDB會依照下列兩個條件檢查每行記錄:
a. InnoDB只查找版本早於目前事務版本的資料行(也就是,行的系統版本號小於或等於事務的系統版本號),這樣可以確保事務讀取的行,要么是在事務開始前已經存在的,要嘛是事務自身插入或修改過的。
b.行的刪除版本要么未定義,要么大於目前事務版本號。這可以確保事務讀取到的行,在事務開始之前未被刪除。
只有符合上述兩個條件的記錄,才能傳回作為查詢結果。
INSERT
InnoDB為新插入的每一行儲存目前系統版本號碼作為行版本號。
DELETE
InnoDB為刪除的每一行儲存目前系統版本號碼作為行刪除識別。
UPDATE
InnoDB為插入一行新記錄,保存目前系統版本號作為行版本號,同時保存當前系統版本號到原來的行作為行刪除標識。
保存這兩個額外系統版本號,使大多數讀取操作都可以不用加鎖。這樣設計使得讀取資料操作很簡單,效能很好,也能保證只會讀取到符合標準的行。不足之處是每行記錄都需要額外的儲存空間,需要做更多的行檢查工作,以及一些額外的維護工作。
MVCC只在REPEATABLE READ和READ COMMITTED兩個隔離等級下運作。其他兩個隔離等級都和MVCC不相容於註4,因為READ UNCOMMITTED總是讀取最新的資料行,而不是符合目前交易版本的資料行。而SERIALIZABLE則會對所有讀取的行都加鎖。
1.5 MySQL的儲存引擎
在檔案系統中,MySQL將每個資料庫(也可以稱為schema)儲存為資料目錄下的子目錄。建立表格時,MySQL會在資料庫子目錄下建立一個和表格同名的.frm檔案保存表的定義。例如建立一個名為MyTable的表,MySQL會在MyTable.frm檔案中儲存該表的定義。因為MySQL使用檔案系統的目錄和檔案來保存資料庫和表格的定義,大小寫敏感度和具體的平台密切相關。在Windows中,大小寫是不敏感的;而在類別Unix中則是敏感的。不同的儲存引擎保存資料和索引的方式是不同的,但表的定義則是在MySQL服務層統一處理的。
可以使用SHOW TABLE STATUS指令(在MySQL 5.0以後的版本中,也可以查詢INFORMATION SCHEMA中對應的表)顯示表格的相關資訊。例如,對於mysql資料庫中的user表:
mysql> SHOW TABLE STATUS LIKE 'user' \G
Name: user
# Row_format: Dynamic Rows : 6 Avg_row_length: 59 # Index length : 2048 Data_free: 0 Auto_increment: NULL## Create_time: 2002-
## Create_time: 2002-## Create_time: 2002-
## Create_time: 2002-01024 18 01- 24 21: 56 : 29 Check_time: NULL Collation : ut f8_bin### Comment: Users and global privileges
1 row in set (o.oo sec)
榆出的結果表明,這是一個MyISAM表。輸出中還有很多其他資訊以及統計資料。下面簡單介紹一下每一行的含義。
Name
表名。
表的儲存引擎類型。在舊版本中,該列的名字叫Type,而不是Engine。 | |
#行的格式。對於MyISAM表,可選的值為Dynamic、Fixed或Comp ressed。 Dynamic的行長度是可變的,一般包含可變長度的字段,如VARCHAR或BLOB。 Fixed的行長度則是固定的,只包含固定長度的列,如CHAR和INTEGER。 Compressed的行則只存在於壓縮表中。 | |
#表中的行數。對於MyISAM和其他一些儲存引擎,該值是精確的,但對於InnoDB,該值是估計值。 | |
平均每行包含的位元組數。 |
|
Data_length |
#表格資料的大小(以位元組為單位)。 |
Max- data_length |
#表格資料的最大容量,該值和儲存引擎有關。 |
Index_length |
#索引的大小(以位元組為單位)。 |
Data_free |
#對於MyISAM表,表示已指派但目前沒有使用的空間。這部分空間包括了先前刪除的行,以及後續可以被INSERT利用的空間。 |
Auto_increment |
#下一個AUTO INCREMENT的值。 |
Create_time |
#表的建立時間。 |
Update_time |
#表格資料的最後修改時間。 |
Check_ time |
#使用CKECK TABLE指令或myisamchk工具最後一次檢查表的時間。 |
Collation |
表的預設字元集和字元列排序規則。 |
Checksum |
#如果啟用,則儲存的是整個資料表的即時校驗和。 |
Create_options |
#刨建表時指定的其他選項。 |
Comment |
#該欄位包含了一些其他的額外資訊。對於MyISAM表,儲存的是表在建立時所帶的註解。對於InnoDB表,則保存的是InnoDB表空間的剩餘空間資訊。如果是視圖,則該列包含「VIEW」的文字字樣。 |
1.6 MySQL時間軸
1.7 MySQL的發展模式
#
參考:《高效能MySQL》
以上是MySQL架構的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于架构原理的相关内容,MySQL Server架构自顶向下大致可以分网络连接层、服务层、存储引擎层和系统文件层,下面一起来看一下,希望对大家有帮助。

在mysql中,可以利用char()和REPLACE()函数来替换换行符;REPLACE()函数可以用新字符串替换列中的换行符,而换行符可使用“char(13)”来表示,语法为“replace(字段名,char(13),'新字符串') ”。

mysql的msi与zip版本的区别:1、zip包含的安装程序是一种主动安装,而msi包含的是被installer所用的安装文件以提交请求的方式安装;2、zip是一种数据压缩和文档存储的文件格式,msi是微软格式的安装包。

方法:1、利用right函数,语法为“update 表名 set 指定字段 = right(指定字段, length(指定字段)-1)...”;2、利用substring函数,语法为“select substring(指定字段,2)..”。

转换方法:1、利用cast函数,语法“select * from 表名 order by cast(字段名 as SIGNED)”;2、利用“select * from 表名 order by CONVERT(字段名,SIGNED)”语句。

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于MySQL复制技术的相关问题,包括了异步复制、半同步复制等等内容,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了mysql高级篇的一些问题,包括了索引是什么、索引底层实现等等问题,下面一起来看一下,希望对大家有帮助。

在mysql中,可以利用REGEXP运算符判断数据是否是数字类型,语法为“String REGEXP '[^0-9.]'”;该运算符是正则表达式的缩写,若数据字符中含有数字时,返回的结果是true,反之返回的结果是false。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

禪工作室 13.0.1
強大的PHP整合開發環境

SublimeText3漢化版
中文版,非常好用

SublimeText3 Linux新版
SublimeText3 Linux最新版

記事本++7.3.1
好用且免費的程式碼編輯器

Dreamweaver CS6
視覺化網頁開發工具