日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL InnoDB存储引擎

發(fā)布時間:2023/12/9 数据库 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL InnoDB存储引擎 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

呵呵噠。。。

?

MySQL體系結(jié)構(gòu)和存儲引擎

首先要搞懂的是什么是數(shù)據(jù)庫,什么是數(shù)據(jù)庫實例。

數(shù)據(jù)庫:物理操作系統(tǒng)文件或其他形式文件類型的集合。

實例:MySQL數(shù)據(jù)庫由后臺線程以及一個共享內(nèi)存區(qū)組成,實例才是真正對數(shù)據(jù)庫進行操作的。

譬如:數(shù)據(jù)庫就像蓋樓所需的石頭、砂和水泥等原材料,而正在使用這些原材料蓋樓的施工隊則是實例,哈哈。

?

MySQL實例啟動的方法有很多種,啟動時讀取配置文件,如果配置文件有多個,而且配置項又有很多相同的,那么會以最后讀到的配置項為準。

?

數(shù)據(jù)庫實例是一層數(shù)據(jù)庫管理軟件,用戶不能直接地操縱數(shù)據(jù)庫,只能通過實例提供的接口來訪問數(shù)據(jù)庫。

圖1 MySQL體系結(jié)構(gòu)

從圖1中可以發(fā)現(xiàn),MySQL又一下幾部分組成:

  • 連接池組件:Connectors
  • 管理服務和工具組件:Management Service & Utilities
  • SQL接口組件:SQL Interface
  • 查詢分析器組件:Parser
  • 優(yōu)化器組件:Optimizer
  • 緩沖組件:Caches & Buffers
  • 插件式存儲引擎:Pluggable Storage Engines
  • 物理文件:Files & Logs

MySQL的這個架構(gòu)模式在很多數(shù)據(jù)庫中都有體現(xiàn),你可以學一下MySQL這個架構(gòu),好歹也是架構(gòu)啊!

MySQL數(shù)據(jù)庫的特色就是插件式的表存儲引擎。

MySQL插件式存儲引擎架構(gòu)提供了一系列標準的管理和服務支持。

存儲引擎是底層物理結(jié)構(gòu)的實現(xiàn),每個存儲引擎開發(fā)者可以按照自己的意愿進行開發(fā)。

??? 注意:

??????? 存儲引擎是基于表的,而不是數(shù)據(jù)庫的!

?

存儲引擎的好處是:

  • 每個存儲引擎都有各自的特點,可以根據(jù)具體的應用不同選擇/建立不同的存儲引擎表。
  • 對于上層應用的開發(fā)來說,存儲引擎是透明的。
  • MySQL數(shù)據(jù)庫的核心在于存儲引擎。
  • MySQL官方手冊給出了編寫自定義存儲引擎的過程(可以去看下咯)。

?

常見的存儲引擎有(不能詳寫了,木有時間了):

InnoDB、MyISAM、NDB、Memory、Archive、Federated、Maria;

其他的有:Merge、CSV、Sphinx、Infobright

至于存儲引擎之間的比較,讓他們見鬼去吧, 哦,我的上帝~

?

查看當前MySQL數(shù)據(jù)庫所支持的引擎:SHOW ENGINES\G;

MySQL自帶的示例數(shù)據(jù)庫和數(shù)據(jù)庫的文檔放在一起,下載地址:http://dev.mysql.com/doc/

?

連接MySQL

連接MySQL操作是一個連接進程和MySQL數(shù)據(jù)庫實例進行通信,本質(zhì)上是進程通信(還好老子看了點,不然就懵逼了),常見的進程通信方式有:

管道、命名管道、命名名字、TCP/IP套接字、UNIX域套接字。

TCP/IP套接字:在任何平臺下都可以使用,也是使用最多的一種,通過TCP/IP連接MySQL實例時,MySQL會先檢查一張權(quán)限視圖,判斷請求客戶端IP是否允許連接到實例;

SELECT host, user, password FROM user;

命名管道和共享內(nèi)存:

UNIX域套接字:在Linux和Unix下可以使用UNIX域套接字,這個并不是一個網(wǎng)絡協(xié)議,所以只能在客戶端和數(shù)據(jù)庫實例在同一臺機器的情況下使用。

制定套接字文件的路徑:—socket=/tmp/mysql.sock

SHOW VARIABLES LIKE 'socket';

?

