第一章、MySQL架構及歷史

前言

Mysql作為目前互聯網工作的主流數據庫,有著其不容撼動的地位,之前面試過一些公司,對于程序員來說,企業對于Mysql的技能要求還是比較高的。所以有必要系統深入研究下Mysql。于是乎就有了這一系列博客的誕生。這些博客內容主要是結合我自己工作中所用的的東西,以及《高性能Myql》這本書的讀書筆記。


購買地址,請支持正版圖書。

1.1、Mysql邏輯結構

  • Mysql是三層的邏輯架構,如下圖


    • 第一層:服務層(為客戶端服務):為請求做連接處理,授權認證,安全等。
    • 第二層:Mysql核心服務層:主要提供,查詢解析、分析、優化、緩存以及內置函數,跨存儲引擎功能(存儲過程、視圖、觸發器)
    • 第三層:存儲引擎層,負責數據的存儲和提取
1.1.1、連接管理與安全性

這里有第一層處理,每個客戶端的連接都會在服務器進程中擁有一個線程,連接的查詢在這個線程中單獨進行。

1.1.2、優化與執行

此處由第二層,中間層處理,該處的優化器負責創建內部數據結構,然后優化,包括重寫查詢,決定表的讀取順序,以及選擇合適的索引。

1.2、并發控制

并發是個老生常談的問題,不管在java還是mysql以及oracle中,都需要保證并發時數據的一致性。面對并發問題,不可避免的都需要用到鎖,并發的優化很多時候也就是鎖的優化。

1.2.1、讀寫鎖
  • 讀鎖:共享,互不阻塞,即多用戶同一時刻讀統一資源,互不干擾。
  • 寫鎖:排他,一個寫鎖會阻塞其他的讀和寫,安全策略只有這樣才能保證同一時刻只有一個用戶能寫入,并防止其他用戶讀取正在寫入的同一資源,避免臟讀。
1.2.2、鎖力度

一種優化的策略,對于不同的鎖提供不同的力度,讓鎖定對象更有選擇性。當然加鎖的操作也增加系統的開銷。包括(獲得鎖,檢查鎖是否解除,是否鎖)。下面介紹兩種最重要的鎖力度

  • 表鎖(table lock)
    顧名思義就是將整張表鎖定,Mysql中最基本的鎖策略,并且是開銷最小的策略,加鎖之后,整個表數據受到影響,不利于并發,寫鎖優先級高于讀鎖,因此一個寫鎖請求可能會被插入到讀鎖的隊列前面。服務器也會使用ALTER TABLE之類的語句使用表鎖。
  • 行級鎖(row lock)
    支持高并發,同事帶來最大的鎖開銷。只有存儲引擎實現,第二層不會實現。

1.3、事務

事務也是數據庫中一個老生常談的問題,我們常常口頭說的ACID,或者可以說是一個獨立的工作單元,對外只有成功和失敗的結果,不會出現部分成功或者失敗。也即提交(commit)或者回退(rollback)兩種操作。

  • A(Atomicity-原子性):不可分割的單元,要么成功,要么失敗。
  • C(Consistency-一致性):主要強調的是,如果在執行事務之前數據庫是一致的,那么在執行事務之后數據庫也還是一致的
  • I(Isolation-隔離性):事務彼此之間沒有影響,即在最終提交前對其他事務不可見
  • D(Durability-持久性):一旦事務提交,其修改會永久保存到數據庫中。

不是所有的數據庫都支持事務,像現在大火的nosql大多都不支持事務,而mysql不同的引擎對事務的支持也不一樣,像默認的InnoDB是支持事務的,而Myisam這一的引擎就不支持事務。這個需要根據業務去做相應的選擇

1.3.1、隔離級別
  • 數據庫提供了四種事務隔離級別, 不同的隔離級別采用不同的鎖類開來實現.
隔離級別 臟讀可能性 不可重復讀可能性 幻讀可能性 加鎖讀
READ UNCOMMITTED YES YES YES NO
READ COMMITED NO YES YES NO
REPEATABLE READ NO NO YES NO
SERIALIZABLE NO NO NO YES
相關概念
  • 臟讀:事務中的修改,即使未提交,對其他事務也是課件的。事務可以讀取未提交的數據。
  • 不可重復讀:在同一個事務中,再次讀取數據時,所讀取的數據,和第1次讀取的數據,不一樣了
  • 幻讀:幻讀的重點在于新增或者刪除,同樣的條件, 第1次和第2次讀出來的記錄數不一樣。
    幻讀是指當一個事務在讀取某個范圍內的數據時,另一個事務在這個范圍內插入了一行記錄并提交,于是當前一個事務再次讀取該范圍內的數據時,發現多出了一行,即幻行。
