高性能MySQL 第一章 MySQL架構(gòu)與歷史

從我的個人博客訪問

MySQL的特性是它的存儲引擎架構(gòu)

這種設計將查詢處理(Query Processing)及其他系統(tǒng)任務(Server Task) 和數(shù)據(jù)的存儲/提取相分離辩涝。

在使用時根據(jù)具體情況選擇存儲引擎衰腌。

MySQL邏輯架構(gòu)

MySQL服務器邏輯架構(gòu)圖

由上圖可以主要分為三層:

第一層架構(gòu) 主要功能:連接處理新蟆,授權認證,安全等右蕊。

第二層架構(gòu) 大多數(shù)MySQL的核心服務都在這一層:查詢解析琼稻、分析、優(yōu)化饶囚、緩存以及所有的內(nèi)置函數(shù)(eg: 日期帕翻、時間、數(shù)學萝风、加密等函數(shù))嘀掸,所有跨存儲引擎的功能都在這一層實現(xiàn):存儲過程、觸發(fā)器规惰、視圖等横殴。

第三層架構(gòu) 包含了存儲引擎 負責MySQL中數(shù)據(jù)的存儲和提取。 服務器通過API與存儲引擎進行通信卿拴,API屏蔽了不同引擎之間的差異衫仑。

連接管理與安全性

每個客戶端連接都會在服務器進程中擁有一個線程,這個連接的查詢只會在這個單獨的線程中執(zhí)行堕花。

服務器會緩存線程或者使用線程池技術文狱,不需要為每個連接創(chuàng)建一個線程,因而使用較少的線程來服務大量的連接缘挽。

當客戶連接服務器的時候瞄崇,服務器會對其進行認證呻粹,基于用戶名、密碼苏研、主機信息等浊。

客戶連接上服務器,執(zhí)行某個操作時摹蘑,服務器會對其進行權限判斷筹燕,判斷該用戶是否有權限進行該項操作。

優(yōu)化與執(zhí)行

MySQL會解析查詢,并創(chuàng)建解析樹衅鹿,然后對其進行各種優(yōu)化撒踪,包括重寫查詢、決定表的讀取順序大渤,以及選取合適的索引等制妄。

用戶可以使用特殊的關鍵字提示(hint)優(yōu)化器,影響其決策過程耕捞。

也可以請求優(yōu)化器解釋(explain)優(yōu)化過程,讓客戶知道服務器如何進行優(yōu)化俺抽。

以便用戶修改查詢和schema纬霞、修改相關配置驱显,使之高效運行。

優(yōu)化器并不關心表使用的是什么存儲引擎埃疫,但存儲引擎對于優(yōu)化查詢是有影響的。

對于SELECT語句栓霜,在解析查詢之前翠桦,服務器會先檢查查詢緩存(Query Cache),如果能找到對應的查詢,服務器就會直接返回查詢緩存中的結(jié)果集胳蛮。


并發(fā)控制

無論何時销凑,只要有多個查詢需要在同一時刻修改數(shù)據(jù),就會產(chǎn)生并發(fā)控制問題仅炊。

MySQL的并發(fā)控制包含兩個層面: 服務器層和存儲引擎層

MySQL的并發(fā)控制主要靠機制解決斗幼。

讀寫鎖

讀鎖(read lock) 也叫 共享鎖(shared lock)

寫鎖(write lock) 也叫 排他鎖(exclusive lock)

讀鎖是共享的,是相互不阻塞的抚垄。多個客戶可以同時讀取同一個資源而不受干擾蜕窿。

寫鎖是排他的谋逻,一個寫鎖會阻塞其他的讀鎖和寫鎖。

在實際的數(shù)據(jù)庫系統(tǒng)中桐经,每時每刻都會發(fā)生鎖定毁兆。大多數(shù)時候,MySQL鎖的內(nèi)部管理都是透明的阴挣。

鎖粒度

加鎖會消耗資源气堕。鎖的各種操作,包括獲得鎖屯吊,檢查所是否解除送巡,釋放鎖,都會增加系統(tǒng)開銷盒卸。