好了,這章就看完了,遺留的就是對不同存儲引擎的介紹和比較咯。。。。。。

?

?

InnoDB存儲引擎

?

InnoDB是事物安全的MySQL存儲引擎,是OLTP應用中核心表的首選存儲引擎。

InnoDB是MySQL中第一個完整支持ACID事物的存儲引擎,其特點是:

行鎖設計

支持MVCC

支持外鍵

提供一致性非鎖定讀

有效利用CPU和內(nèi)存

?

從MySQL5.1版本開始,允許存儲引擎以動態(tài)方式加載,這樣存儲引擎的更新可以不受MySQL數(shù)據(jù)庫版本的限制。

所以5.1中可以有靜態(tài)編譯的版本,也可以有動態(tài)加載的版本。

?

InnoDB體系架構(gòu)

?

圖2 InnoDB存儲引擎體系架構(gòu)

InnoDB存儲引擎有多個內(nèi)存塊,可以認為這些內(nèi)存塊組成了一個大的內(nèi)存池,負責:

維護所有進程/線程需要訪問的多個內(nèi)部數(shù)據(jù)結(jié)構(gòu)

緩存磁盤上的數(shù)據(jù)

重做日志的緩沖(redo log)

?

后臺線程的主要作用是負責刷新內(nèi)存池中的數(shù)據(jù),保證緩沖池內(nèi)的數(shù)據(jù)是最近的數(shù)據(jù);同時將臟數(shù)據(jù)刷回磁盤;保證數(shù)據(jù)庫發(fā)生異常時InnoDB的恢復。

?

InnoDB是一個多線程模型,每個線程負責不同的任務。

1. Master Thread

2. IO Thread

3. Purge Thread

4. Page Cleaner Thread

?

內(nèi)存

1. 緩沖池

2. LRU List、Free List和Flush List

3. 重做日志緩沖

4. 額外的內(nèi)存池

?

CheckPoint技術

?

Master Thread工作方式

?

InnoDB的關鍵特性

插入緩沖(Insert Buffer)

兩次寫(Double Write)

自適應哈希索引(Adaptive Hash Index)

異步IO(Async IO)

刷新鄰接頁(Flush Neighbor Page)

?

啟動、關閉與恢復

?

小結(jié):感覺這章的內(nèi)容還是挺重要的,對于理解InnoDB引擎或者底層實現(xiàn)

?

文件

MySQL和InnoDB存儲引擎用到的文件有:

參數(shù)文件:

日志文件:

socket文件:

pid文件:

MySQL表結(jié)構(gòu)文件:

存儲引擎文件:

?

?

?

?

InnoDB存儲引擎表的邏輯存儲和實現(xiàn),重點分析表的物理存儲特征,即表中的數(shù)據(jù)是如何組織和存放的。

?

索引組織表

?

在InnoDB存儲引擎中,表都是根據(jù)主鍵順序存放的,這種存儲方式的表稱為索引組織表(index organized table)。

在InnoDB存儲引擎表中,每張表都有個主鍵(Primary Key),如果創(chuàng)建表時沒有顯式地定義主鍵,則InnoDB存儲引擎會按照如下方式選擇或者創(chuàng)建主鍵:

首先判斷表中是否有非空的唯一索引(Unique NOT NULL),如果有,則該列即為主鍵;

如果不符合上述條件,InnoDB存儲引擎將選擇建表時定義一個非空唯一索引主鍵。注意,主鍵的選擇是根據(jù)的是定義索引的順序,而不是建表時列的順序。

?

?

InnoDB邏輯存儲結(jié)構(gòu)

?

在InnoDB中所有的數(shù)據(jù)都被邏輯地存放在一個空間中,稱之為表空間(tablespace)。表空間又由段(segment)、區(qū)(extent)、頁(page)組成。頁在一些文檔中也稱之為塊(block)。

?

圖 InnoDB邏輯存儲結(jié)構(gòu)

表空間

?

?

?

區(qū)

?

?

?

?

InnoDB行記錄格式

?

InnoDB存儲引擎和大多數(shù)的數(shù)據(jù)庫一樣,記錄是以行的形式存在的。即頁中保存著表中一行行的數(shù)據(jù)。

在InnoDB 1.0.x版之前,InnoDB引擎提供了Compact和Redundant兩種格式來存放行記錄數(shù)據(jù),這也是目前用得最多的,Redundant是為了兼容之前的版本而保留的。