臟讀、不可重復讀、幻讀的級別高低是:  
臟讀 < 不可重復讀 < 幻讀
所以,設置了最高級別的SERIALIZABLE_READ就不用在設置REPEATABLE_READ和READ_COMMITTED了

  • READ UNCOMMITTED(未提交讀):數據庫中幾乎不用這種事務。
  • READ COMMITED(已提交讀):大多數數據庫的默認隔離級別(MySQL不是)。這個級別代表事務開始后,只能讀到其他事務提交后的修改,未提交的修改是不可見的。顯然這樣就解決了臟讀的問題。但是還是會遇到不可重復讀的問題。
  • REPEATABLE READ(可重復讀):Mysql的默認隔離級別,該級別保證了同一個事務中多次讀取同樣記錄的結果是一致的。
  • SERIALIZABLE(可序列化讀):最高的隔離級別,通過強制事務串行執行,避免了前面說的幻讀問題。該級別會在讀取的每一行上都加鎖,所以可能導致大量的超時和鎖爭用問題。
1.3.2、死鎖

兩個活多個事務在同一資源上相互占用,并請求鎖定對方占用的資源,從而導致惡性循環的現象。
為解決這種問題,數據庫都是些了各種死鎖檢測和死鎖超時機制。

  • 如InnoDB若檢測到死鎖循環依賴,就立即返回一個錯誤。
  • 當查詢時間到鎖等待超時的設定后放棄鎖清秋。
    InnoDB的處理方式是,將持有最少行級排他鎖的事務進行回滾。
1.4、事務日志

由于事務日志的寫入是順序I/O操作,會比隨機I/O快的多。(因為機械硬盤讀寫最費時間的就是磁頭的定位和移動過程)
當數據持久化到事務日志以后,再慢慢地刷寫回真正的數據庫。即使途中服務器掛了,重啟后還是可以根據事務日志來恢復數據。

1.5、MySQL中的事務

MySQL提供了兩種事務的存儲引擎:InnoDB和NDB cluster。另外還有一些第三方的事務,比較知名的有XtraDB和PBXT。

  • 自動提交(AutoCommit):Mysql默認是自動提交模式。如果你不顯式地開始一個事務,那么每次查詢都當做一個事務。
    可通過以下方式查詢活修改自動提交模式
SHOW VARIABLES LIKE 'AUTOCOMMIT';

SET AUTOCOMMIT = 0;--1表示啟用,0表示禁用

  • 設置隔離級別:可以配置文件中修改整個數據庫的隔離級別,也可以只改變當前會話的隔離
mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

1.6、多版本并發控制(MVCC)

不同的存儲引擎MVCC實現不同,典型的有樂觀并發和悲觀并發控制。下面結合InnoDB說明下。
InnoDB的MVCC,通過在每行記錄后面保存兩個隱藏列實現,這兩個列一個保存行的創建時間,一個保存過期(刪除時間),當然這里存儲的創建時間不是真正的時間,而是系統版本號。

  • REPEATABLE READ級別下,MVCC操作如下:
    • select :InnoDB只查找版本早于當前事務版本的數據行(即創建版本號《=當前事務版本號),這樣保證事務讀取的行是早于事務開始前就已經存在的。刪除版本號》當前事務版本號,保證事情讀取到的行在事務開始前未被刪除。
    • insert:插入新行的時候,將事務分配到的版本號賦給創建版本號那個列屬性。
    • delete:為刪除的每一行保存當前系統版本號為行刪除標識,即將該版本號存入刪除版本號的那個列屬性
    • update:實際上是新插入一條記錄,然后將事務分配到的版本號賦給舊記錄的刪除版本號列以及新記錄的創建版本號列。

MVCC只在REPEATABLE READ和READ COMMITTED兩個隔離級別下工作。

1.7、MySQL存儲引擎

查詢表相關信息,命令如下

