面試必備常見存儲引擎與鎖的分類,請查收

      網友投稿 622 2025-03-31

      我們在上篇文章中提到了記錄鎖(行鎖)、間隙鎖和臨鍵鎖,后臺有小伙伴催我更新一下其他的鎖。拖延癥又犯了,趁周末,今天我們來總結一下MyISAM和InnoDB引擎下鎖的種類及使用方法。


      MySQL的四大常見存儲引擎

      談到MyISAM和InnoDB了我們先來了解一下什么是存儲引擎吧。MySQL中的數據用各種不同的技術存儲在文件(或者內存)中,這些技術中的每一種技術都使用不同的存儲機制、索引技巧、鎖定水平并且最終提供廣泛的不同的功能,我們把這些不同的技術以及配套的相關功能稱為存儲引擎(也稱作表類型)。MySQL默認配置了許多不同的存儲引擎,我們可以選擇不同的存儲引擎來滿足我們對數據的處理(存儲、檢索等)需求,以改善我們應用程序的整體功能。正因為MySQL存儲引擎的多樣性,使得MySQL深受廣大開發者的垂青。

      我們的前提條件:我用的是5.7.24-log版本,可以在Navicat中通過SELECT VERSION();命令查看。那么MySQL都有哪些存儲引擎呢?我們可以使用sql命令SHOW ENGINES;來查看,結果如下:

      Engine:表示儲存引擎名稱;

      Support:表示MySQL是否支持該存儲引擎,DEFAULT為默認的存儲引擎;

      Comment:是對該存儲引擎的功能描述,例如:InnoDB支持事務、行級鎖定和外鍵;

      Transactions:是否支持事務;

      XA:存儲引擎是否支持分布式事務;

      Savepoints:存儲引擎是否支持保存點。

      接著讓我們來說一下其中比較常見的四大存儲引擎吧。

      InnoDB是MySQL(MySQL5.5以后)的默認存儲引擎,支持事務、行級鎖和外鍵,被用來處理大量短期事務。如果使用到外鍵、需求并發程度較高、數據一致性要求較高的話,那么通常選擇InnoDB引擎,這也是互聯網大廠使用InnoDB存儲引擎的原因。除非有非常特別的原因需要使用其他的存儲引擎,否則建議優先考慮InnoDB。但是對比MyISAM,InnoDB寫的處理效率會差一些,并且會占用更多的磁盤空間以保留數據和索引。

      MyISAM提供了大量的特性,包含全文索引、壓縮、空間行數等,支持3種不同的存儲格式,分別是:靜態表、動態表、壓縮表。

      靜態表:表中的字段都是非變長字段,這樣每個記錄都是固定長度的。優點是存儲非常迅速,容易緩存,出現故障容易恢復;缺點是占用的空間通常比動態表多(因為存儲時會按照列的寬度定義補足空格),在取數據的時候,默認會把字段后面的空格去掉,如果不注意會把數據本身帶的空格也會忽略。

      動態表:表中的字段都是變長字段,記錄不是固定長度的。這樣存儲的優點是占用的空間相對較少;缺點是頻繁的更新、刪除數據容易產生碎片,需要定期執行OPTIMIZE TABLE或者myisamchk -r命令來改善性能,并且出現故障的時候恢復相對比較困難。

      壓縮表:壓縮表由myisamchk工具創建,占據非常小的空間,因為每條記錄都是被單獨壓縮的,所以只有非常小的訪問開支。

      在MyISAM中,數據文件和索引文件可以放置在不同的目錄(在創建表的時候通過DATA DIRECTORY和INDEX DIRECTORY語句指定文件的絕對路徑),平均分配IO,獲取更快的訪問速度。但是MyISAM不支持事務,不支持外鍵,也不支持行級鎖,支持表級鎖,有個缺陷就是崩潰后無法恢復。如果應用程序以檢索為主,只有少量的插入、更新和刪除操作,并且對事物的完整性、并發程度不是很高的話,通常建議選擇MyISAM存儲引擎。

      Memory存儲引擎使用存在內存中的內容來創建表,所以它的訪問速度非常快,并且默認使用HASH索引。但是一旦服務器關閉或者mysqld守護進程崩潰時,所有的Memory數據都會丟失,但表還會繼續存在,獲得速度的同時也帶來了一些缺陷。

      它要求存儲在Memory數據表里的數據使用的是長度不變的格式,這意味著不能使用BLOB和TEXT這樣的長度可變的數據類型,VARCHAR是一種長度可變的類型,但因為它在MySQL內部當做長度固定不變的CHAR類型,所以可以使用。

      服務器需要足夠的內存來維持在同一時間內使用的MEMORY表,當不再使用MEMORY表時,要釋放MEMORY表所占用的內存,應該執行DELETE FROM或truncate table或者刪除整個表。每個MEMORY表中放置的數據量的大小,受到max_heap_table_size系統變量的約束,這個系統變量的初始值是16M,同時在創建MEMORY表時可以使用MAX_ROWS子句來指定表中的最大行數。它通常用于更新不太頻繁的小表。

      Merge存儲引擎是一組MyISAM表的組合,這些MyISAM表結構必須完全相同,Merge表本身沒有數據,對Merge類型的表進行查詢、更新、刪除的操作,實際上是對內部的MyISAM表進行的。Merge表在磁盤上保留兩個文件,一個是.frm文件存儲表定義、一個是.MRG文件存儲Merge表的組成等。MERGE表的優點在于可以突破對單個MyISAM表大小的限制,并且通過將不同的表分布在多個磁盤上,可以有效地改善MERGE表的訪問效率。

      面試必備常見存儲引擎與鎖的分類,請查收

      我們可以通過show create table 表名 命令來查看表使用的引擎,由以下代碼可以看出test表使用的是MyISAM存儲引擎。

      CREATE TABLE `test` ( `id` int(1) NOT NULL AUTO_INCREMENT, `name` varchar(8) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=46 DEFAULT CHARSET=utf8

      相對其他數據庫而言,MySQL的鎖機制比較簡單,其最顯著的特點是不同的存儲引擎支持不同的鎖機制。比如,MyISAM和MEMORY存儲引擎采用的是表級鎖(table-level locking);BDB存儲引擎(5.1之后就不直接支持了,因為BDB被oracle收購了)采用的是頁面鎖(page-level locking),但也支持表級鎖;InnoDB存儲引擎既支持行級鎖(row-level locking),也支持表級鎖,但默認情況下是采用行級鎖。接下來就讓我們來了解一下MyISAM和InnoDB鎖的具體分類與使用方法。

      MyISAM鎖

      MyISAM存儲引擎支持的表級鎖分為表共享讀鎖(Table Read Lock)和表獨占寫鎖(Table Write Lock),以下簡稱讀鎖和寫鎖。先看一下他們的特性:

      讀鎖:不會阻礙其它進程的讀,但是會阻礙寫,只有當讀鎖釋放之后,才會執行其它進程的寫–讀鎖阻塞寫鎖,但是不阻塞讀鎖;

      寫鎖:會阻礙其他進程的讀和寫,只有當寫鎖釋放,才會執行其它寫操作–寫鎖阻塞讀鎖和寫鎖;

      接下來讓我們用例子來演示一下上邊的結論,在演示之前,先讓我們來說幾個命令吧。

      LOCK TABLE 表名 WRITE/READ:給表加寫鎖或者讀鎖;

      UNLOCK TABLES:給表解鎖

      演示一:表共享讀鎖

      當session1給表test加讀鎖時,session1只能讀取當前表的數據,不可以讀其他表,也不可以修改test和其他表;

      session2可以讀取test表數據,更新test表阻塞,但是可以修改和查詢其他表數據。

      演示二:表獨占寫鎖

      當session1給表test加寫鎖時,可以更新test表,讀test表阻塞,但是不可以修改和查詢其他表數據;

      session2查詢和更新test表阻塞,但是可以查詢和更新其他表。

      另外我們還可以使用show open tables命令來查看在表緩存中當前被打開的非TEMPORARY表的鎖使用情況,其中In_use表示有鎖正在使用。

      也可以使用show status like 'table%'命令來查看鎖的爭奪情況,其中Table_locks_waited為等待次數,每等待一次,值就加一,值越大,表示存在越嚴重的表級鎖爭用;Table_locks_immediate為產生表級鎖定的次數,表示可以立即獲取鎖的查詢次數,每立即獲取鎖,值加一。

      MyISAM默認是使用select語句加讀鎖,增刪改操作加寫鎖。MyISAM是偏讀鎖,讀寫調度寫優先,不適合做寫為主的表的引擎。因為寫鎖后,其他線程不能做任何操作,大量更新會使查詢很難得到鎖,從而永遠阻塞。

      InnoDB鎖

      上篇文章中我們講過了記錄鎖(行鎖)、間隙鎖和臨鍵鎖,這里就不再贅述了。接下來我們按照鎖的模式講一下InnoDB里的共享鎖、排他鎖和意向鎖,其中共享鎖和排他鎖屬于行級鎖,行級鎖都是基于索引項的,如果沒有索引項,則添加的是表級鎖;意向鎖屬于表級鎖。

      共享鎖:Shared Locks,簡稱S鎖

      若事務T對數據對象A加上S鎖,則事務T只能讀A;其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。這就保證了其他事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。可以通過select ... lock in share mode來加共享鎖,通過Commit、Rollback來釋放鎖。

      排他鎖:Exclusive lock,簡稱X鎖,也叫互斥鎖

      若事務T對數據對象A加上X鎖,則只允許T讀取和修改A,其它任何事務都不能再對A加任何類型的鎖(排他鎖不可與其他鎖共存),直到T釋放A上的鎖。它防止任何其它事務獲取資源上的鎖,直到在事務的末尾將資源上的原始鎖釋放為止。可以通過select ... for update手動加鎖,也可以通過增刪改操作自動加鎖,通過Commit、Rollback來釋放鎖。

      意向鎖:Intention Locks

      說起意向鎖,大家先來考慮一下這個問題:假設存在兩個事務A和B對表test進行操作,首先事務A對第十行數據加了一把讀鎖,鎖住了該行數據,讓這一行只能讀,不能寫;然后事務B想要對該表加一把表級的寫鎖,那么事務B能否加鎖成功呢?思考兩秒鐘…答案當然是否定的,即事務B無法加鎖成功。如果我們假設它加鎖成功的話,那么理論上它就能修改表中的任意一行,這將與事務A持有的行級鎖(讀鎖)產生沖突。而數據庫想避免這種沖突的話,就需要將事務B的加鎖申請給阻塞住,直到事務A的行鎖被釋放。那么問題來了,數據庫是怎么判斷這種沖突的呢?我們可以想到兩種方案:一、判斷表是否已被其他事務用表鎖鎖表;二、判斷表中的每一行是否已被行鎖鎖住。很顯然,如果采用第二種方法的話,需要一行一行去遍歷整張表,效率太慢進而造成系統消耗,所以我們選擇第一種方法,這也就是意向鎖是表鎖的原因。

      意向鎖是放置在資源層次結構的一個級別上的鎖,以保護較低級別資源上的共享鎖或排它鎖,意向鎖無法手動創建。如果對任一結點加鎖時,必須先對它的上層結點加意向鎖也就是如果對一個結點加意向鎖,則說明該結點的下層結點正在被加鎖。意向鎖的執行流程:如果另一個任務試圖在該表級別上應用共享或排它鎖,則受到由第一個任務控制的表級別意向鎖的阻塞,第二個任務在鎖定該表前不必檢查各個頁或行鎖,而只需檢查表上的意向鎖,所以意向鎖不是用來給數據加鎖的,而是用來判斷數據有沒有存在鎖的標志。下面介紹兩種常用的意向鎖:意向共享鎖(Intent Share Lock,簡稱IS鎖)、意向排它鎖(Intent Exclusive Lock,簡稱IX鎖)。

      意向共享鎖(IS):事務打算給數據行加行共享鎖,事務在給一個數據行加共享鎖前必須先取得該表的IS鎖。

      意向排他鎖(IX):事務打算給數據行加行排他鎖,事務在給一個數據行加排他鎖前必須先取得該表的IX鎖。

      意向鎖的兼容關系如下:

      其他鎖簡介(了解)

      InnoDB還包含插入意向鎖、自增鎖和空間鎖。

      插入意向鎖(Insert Intention Locks):是間隙鎖的一種,它的目的是為了提高插入性能。在多個事務對同一個索引中的同一個范圍區間插入記錄時,如果插入的位置不沖突,不會阻塞彼此,主要是不需要去申請排他鎖。

      自增鎖(AUTO-INC Locks):自增鎖是MySQL中一種特殊的鎖,如果表中存在自增字段,MySQL便會自動維護一個自增鎖。和自增鎖相關的一個參數為(5.1.22版本之后加入)innodb_autoinc_lock_mode,可以設定3個值,0:traditonal(每次都會產生表鎖,可以控制插入順序,效率低);1:consecutive(會產生一個輕量鎖,simple insert會獲得批量的鎖,保證連續插入,默認);2:interleaved(不會鎖表,來一個處理一個,并發最高,會存在復制問題)。

      總結

      MySQL這三種鎖的特性可大致歸納如下:

      表級鎖(偏讀):開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖沖突的概率最高,并發度最低。

      行級鎖(偏寫):開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,并發度也最高。

      頁面鎖:開銷和加鎖時間界于表鎖和行鎖之間;會出現死鎖;鎖定粒度界于表鎖和行鎖之間,并發度一般。

      以上就是今天的全部內容了,如果你感興趣的話,可以關注“阿Q說代碼”!你也可以后臺留言領取java干貨資料:學習筆記與大廠面試題。

      MySQL

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Excel字符串比較及清理垃圾字符
      下一篇:word怎么批量提取出生日期
      相關文章
      亚洲人妻av伦理| 亚洲中文字幕无码爆乳app| 亚洲日韩一区精品射精| 亚洲精品国产手机| 亚洲VA中文字幕无码一二三区| 日日噜噜噜噜夜夜爽亚洲精品| 亚洲乱码日产精品a级毛片久久 | 亚洲爆乳成av人在线视菜奈实| 亚洲精品免费网站| 亚洲精品第一综合99久久| 亚洲av永久无码精品三区在线4| 亚洲国产成人精品无码一区二区 | 亚洲欧洲中文日韩久久AV乱码| 亚洲av片一区二区三区| 亚洲国产精品碰碰| 亚洲日韩国产一区二区三区| 狠狠色婷婷狠狠狠亚洲综合| 伊人久久精品亚洲午夜| 国产成人综合亚洲亚洲国产第一页| 国产亚洲精品资在线| 国产亚洲精品成人AA片新蒲金| 中文字幕不卡亚洲| 亚洲国产精品无码久久一线 | 亚洲日韩久久综合中文字幕| 亚洲精品无播放器在线播放| 国内成人精品亚洲日本语音| 亚洲毛片网址在线观看中文字幕 | 亚洲小说图区综合在线| 亚洲av午夜电影在线观看| 免费亚洲视频在线观看| 亚洲综合色视频在线观看| 中文字幕日韩亚洲| 亚洲av永久无码精品表情包| 久久久久亚洲AV成人片| 亚洲卡一卡2卡三卡4麻豆| 2020亚洲男人天堂精品| 亚洲熟妇自偷自拍另欧美| 国产精品亚洲精品日韩动图| 国产亚洲美日韩AV中文字幕无码成人| 亚洲精品无码鲁网中文电影| 老色鬼久久亚洲AV综合|