數(shù)據(jù)庫實例的作用之一就是讀取頁中存放的行記錄。如果用戶知道野種行記錄的組織規(guī)則,也可以自行編寫工具讀取記錄。

?

分表講了一下Compact行記錄格式和Redundant行記錄格式。

?

?

行溢出數(shù)據(jù)

?

?

Compressed和Dynamic行記錄格式

?

Char個行記錄格式

?

InnoDB數(shù)據(jù)頁結(jié)構(gòu)

?

頁是InnoDB引擎管理數(shù)據(jù)庫的最小磁盤單位。頁類型為B-tree Node的頁存放的即是表中行的實際數(shù)據(jù)了。

?

?

Named File Formats機制

?

InnoDB存儲引擎通過Named File Formats解決不同版本下頁結(jié)構(gòu)的兼容性問題。

?

?

約束

?

?

視圖

?

分區(qū)表:水平分區(qū)和垂直分區(qū)

?

?

索引與算法

索引太多,程序的性能受到影響;

索引太少,查詢的性能又會受到影響。So,必須找到一個平衡點。

?

?

對于數(shù)據(jù)的使用,從一開始就應該添加索引。

開發(fā)人員往往對于數(shù)據(jù)庫的使用停留在應用層面,比如編寫SQL語句、存儲過程之類的,甚至不知道索引的存在。

DBA往往不夠了解業(yè)務的數(shù)據(jù)流,而添加索引需要通過監(jiān)控大量的SQL語句進而從中找到問題。這個步驟所需的時間肯定大于當初添加索引所需要的時間。索引也不是越多越好,索引越多導致磁盤占用很高。

?

這里對索引的內(nèi)部機制了解,通過了解內(nèi)部索引來了解哪里可以使用索引。

?

InnoDB存儲引擎索引的概述

?

InnoDB支持的索引類型有:B+樹索引、全文索引、哈希索引

?

InnoDB支持的哈希索引是自適應的,InnoDB存儲引擎會根據(jù)表的使用情況自動為表生成哈希索引,不能人為干預是否在一張表中生成哈希索引。

自適應哈希索引

?

?

圖 全文索引

?

?

?

B+樹索引是傳統(tǒng)意義上的索引, 也是目前關系型數(shù)據(jù)庫中使用最多和最有效的索引。B不是binary的意思,而是balance的意思,可有效減少磁盤IO。

注意:B+樹索引并不能夠找到一個給定鍵值的具體行。B+樹索引只能找到被查詢數(shù)據(jù)行所在的頁。然后通過將其讀入內(nèi)存,再在內(nèi)存中進行查找。

?

?

?

?

?

數(shù)據(jù)結(jié)構(gòu)與算法

?

關于B+ tree的

二分查找法(binary search):二分查找應用廣泛,思想易于理解,但是直到1962年才有了第一個完全正確的二分查找法。

?

二叉查找樹和平衡二叉樹

?

B+樹和二叉樹、平衡二叉樹一樣都是經(jīng)典的數(shù)據(jù)結(jié)構(gòu)。

B+樹由B樹和索引順序訪問方法(ISAM)演化而來,但是現(xiàn)實中已經(jīng)沒有使用B樹的情況了。

B+樹的定義很復雜,總而言之:B+樹是為磁盤或其他直接存取輔助設備設計的一種平衡查找樹。

?

圖 高度為2的B+樹

?

B+樹的插入操作

B+樹的插入必須保證插入以后葉子節(jié)點中的記錄依然排序,同時要考慮到插入到B+樹中的三種情況,每個情況都有不同的插入算法。

圖 B+樹插入數(shù)據(jù)的三種不同情況

?

不管怎么插入數(shù)據(jù),B+樹總是會保持平衡,但是為了平衡性,對新插入的鍵值可能需要做大量的拆分頁(split)操作。

因為B+樹結(jié)構(gòu)主要用于磁盤,頁的拆分意味著磁盤操作,所以應當盡量減少頁的拆分操作。

所以B+樹提供了類似于平衡二叉樹的旋轉(zhuǎn)(Rotation)功能。

?

旋轉(zhuǎn)發(fā)生在Leaf Page已滿,但是左右兄弟節(jié)點沒有滿的情況下,B+樹不會急于做拆分操作,而是將記錄轉(zhuǎn)移到所在頁的兄弟節(jié)點上。