mysql> show table status like 'city' \G
*************************** 1. row ***************************
           Name: city //表名
         Engine: InnoDB//引擎名
        Version: 10
     Row_format: Compact//行的格式
           Rows: 600//行數,對于InnoDB,該行是估計值,其他引擎為準確值
 Avg_row_length: 81//平均每行字節數
    Data_length: 49152//表數據大小,byte為單位
Max_data_length: 0//
   Index_length: 16384
      Data_free: 0
 Auto_increment: 601
    Create_time: 2017-10-09 19:59:23
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options: 
        Comment: 
1 row in set (0.00 sec)

修改表的引擎采用如下語句:

ALTER TABLE city ENGINE = InnoDB;

下面簡單介紹下相關存儲引擎的優缺點

1.7.1、InnoDB

優點:Mysql當前的默認引擎,事務型引擎,用MVCC支持高并發,通過間隙鎖在REPEATABLE READ級別下就能防止幻讀。支持熱備份。
缺點:非常復雜,性能較一些簡單的引擎要差一點兒。空間占用比較多。

1.7.2、MyISAM:

優點:Mysql 5.1之前版本的默認引擎。全文索引、壓縮、空間函數(GIS)、并發插入、某些場景下性能很好
缺點:非事務型、不支持行鎖、崩潰后數據不容易修復

1.7.3、Archive:

優點:支持高并發插入,解決不可重復讀,針對高速插入和壓縮做了優化的簡單引擎
缺點:只支持查詢和插入操作,非事務型,僅適合日志和數據采集的應用場景

1.7.4、CSV引擎:

優點:有效支持CSV格式文件的導入導出。
缺點:作者沒說

1.7.5、Memory引擎:

優點:用來快速地訪問數據的,比MyISAM快一個數量級。支持Hash索引,因此查詢操作非常快。
缺點:所有數據保存在內存里,重啟只留下表結構。只支持表級鎖,并發能力低下。不支持BLOB或TEXT類型的列。且行長度固定,容易導致內存浪費。

1.7.6、NDB集群引擎:

作者沒有細講,后文會細講的吧,總之就是支持建立集群。

1.7.7、XtraDB和PBXT等OLTP類引擎:

優點:可完全替代InnoDB,或者高度相似。還額外提供了一些性能優化、可測量性、操作靈活性
缺點:第三方的引擎,社區支持的存儲引擎,可能不能保證質量
其實最常用的是InnoDB和MyISAM

  • 相關參數對比
特性 InnoDB MyISAM MEMORY ARCHIVE
存儲限制(Storage limits) 64TB No YES No
支持事物(Transactions) Yes No No No
鎖機制(Locking granularity) 行鎖 表鎖 表鎖 行鎖
B樹索引(B-tree indexes) Yes Yes Yes No
T樹索引(T-tree indexes) No No No No
哈希索引(Hash indexes) Yes No Yes No
全文索引(Full-text indexes) Yes Yes No No
集群索引(Clustered indexes) Yes No No No
數據緩存(Data caches) Yes No N/A No
索引緩存(Index caches) Yes Yes N/A No
數據可壓縮(Compressed data) Yes Yes No Yes
加密傳輸(Encrypted data[1]) Yes Yes Yes Yes
集群數據庫支持(Cluster databases support) No No No No
復制支持(Replication support[2]) Yes No No Yes
外鍵支持(Foreign key support) Yes No No No
存儲空間消耗(Storage Cost) N/A 非常低
內存消耗(Memory Cost) N/A
數據字典更新(Update statistics for data dictionary) Yes Yes Yes Yes
備份/時間點恢復(backup/point-in-time recovery[3]) Yes Yes Yes Yes
多版本并發控制(Multi-Version Concurrency Control/MVCC) Yes No No No
批量數據寫入效率(Bulk insert speed) 非常快
地理信息數據類型(Geospatial datatype support) Yes Yes No Yes
地理信息索引(Geospatial indexing support[4]) Yes Yes No Yes
  1. 在服務器中實現(通過加密功能)。在其他表空間加密數據在MySQL 5.7或更高版本兼容。
  2. 在服務中實現的,而不是在存儲引擎中實現的。
  3. 在服務中實現的,而不是在存儲引擎中實現的。
  4. 地理位置索引,InnoDB支持可mysql5.7.5或更高版本兼容

下一章開始MySQL基準測試,當然前幾章相關的內容會相對少,這些主要是相關的介紹,讓大家大致有個了解。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376

推薦閱讀更多精彩內容