鎖的粒度越小骗爆,就能對修改的數(shù)據(jù)片進行更精確的鎖定,系統(tǒng)的并發(fā)程度就越高蔽介,但是系統(tǒng)的開銷就越大摘投。

表鎖(table lock)

表鎖是MySQL中最基本的一種鎖策略,并且是開銷最小的策略,它會鎖定整張表虹蓄。

當一個用戶在對表進行寫操作(插入犀呼、刪除、更新等)前薇组,需要先獲取寫鎖外臂,這會阻塞其他用戶對該表的所有讀寫操作细移。

只有在沒有寫鎖時恩袱,其他用戶才能獲得讀鎖旬牲。

盡管存儲引擎可以管理自己的鎖虫几,MySQL本身還是會使用各種有效的表鎖來實現(xiàn)不同的目的赘艳。

比如蕾管,服務器會為諸如ALTER TABLE之類的語句使用表鎖娇掏,而忽略存儲引擎的鎖機制勋眯。

行級鎖(row lock)

行級鎖可以最大程度的支持并發(fā)操作(同時也帶來了最大的鎖開銷)

行級鎖只在存儲引擎層次實現(xiàn),而在MySQL服務器層沒有實現(xiàn)孽江,服務器層完全不了解存儲引擎中的鎖實現(xiàn)岗屏。

所有存儲引擎都以自己的方式實現(xiàn)了鎖機制漱办。


事務

事務就是一組原子性的SQL查詢,或者說一個獨立的工作單元暇屋。

事務內(nèi)的語句咐刨,要么全部成功扬霜,要么全部失敗著瓶。

事務的ACID特性材原,表示原子性(atomicity)华糖、一致性(consistency)瘟裸、隔離性(isolation)话告、永久性(durability)

用戶可以根據(jù)業(yè)務是否需要事務處理沙郭,來選擇合適的存儲引擎病线。

對于不需要事務的查詢類應用鲤嫡,可以選擇一個非事務型的存儲引擎暖眼。

隔離級別

在SQL標準中定義了4種隔離級別诫肠,每一種級別都規(guī)定了一個事務中所做的修改栋豫,哪些在事務內(nèi)和事務間是可見的丧鸯,哪些是不可見的骡送。

較低級別的隔離通乘猓可以執(zhí)行更高的并發(fā)派敷,系統(tǒng)的開銷也更低篮愉。

READ UNCOMMITTED (未提交讀)

在這個級別试躏,事務中的修改设褐,即便沒有提交助析,對其他事務也是可見的外冀。事務可以讀取未提交的數(shù)據(jù)雪隧,這也被成為臟讀(Dirty Read)

這個級別會導致很多問題,性能也不會比別的級別好很多藕畔,也沒有別的級別的優(yōu)點劫流,實際應用中很少使用祠汇。

READ COMMITTED (提交讀)

大多數(shù)數(shù)據(jù)庫系統(tǒng)的默認隔離級別都是這個(mysql不是)可很。

在這個級別,一個事務開始時苇本,只能‘看到’已經(jīng)提交的事務所作的修改瓣窄。即:一個事務從開始知道提交之前俺夕,所作的修改對其他事務都是不可見的劝贸。

場景:

在一個事務內(nèi)映九,多次讀同一個數(shù)據(jù)件甥。在這個事務還沒有結(jié)束時言缤,另一個事務也訪問該同一數(shù)據(jù)管挟。
那么僻孝,在第一個事務的兩次讀數(shù)據(jù)之間。
由于第二個事務的修改您单,那么第一個事務讀到的數(shù)據(jù)可能不一樣虐秦。
這樣就發(fā)生了在一個事務內(nèi)兩次讀到的數(shù)據(jù)是不一樣的悦陋。

因而這個級別有時候也叫做不可重復讀

REPEATABLE READ (可重復讀)

這個級別是MySQL默認的事務隔離級別