通常會先對左兄弟檢查來做旋轉(zhuǎn)操作。采用旋轉(zhuǎn)操作使得B+樹減少了一次頁的拆分操作。

?

B+樹的刪除操作

B+樹使用填充因子(fill factor)來控制樹的刪除變化,50%是填充因子的最小值。B+樹的刪除操作同樣必須保證刪除后葉子節(jié)點中的記錄依然排序,刪除也要考慮三種情況:

如果刪除之后,Fill Factor小于50%,那么需要做合并操作。

?

B+樹索引

?

B+樹索引的本質(zhì)就是B+樹在數(shù)據(jù)庫中的實現(xiàn)。但是B+樹在數(shù)據(jù)庫中的特點是高扇出性,什么鬼?就是葉節(jié)點多。

因此數(shù)據(jù)庫中,B+樹的高度一般都是在2~4層,也就是說查找某一鍵值最多需要2到4次IO。2~4次IO意味著查詢時間只要0.02~0.04秒。

?

?

?

?

數(shù)據(jù)庫中的B+樹索引可以分為聚集索引(clustered index)和輔助索引(secondary index)。

?

聚集索引

?

圖 聚集索引

?

圖 聚集索引

?

?

圖 聚集索引和非聚集索引的區(qū)別

?

InnoDB存儲引擎表是索引組織表,即表中的數(shù)據(jù)按照主鍵順序存放。

而聚集索引(clustered index)就是按照每張表的主鍵構(gòu)造一顆B+樹,同時葉子節(jié)點中存放的即為整張表的行記錄數(shù)據(jù),也將聚集索引的葉子節(jié)點稱為數(shù)據(jù)頁。

聚集索引的這個特性決定了索引組織表中數(shù)據(jù)也是索引的一部分。同B+樹數(shù)據(jù)結(jié)構(gòu)一樣,每個數(shù)據(jù)頁都通過一個雙向鏈表來進行鏈接。

?

由于實際的數(shù)據(jù)頁只能按照一顆B+樹進行排序,因此每張表只能擁有一個聚集索引。在多數(shù)情況下,查詢優(yōu)化器傾向于采用聚集索引,

因為聚集索引能夠在B+樹索引的葉子節(jié)點上直接找到數(shù)據(jù)。

此外由于定義了數(shù)據(jù)的邏輯順序,聚集索引能夠特別快地訪問針對范圍值的查詢。查詢優(yōu)化器能夠快速地發(fā)現(xiàn)某一段范圍的數(shù)據(jù)頁需要掃描。

?

圖 聚集索引中的數(shù)據(jù)查找

?

圖 非聚集索引中的數(shù)據(jù)查找

注意,聚集索引如果按照特定的順序存放物理數(shù)據(jù),那么維護成本會很高。所以聚集索引的存儲并不是物理上連續(xù)的,而是邏輯上連續(xù)的。

其中有兩點:一時前面說到的頁通過雙向鏈表鏈接,頁按照主鍵的順序排序;

另一點是每個頁中的記錄也是通過雙向鏈表進行維護的,物理存儲上可以同樣不按照主鍵存儲。

?

?

聚集索引的另一個好處是,它對于主鍵的排序查找和范圍查找的速度非常快,葉子節(jié)點的數(shù)據(jù)就是用戶所要查找的數(shù)據(jù)。

?

雖然有通過order by進行排序,但是實際過程中并不會進行所謂的filesort,這是聚集索引的特點之一。

?

另一個是范圍查找,即如果要查找主鍵某一范圍內(nèi)的數(shù)據(jù),通過葉子節(jié)點的上層中間節(jié)點就可以得到頁的范圍,之后直接讀取數(shù)據(jù)頁即可。

?

輔助索引

?

輔助索引(secondary index),也成為非聚集索引,葉子節(jié)點并不包含記錄的全部數(shù)據(jù)。葉子節(jié)點除了包含鍵值以外,每個葉子節(jié)點中還會包含了一個書簽(bookmark)。

該書簽用來告訴InnoDB存儲引擎哪里可以找到與索引對應的行數(shù)據(jù)。

由于InnoDB存儲引擎是索引組織表,因此InnoDB存儲引擎的輔助索引的書簽就是相應行數(shù)據(jù)的聚集索引鍵。

?

