本文主要給大家介紹MySQL的底層原理之并發(fā)控制,文章內(nèi)容都是筆者用心摘選和編輯的,具有一定的針對性,對大家的參考意義還是比較大的,下面跟筆者一起了解下mysql的底層原理之并發(fā)控制吧。
網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了興寧免費(fèi)建站歡迎大家使用!
1、mysql的邏輯框架
mysql邏輯框架圖如下:
最上層是處理客戶端過來的連接的。
主要做連接處理、授權(quán)認(rèn)證、安全等。Mysql在這一層維護(hù)了一個(gè)線程池,用于處理來自客戶端的連接。Mysql可以使用用戶名密碼認(rèn)證,
也可以使用SSL基于X.509證書認(rèn)證。
第二層由三部分組成:查詢緩存、解析器、優(yōu)化器。解析器用來解析SQL語句,優(yōu)化器會對解析之后的語句進(jìn)行優(yōu)化。
在解析查詢前,云服務(wù)器會先檢查查詢緩存,如果能在其中找到對應(yīng)的查詢結(jié)果,則無需再進(jìn)行查詢解析、優(yōu)化等過程,直接返回查詢結(jié)果。存儲過程、觸發(fā)器、視圖等都在這一層實(shí)現(xiàn)。
第三層是存儲引擎,存儲引擎負(fù)責(zé)在MySQL中存儲數(shù)據(jù)、提取數(shù)據(jù)、開啟一個(gè)事務(wù)等等。存儲引擎通過API與上層進(jìn)行通信,這些API屏蔽了不同存儲引擎之間的差異,使得這些差異對上層查詢過程透明。存儲引擎不會去解析SQL。mysql最常用的存儲引擎是InnoDB。
2、mysql的并發(fā)控制
如果多個(gè)線程同時(shí)操作數(shù)據(jù),就有可能引發(fā)并發(fā)控制的問題。
2-1、讀寫鎖
如果多個(gè)線程都只是讀數(shù)據(jù),其實(shí)可以一起讀,不會互相影響,這個(gè)時(shí)候應(yīng)該使用“讀鎖”,也稱為共享鎖。
獲取讀鎖的線程之間互相不會阻塞,可以同時(shí)讀取一個(gè)資源。
如果有一個(gè)線程需要寫數(shù)據(jù),則應(yīng)該使用“寫鎖”,也成為排它鎖。
寫鎖會阻塞其它的寫鎖和讀鎖,直至寫操作完成。
2-2、鎖粒度
首先明確一個(gè)概念:在給定的資源上,需要加鎖的數(shù)據(jù)越少,系統(tǒng)能夠承載的并發(fā)量就越高。
但加鎖也是需要消耗資源的,如果系統(tǒng)花費(fèi)大量的時(shí)間來管理鎖,而不是存取數(shù)據(jù),
那么系統(tǒng)的性能可能會因此受影響。
所以一個(gè)好的“鎖策略”就是要在鎖的開銷和數(shù)據(jù)的安全性之間尋求平衡,Mysql支持多個(gè)存儲引擎的架構(gòu),
每種存儲引擎都可以實(shí)現(xiàn)自己的鎖策略和鎖粒度。
2-3、表鎖和行鎖
表鎖顧名思義就是鎖住整張表。表鎖開銷比較小。對表加寫鎖后,其它用戶對這張表的所有讀寫操作都會被阻塞。
在Mysql中,盡管存儲引擎可以提供自己的鎖,但Mysql有時(shí)候也會使用表鎖,比如ALTER TABLE之類的語句。
寫鎖比讀鎖有更高的優(yōu)先級,因此一個(gè)寫鎖請求可能會插入到讀鎖隊(duì)列的前面。
行級鎖即鎖住整行,可以最大程度地支持并發(fā)處理,但加解鎖的開銷也會比較大。行級鎖只在儲存引擎層實(shí)現(xiàn),
所有的存儲引擎都以自己的方式實(shí)現(xiàn)了行級鎖。
3、MVCC
MVCC即“多版本并發(fā)控制”,可以認(rèn)為MVCC是行級鎖的一個(gè)變種,但是它在很多情況下避免了加鎖操作,
因此開銷更低。
主流的關(guān)系型數(shù)據(jù)庫都實(shí)現(xiàn)了MVCC,但實(shí)現(xiàn)機(jī)制各有不同。實(shí)際上MVCC也沒有一個(gè)統(tǒng)一的標(biāo)準(zhǔn)。
但大都實(shí)現(xiàn)了非阻塞的讀操作,寫操作也只是鎖定必要的行。
MVCC保證的是每個(gè)事務(wù)里面在執(zhí)行期間看到的數(shù)據(jù)都是一致的。
但不同的事務(wù)由于開始的時(shí)間不同,所以可能對同一張表,同一時(shí)刻看到的數(shù)據(jù)是不一樣的。
在Mysql的InnoDB引擎,是通過給每行記錄后面保存兩個(gè)隱藏的列來實(shí)現(xiàn)的。
一個(gè)是保存行的創(chuàng)建時(shí)間,另一個(gè)保存了行的過期時(shí)間(或刪除時(shí)間)。
實(shí)際上存儲的并不是實(shí)際的一個(gè)時(shí)間戳,而是‘系統(tǒng)版本號’。
每次開啟一個(gè)事務(wù),系統(tǒng)版本號都會遞增。事務(wù)開始時(shí),系統(tǒng)版本號會作為事務(wù)的版本號,用來和查詢到的行的版本號進(jìn)行比較。
下面分別介紹常見的CRUD操作中版本號是怎么工作的:
INSERT
保存當(dāng)前系統(tǒng)版本好的作為行版本號
DELETE
保存當(dāng)前的系統(tǒng)版本號到這行數(shù)據(jù)的“刪除版本”。
UPDATE
插入一行新紀(jì)錄,保存當(dāng)前系統(tǒng)版本號作為航版本號,同時(shí)保存當(dāng)前系統(tǒng)版本號到原來的行的“刪除版本”。
SELECT
只查找版本早于當(dāng)前事務(wù)版本的行。這樣可以保證事務(wù)讀取的行,要么之前就存在,
要么是這個(gè)事務(wù)本身自己插入或者修改的。
行的“刪除版本”要么未定義,要么大于當(dāng)前事務(wù)版本號。這樣可以確保事務(wù)讀取到的行,
在事務(wù)之前沒有被刪除。
MVCC只在REPEATABLE READ
和READ COMMITTED
兩個(gè)隔離級別下工作,其它兩個(gè)隔離級別不能工作。
因?yàn)?code>READ UNCOMMITTED總是讀取最新的數(shù)據(jù)防,而不是符合當(dāng)前事務(wù)版本的數(shù)據(jù)行。而SERIALIZABLE
則會對所有讀取的行都加鎖。
看完以上關(guān)于mysql的底層原理之并發(fā)控制,很多讀者朋友肯定多少有一定的了解,如需獲取更多的行業(yè)知識信息 ,可以持續(xù)關(guān)注我們的行業(yè)資訊欄目的。