這個級別解決了臟讀的問題俺驶,保證在同一個事務中的多次讀取同樣記錄的結(jié)果是一致的暮现,但是該級別無法解決幻讀(Phantom Read)的問題

所謂幻讀:就是當一個事務在讀取某個范圍的記錄時栖袋,另一個事務又在該范圍插入了新的記錄抚太,之前的事務再次讀取該范圍的數(shù)據(jù)時凭舶,會產(chǎn)生幻行(Phantom Row)

SERIALIZABLE (可串行化)

這個級別是最高的隔離級別帅霜,它通過強制事務串行執(zhí)行身冀,避免了前面的幻讀的的問題。

其他的隔離級別中珍促,各個事務還是有一定程度的并發(fā)執(zhí)行猪叙。

可串行化會在讀取的每一行數(shù)據(jù)上都加鎖穴翩,可能會導致大量的超時和鎖爭用的問題芒帕,實際中很少使用背蟆。

隔離級別 臟讀可能性 不可重復讀可能性 幻讀可能性 加鎖讀
READ UNCOMMITTED YES YES YES NO
READ COMMITTED NO YES YES NO
REPEATABLE READ NO NO YES NO
SERIALIZABLE NO NO NO YES

死鎖

死鎖是指兩個或者多個事務在同一資源上相互占用冠场,并請求鎖定對方占用的資源碴裙,從而導致惡性循環(huán)的現(xiàn)象点额。

當多個事務試圖以不同的順序鎖定資源時还棱,就可能產(chǎn)生死鎖珍手。

多個事務同時鎖定同一個資源時琳要,也會產(chǎn)生死鎖稚补。

例如下面兩個事務同時處理 StockPrice表:

事務1

    START TRANSACTION;
    UPDATE StockPrice SET close = 45.50 WHERE stock_id = 4;
    UPDATE StockPrice SET close = 19.80 WHERE stock_id = 5;
    COMMIT;

事務2

    START TRANSACTION;
    UPDATE StockPrice SET close = 19.80 WHERE stock_id = 5;
    UPDATE StockPrice SET close = 45.50 WHERE stock_id = 4;
    COMMIT;

如果剛好兩個事務都執(zhí)行了第一條UPDATE語句课幕,更新了一條數(shù)據(jù)乍惊,同時也鎖定了該行數(shù)據(jù)。

然后每個事務都嘗試去執(zhí)行第二條UPDATE語句撬碟,發(fā)現(xiàn)已經(jīng)被對方鎖定小作,然后都等待對方釋放鎖顾稀,又都同時持有對方需要的鎖静秆,則陷入死循環(huán)抚笔。除非有外部接入才可能解除死鎖殊橙。

為了解決這個問題狱从,數(shù)據(jù)庫系統(tǒng)實現(xiàn)了各種死鎖檢測和死鎖超時機制季研。

死鎖發(fā)生后与涡,只有部分或者完全回滾其中一個事務驼卖,才能打破死鎖。

InnoDB處理死鎖的辦法是:將持有最少行級排他鎖的事務進行回滾儒飒。

事務日志

使用事務日志桩了,存儲引擎在修改表的數(shù)據(jù)時只需要修改其內(nèi)存拷貝井誉,再把該修改行為記錄到持久在硬盤的事務日志中颗圣,不用每次都把修改的數(shù)據(jù)持久到磁盤。

事務采用追加的方式奔则,因此寫日志是對磁盤上一小塊位置的順序IO易茬,速度較快及老。

事務日志持久化之后,內(nèi)存中被修改的數(shù)據(jù)在后臺可以慢慢的刷回到磁盤食铐。如果系統(tǒng)崩潰虐呻,存儲引擎在重啟時可以根據(jù)事務日志恢復數(shù)據(jù)铃慷。

這種稱之為預寫式日志(Write-Ahead Logging),修改數(shù)據(jù)需要寫兩次磁盤蜕该。

MySQL中的事務

MySQL提供了兩種事務型的存儲引擎:InnoDB 和 NDB Cluster堂淡。

自動提交 (AUTOCOMMIT)