輔助索引的存在并不影響數(shù)據(jù)在聚集索引中的組織,因此每張表上可以有多個輔助索引。當通過輔助索引來尋找數(shù)據(jù)時,InnoDB存儲引擎會遍歷輔助索引并通過葉級別的指針

獲得指向主鍵索引的主鍵,然后再通過主鍵索引來找到一個完整的行記錄。

?

注意:輔助索引并不需要讀取數(shù)據(jù)頁,輔助索引中并不存放數(shù)據(jù),全都是索引

?

圖 非聚集索引

?

?

圖 非聚集索引

?

?

圖 聚集索引與非聚集索引

上面這張圖表現(xiàn)的還不錯哦。

?

稱為堆表的表類型是將行數(shù)據(jù)按照插入的順序存放,堆表的特性決定了堆表上的索引都是非聚集索引,主鍵與非主鍵的區(qū)別只是是否唯一且非空(NOT NULL)。

此時書簽是一個行標識(Row Identifier, RID),可以用如"文件號:頁號:槽號"的格式來定位實際的數(shù)據(jù)行。

?

某些情況下堆表的確要比索引組織表更快,但也要考慮到數(shù)據(jù)是否需要更新,并且更新是否影響到物理地址的變更。

同時也不能忽視排序和查找。

非聚集索引的離散讀,但是一般的數(shù)據(jù)庫都通過實現(xiàn)預讀(read ahead)技術來避免多次的離散讀操作。

因此建立索引組織表還是堆表取決于具體應用。

?

圖 預讀

?

B+樹索引的分裂

?

之前講到的B+樹的分裂是最為簡單的一種情況,在數(shù)據(jù)庫中的B+樹分裂則有所不同。

因為之前的B+樹分裂并沒有涉及到并發(fā),這是最難的一部分。

圖 B+樹的分裂

圖 B+樹的分裂

?

B+樹的分裂也并不總是從中間開始,這樣會導致頁空間的浪費。

?

?

InnoDB存儲引擎的Page Header中有以下幾個部分用來保存插入的順序信息:

PAGE_LAST_INSERT

PAGE_DIRECTION

PAGE_N_DIRECTION

通過這些信息,InnoDB存儲引擎可以決定是向左還是向右分裂,同時決定將分裂點記為哪一個。

?

?

B+樹索引的管理

?

索引的創(chuàng)建和刪除可以通過兩種方法,一種是ALTER TABLE,另一種是CREATE/DROP INDEX。

?

用戶可以設置對整個列的數(shù)據(jù)進行索引,也可以只索引一個列的開頭部分。

?

SHOW INDEX可以查看表中的索引信息。

?

Fast Index Creation

?

對于索引添加或者刪除這類DDL操作,MySQL數(shù)據(jù)庫的操作過程為:

首先創(chuàng)建一張新的臨時表,表結(jié)構(gòu)為通過命令ALTER TABLE新定義的結(jié)構(gòu)

然后把原表中數(shù)據(jù)導入到臨時表中

接著刪除原表

最后把臨時表重命名為原來的表名。

?

?

如果對一張很大的表進行索引的添加和刪除操作,那么將耗費較長時間,更關鍵的是,若有大量事物需要訪問正在被修改的表,這意味著數(shù)據(jù)庫不可用。

?

InnoDB從 1.0.x開始支持一種稱為FIC(快速索引創(chuàng)建)的索引創(chuàng)建方式。

?

對于輔助索引的創(chuàng)建,InnoDB存儲引擎會對創(chuàng)建索引的表上加一個S鎖。在創(chuàng)建的過程中不需要重建表。

?

刪除輔助索引則更為簡單了,InnoDB存儲引擎只需要更新內(nèi)部視圖,并將輔助索引的空間標記為可用,同時刪除MySQL數(shù)據(jù)庫內(nèi)部視圖上對該表的索引定義即可。

?

?

?

Online Schema Change

?

The openarkkit toolkit oak-online-alter-table

?

Online DDL

?

?

Cardinality值

?

?

什么是Cardinality

并不是在所有的查詢條件中出現(xiàn)的列都需要添加索引。

一般的經(jīng)驗是,在訪問表中很少一部分時使用B+樹索引才有意義。

對于性別字段、地區(qū)字段、類型字段,它們的取值的范圍很小,稱為低選擇性。

?

?

相反,如果某個字段的取值范圍很廣,幾乎沒有重復,即屬于高選擇性,則此時使用B+樹索引是非常合適的。

?

?

如果查看索引是否是高選擇性的呢?

?

可以通過SHOW INDEX結(jié)果列中的Cardinality來觀察。

Cardinality值非常關鍵,表示索引中不重復記錄數(shù)量的預估值。

同時需要注意的是Cardinality是一個預估值,而不是準確值。

在實際應用中,Cardinality/n_rows_in_table應盡可能接近1,如果非常小,那么用戶需要考慮是否還有必要建立這個索引。

?

?

B+樹索引的使用

?

不同應用中使用B+樹索引

聯(lián)合索引

覆蓋索引

?

優(yōu)化器選擇不使用索引的情況

?

?

索引提示

?

?

Multi-Range Read優(yōu)化

?

?

ICP優(yōu)化

?

?

哈希算法

?

InnoDB存儲引擎中的哈希算法

?

自適應哈希算法

?

全文檢索

?

?

?

?

開發(fā)多用戶的系統(tǒng)時,最大的難點在于:一方面要最大程度利用數(shù)據(jù)庫的并發(fā)訪問,另外一方面還要確保每個用戶能以一致的方式讀取和修改數(shù)據(jù)。

為此就需要鎖機制。

鎖也是數(shù)據(jù)庫區(qū)別于文件系統(tǒng)的一個關鍵特性。

?

這部分學習的是InnoDB如何對表中的數(shù)據(jù)進行鎖定,以及以怎樣的粒度鎖定數(shù)據(jù)。

?

?

什么是鎖?

?

?

鎖機制用于管理共享資源的并發(fā)訪問。InnoDB存儲引擎會在行級別上對表數(shù)據(jù)上鎖。

?

除了對數(shù)據(jù)表進行上鎖之外,InnoDB也會在內(nèi)部對其他的很多資源使用鎖,從而允許對多種不同資源提供并發(fā)訪問。

例如操作緩沖池中的LRU列表,刪除、添加、移動LRU列表中的元素,為了保證一致性,必須有鎖的介入,從而提供完整性和一致性。

?

對于MyISAM引擎,其鎖是表鎖設計,并發(fā)情況下的讀沒有問題,但是并發(fā)插入時的性能就要差一些。

?

?

lock與latch

?

在數(shù)據(jù)庫中l(wèi)ock和latch都可以被稱為鎖,但是兩者的含義截然不同。

?

latch一般稱為閂鎖,因其要求鎖定的時間必須非常短,若持續(xù)的時間長,則應用性能會很差。在InnoDB存儲引擎中,latch有可以分為mutex(互斥量)和rolock(讀寫鎖)。其目的使用來保證并發(fā)線程操作臨界資源的正確性,并且通常沒有檢測死鎖的機制。

?

lock的對象是事務,用來鎖定的是數(shù)據(jù)庫中的對象,如表、頁、行。并且一般lock的對象僅在事務commit或者rollback后進行釋放(不同事務隔離級別釋放的時間可能不同)。lock是有死鎖機制的。

?

?

?

?

SHOW ENGINE INNODB MUTEX可以查看InnoDB存儲引擎中的latch,輸出結(jié)果的解釋如下:

以上的信息都是比較底層的,一般僅供開發(fā)人員參考,但是用戶還是可以使用這些參數(shù)進行調(diào)優(yōu)。

?

?

InnoDB存儲引擎中的鎖

?

鎖的類型

?

InnoDB存儲引擎實現(xiàn)了如下兩種標準的行級鎖:

共享鎖(S Lock),允許事務讀一行數(shù)據(jù)。

排他鎖(X Lock),允許事務刪除或更新一行數(shù)據(jù)。

?

?

如果一個事務T1已經(jīng)獲取行r的共享鎖,那么另外的事務T2可以立即獲取行r的共享鎖,因為讀取并沒有改變行r的數(shù)據(jù),這種情況稱為鎖兼容(Lock Compatible)。

但若有其他的事務T3想獲取行r的排他鎖,則其必須等待事務T1、T2釋放行r上的共享鎖——稱之為鎖不兼容。

?

X鎖與任何鎖都不兼容,而S鎖僅與S鎖兼容。需要注意的是X和S都是行鎖,兼容是指對同一記錄(row)鎖的兼容情況。

?

此外InnoDB存儲引擎支持多粒度(granular)鎖定,這種鎖定允許事務在行級別上的鎖和表級上的鎖同時存在。