MySQL默認采用自動提交模式绢淀。也就是說,如果不是顯示的開始一個事務覆履,則每個查詢都被當做一個事務執(zhí)行操作硝全。

在當前連接中伟众,可以通過設置 AUTOCOMMIT 變量來啟用或者禁用自動提交模式召廷。

    SHOW VARIABLES LIKE 'AUTOCOMMIT';
Variable_name Value
autocommit ON

對于非事務型的表,相當于一直處于AUTOCOMMIT的狀態(tài)治泥。

MySQL可以通過執(zhí)行 SET TRANSACTION ISOLATION LEVEL XXX 命令來設置隔離級別遮精,新的隔離級別會在下一個事務開始時生效仑鸥。

可以在配置文件中設置整個數(shù)據(jù)庫的隔離級別眼俊,也可以只改變當前會話的隔離級別:

    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMIT 

在事務中混合使用存儲引擎

MySQL服務器層不管理事務疮胖,事務是由下層的存儲引擎實現(xiàn)的闷板。所以在同一個事務中使用多種存儲引擎是不可靠的遮晚。

如果在事務中混合使用了事務型和非事務型存儲引擎县遣,在正常提交的情況下不會有什么問題。

但是如果該事務需要回滾其兴,非事務型的表上的變更無法撤銷元旬。

在非事務型的表上執(zhí)行事務相關操作的時候守问,MySQL通常不會發(fā)出提醒耗帕,也不會報錯,只有在回滾的時候才會發(fā)一個警告:‘某些非事務型的表上的變更無法被回滾’徙赢。

隱式和顯示鎖定

InnoDB會根據(jù)隔離級別在需要的時候自動加鎖狡赐,這種鎖定叫做隱式鎖定枕屉。

另外,InnoDB也支持通過特定的語句進行顯示鎖定西潘,這些語句不屬于SQL規(guī)范喷市。

    SELECT ... LOCK IN SHARE MODE
    SELECT ... FOR UPDATE

MySQL也支持 LOCK TABLESUNLOCK TABLES 語句品姓,這是在服務器層實現(xiàn)的腹备,與存儲引擎無關植酥,不能替代事務處理友驮。

但是建議任何時候都不要顯示的執(zhí)行 LOCK TABLES喊儡。


多版本并發(fā)控制

MySQL的大多數(shù)事務型存儲引擎實現(xiàn)的都不是簡單的行級鎖艾猜〈以撸基于提升并發(fā)性能的考慮算柳,一般都實現(xiàn)了 多版本并發(fā)控制(MVCC)姓言。

不僅是MySQL,包括Oracle、PostgreSQL等其他數(shù)據(jù)庫系統(tǒng)都實現(xiàn)了MVCC,但實現(xiàn)的機制不盡相同猪杭,因為MVCC沒有統(tǒng)一的實現(xiàn)標準皂吮。

MVCC可以認為是行級鎖的一個變種蜂筹,在很多情況下避免了加鎖操作艺挪,因此開銷更低闺属。

雖然實現(xiàn)機制不同,但大都實現(xiàn)了非阻塞的讀操作亚皂,寫操作也只鎖定必要的行狞谱。


Mysql的存儲引擎

InnoDB 存儲引擎

InnoDB存儲引擎是MySQL自5.5版本以來的默認事務型引擎跟衅,也是最重要伶跷、使用最廣泛的存儲引擎叭莫。

它被設計用來處理大量的短期事務雇初,在非事務行的存儲的需求中也很流行靖诗。

除非有非常特別的原因需要使用其他的存儲引擎刊橘,否則應該優(yōu)先考慮使用InnoDB引擎。

MyISAM 存儲引擎

在MySQL5.1及之前的版本伤为,MyISAM是默認的存儲引擎咒循,MyISAM不支持事務和行級鎖。

其他存儲引擎

Archive引擎

Archive存儲引擎只支持INSERT和SELECT操作

Backhole引擎