?

為了支持不同粒度上的鎖,InnoDB存儲引擎有一個額外的鎖方式,稱之為意向鎖(Intention Lock)。意向鎖是將鎖定的對象分為多個層次,意向鎖意味著事務希望在更細粒度(fine granularity)上進行加鎖。

?

如果把上鎖的對象看做一顆樹,那么對最下層的對象上鎖,也就是對最細粒度的對象上鎖,那么首先需要對粗粒度的對象上鎖。

?

如需對頁上的記錄r進行上X鎖,那么分別需要對數(shù)據(jù)庫A、表、頁上意向鎖IX,最后對記錄r上X鎖。

其中任何一部分導致等待,那么該操作需要等待粗粒度鎖的完成。

?

舉例就是,對記錄r加X鎖之前,已經(jīng)有事務對表1進行了S表鎖,那么表1上已經(jīng)存在了S鎖,之后事務需要對記錄r在表上加IX,由于不兼容,所以對該事務需要等待表鎖操作的完成。

?

InnoDB存儲引擎支持的意向鎖設計比價簡單,其意向鎖為表級別的鎖。設計目的主要是為了在一個事務中揭示下一行將被請求的鎖類型。

1. 意向共享鎖(IS Lock),事務想要獲得一張表中某幾行的共享鎖

2. 意向排他鎖(IX Lock),事務想要獲得一張表中某幾行的排他鎖

?

由于InnoDB存儲引擎支持的是行級別的鎖,因此意向鎖其實不會阻塞除全表掃描以外的任何請求。

?

?

用戶可以通過命令SHOW ENGINE INNODB STATUS命令來查看當前鎖請求的信息。

?

可以看到SQL語句select * from? where a<4 lock in share mode在等待,

RECORD LOCKS space id 30 page no 3 n bits 72 index 'PRIMARY' of table 'test'.'t' trx id 48B89DB lock_mode X locks rec but not gap表示鎖住的資源。

locks rec but not gap代表鎖住的是一個索引,不是一個范圍。

?

在InnoDB 1.0版本之前,用戶只能通過命令SHOW FULL PROCESSLIST,SHOW ENGINE INNODB STATUS等來查看當前數(shù)據(jù)庫中的鎖請求,然后再判斷事務鎖的情況。

從InnoDB1.0開始,INFORMATION_SCHEMA架構(gòu)下添加了表INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS。

通過這三張表,用戶可以更加單地監(jiān)控當前事務并分析可能存在的問題。

?

?

?

?

一致性非鎖定讀(consistent nonlocking read)指的是InnoDB存儲引擎通過多行版本控制(multi versioning)的方式來讀取當前執(zhí)行時間數(shù)據(jù)庫中行的數(shù)據(jù)。

?

如果讀取的行正在執(zhí)行DELETE或者UPDATE操作,這時讀取操作不會因此去等待行上鎖的釋放,相反的,InnoDB存儲引擎會讀取行的一個快照數(shù)據(jù)。

?

?

?

之所以成為非鎖定讀,是因為不需要等待訪問的行上X鎖的釋放。

?

快照數(shù)據(jù)是指該行的之前版本的數(shù)據(jù),該實現(xiàn)是通過undo段來完成。而undo用來在事務中回滾數(shù)據(jù),因此快照數(shù)據(jù)本身是沒有額外的開銷。

此外快照數(shù)據(jù)的讀取是不需要上鎖的,因為沒有事務需要對歷史數(shù)據(jù)進行修改操作。

?

?

非鎖定讀機制極大提高了數(shù)據(jù)庫的并發(fā)性。

在InnoDB存儲引擎的默認設置下,這是默認的讀取方式,即讀取不會占用和等待表上的鎖。

?

但是在不同事務隔離級別下,讀取的方式不同,并不是在每個事務隔離級別下都是采用非鎖定的一致性讀。

此外即使使用非鎖定的一致性讀,但是對于快照數(shù)據(jù)的定義也各不相同。

?

快照數(shù)據(jù)就是當前行數(shù)據(jù)之前的歷史版本,每行記錄可能有多個版本。一行記錄可能有不止一個快照數(shù)據(jù),一般稱這種技術為行多版本控制,由此帶來的并發(fā)控制,

稱為多版本并發(fā)控制(Multi Version Concurrency Control,MVCC)。

?

在事務隔離級別READ COMMITTED和REPEATABLE READ(InnoDB存儲引擎默認的隔離級別)下,InnoDB存儲引擎使用的是非鎖定的一致性讀。

然后對于快照數(shù)據(jù)的定義卻不一樣。

?

在READ COMMITTED事務隔離級別下,對于快照數(shù)據(jù),非一致性讀總是讀取被鎖定行的最新一份快照數(shù)據(jù)(fresh snapshot)。

而在REPEATEABLE READ事務隔離級別下,對于快照數(shù)據(jù),非一致性讀總是讀取事務開始時的行數(shù)據(jù)版本。

?

?

BEGIN;

COMMIT;

?

?

?

非一致性鎖定讀

?

在默認配置下,即事務隔離級別為REPEATABLE READ模式下,InnoDB存儲引擎的SELECT操作使用一致性非鎖定讀。

但是在某些情況下,用戶需要顯式地對數(shù)據(jù)庫操作進行加鎖以保證數(shù)據(jù)邏輯的一致性。

而這要求數(shù)據(jù)庫支持加鎖語句,即使對于SELECT的只讀操作。

InnoDB存儲引擎對于SELECT語句支持兩種一致性的鎖定讀(locking read)操作:

SELECT ..... FOR UPDATE

SELECT ..... LOCK IN SHARE MODE

?

SELECT ...... FOR UPDATE對讀取的行記錄加一個X鎖,其他事物不能對已鎖定的行加上任何鎖。

SELECT ...... LOCK IN SHARE MODE對讀取的行記錄加一個S鎖,其他事務可以向被鎖定的行加S鎖,但是如果加X鎖,則會被阻塞。

?

?

對于一致性非鎖定讀,即使讀取的行已被執(zhí)行了SELECT ..... FOR UPDATE,也是可以進行讀取的。

此外,SELECT .... FOR UPDATE,SELECT ...... LOCK IN SHARE MODE必須在一個事務中,當事務提交了,鎖也就被釋放了。

?

因此在使用上面兩句SELECT的時候,務必加上begin,start transaction或者set autocommit=0。

?

?

自增長和鎖

?

外鍵和鎖

?

?

?

鎖的算法

?

行鎖的三種算法:

Record Lock:單行記錄的鎖

Gap Lock:間隙鎖,鎖定一個范圍,但不包含記錄本身

Next-key Lock:Gap Lock + Record Lock,鎖定一個范圍,并鎖定記錄本身

?

解決Phantom Problem

?

?

鎖問題

?

臟讀

?

臟讀就是指在不同的事務下,當前事務讀到了另外事務未提交的數(shù)據(jù)。

?

不可重復讀

?

丟失更新

?

?

阻塞

?

?

死鎖

?

死鎖的概念

?

?

死鎖概率

?

?

死鎖示例

?

鎖升級

?

事務

?

數(shù)據(jù)庫中事務的目的:事務會把數(shù)據(jù)庫從一種一致狀態(tài)轉(zhuǎn)為另一種一致狀態(tài)。

在數(shù)據(jù)庫提交工作時,要么確保所有修改都已經(jīng)保存了,要么所有修改都不保存。

?

ACID

原子性(atomicity)

一致性(consistency)

隔離性(isolation)

持久性(durability)

?

認識事務

?

事務有著嚴格的定義,必須同時滿足四個特性,但是數(shù)據(jù)庫廠商出于各種目的,并沒有嚴格去滿足事務的ACID標準。

對于InnoDB存儲引擎而言,其默認的事務隔離級別READ REPEATABLE,完全遵循和滿足事務的ACID特性。

?

分別介紹事務的四個特性

?

事務的分類

?

扁平事務(Flat Transaction)

帶有保存點的扁平事務(Flat Transaction with Savepoints)

鏈事務(Chained Transactions)

嵌套事務(Nested Transactions)

分布式事務(Distributed Transactions)

?

?

?

事務的實現(xiàn)

?

?

事務控制語句

?

隱式提交的SQL語句

?

?

對事物操作的統(tǒng)計

?

每秒事務處理能力(Transaction Per Second)

?

事務的隔離級別

?

?

分布式事務

?

?

不好的事務習慣

?

?

長事務

?

?

備份與恢復

?

?

?

性能調(diào)優(yōu)

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的MySQL InnoDB存储引擎的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。