Backhole沒有實現(xiàn)任何的存儲機制绞愚,他會丟棄所有插入的數(shù)據(jù)叙甸,不做保存,服務器會記錄Backhole表的日志位衩。

CSV引擎

CSV引擎可以將普通的csv文件作為MySQL的表來處理裆蒸,但是這種引表不支持索引。

Memory引擎

Memory引擎數(shù)據(jù)保存在內(nèi)存中糖驴,查詢速度快僚祷,但是重啟之后數(shù)據(jù)丟失,表結(jié)構(gòu)還會保留贮缕。

NDB集群引擎

MySQL服務器,NDB集群存儲引擎,以及分布式的、share-nothing的雏搂、容災的线椰、高可用的NDB數(shù)據(jù)庫的組合烦绳,被稱為MySQL集群(MySQL Cluster)享扔。

第三方存儲引擎

MySQL從2007年開始提供插件式的存儲引擎API,從此產(chǎn)生了許多為不同目的而設計的存儲引擎

主要有: OLTP類引擎于个、 面向列的存儲引擎羽氮、社區(qū)存儲引擎 等尤筐。

選擇合適的存儲引擎

大多數(shù)情況下,InnoDB都是正確的選擇。

只有遇到一些比較特殊的需求時,才會考慮用其他引擎。


Mysql時間線

版本 時間 說明
版本3.23 2001 這個版本的發(fā)布被認為是Mysql真正誕生的時刻软能,以MyISAM引擎代替之前的ISAM引擎,引入全文索引和復制
版本4.0 2003 支持UNION和多表DELETE語法叛买,重寫了復制难礼,InnoDB成為標配
版本4.1 2005 支持子查詢和INSERT ON DUPLICATE KEY UPDATE,支持UTF-8字符集
版本5.0 2006 支持視圖谦炬、觸發(fā)器吼鳞、存儲過程和存儲函數(shù),ISAM代碼被徹底移除
版本5.1 2008 支持分區(qū)、基于行的復制以及Plugin API
版本5.5 2010 InnoDB成為默認的存儲引擎

1995 MySQL AB公司創(chuàng)建蜓氨。

2008年 MySQL AB公司被SUN收購

2010年 SUN公司被Oracle收購

隨著MySQL被Oracle收購,許多公司開始尋找替代品。

倒向MariaDB: 谷歌(2013年9月) RedHat(2013年6月) 維基百科(2013年4月)

倒向PostreSQL: 蘋果(2011年)


最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谎懦,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡摩瞎,警方通過查閱死者的電腦和手機喜颁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茂装,“玉大人,你說我怎么就攤上這事⊥郑” “怎么了笛丙?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵激涤,是天一觀的道長般贼。 經(jīng)常有香客問我叠洗,道長,這世上最難降的妖魔是什么访递? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任灾炭,我火速辦了婚禮,結(jié)果婚禮上请唱,老公的妹妹穿的比我還像新娘勋功。我一直安慰自己信不,他們只是感情好梭姓,可當我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布祭刚。 她就那樣靜靜地躺著涡驮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪辜膝。 梳的紋絲不亂的頭發(fā)上忱辅,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天场躯,我揣著相機與錄音吠架,去河邊找鬼俱诸。 笑死菠劝,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的睁搭。 我是一名探鬼主播赶诊,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼园骆!你這毒婦竟也來了舔痪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤遇伞,失蹤者是張志新(化名)和其女友劉穎辙喂,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸠珠,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡巍耗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了渐排。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炬太。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖驯耻,靈堂內(nèi)的尸體忽然破棺而出亲族,到底是詐尸還是另有隱情,我是刑警寧澤可缚,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布霎迫,位于F島的核電站,受9級特大地震影響帘靡,放射性物質(zhì)發(fā)生泄漏知给。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望涩赢。 院中可真熱鬧戈次,春花似錦、人聲如沸筒扒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽花墩。三九已至悬秉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間观游,已是汗流浹背搂捧。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留懂缕,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓王凑,卻偏偏與公主長得像搪柑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子索烹,可洞房花燭夜當晚...
    茶點故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容