MySQL 鎖之二——表鎖

1、概述

MySQL 表級(jí)鎖是以單個(gè)表為粒度的鎖,InnoDB 和 MyISAM 引擎都支持表級(jí)鎖;

2、表鎖分類及原理

2.1 表級(jí)共享鎖和表級(jí)排它鎖

加鎖方式:lock tables … read/write;
解鎖方式:可以使用 unlock table; 主動(dòng)解鎖,也可以等客戶端斷開連接時(shí)自動(dòng)釋放;
兼容性:
共享鎖可以兼容其他共享鎖,但不兼容排它鎖,排它鎖則不兼容任何鎖;
注意:
lock tables 語(yǔ)法除了會(huì)限制別的線程的讀寫外,也限定了本線程的操作對(duì)象;
舉例說(shuō)明:如果在某個(gè)線程 A 中執(zhí)行 lock table t1 read, t2 write; 這個(gè)語(yǔ)句,則其他線程寫 t1、讀寫 t2 的語(yǔ)句都會(huì)被阻塞。同時(shí),線程 A 在執(zhí)行 unlock tables 之前,也只能執(zhí)行讀 t1、讀寫 t2 的操作。連寫 t1 都不允許,自然也不能訪問(wèn)其他表;

2.2 意向共享鎖和意向排它鎖

意向鎖是用來(lái)解決表級(jí)鎖和行級(jí)鎖的共存問(wèn)題的,那么它如何做到呢?

例如:事務(wù) A 在表的某一行中加了記錄鎖,事務(wù) B 想在該表上添加表級(jí)排它鎖,這時(shí),事務(wù) B 想要知道是否可以添加表級(jí)排它鎖,就要做全表掃描,看是否有記錄上有記錄鎖,這樣效率極其低下,基本不可用,這時(shí)就需要意向鎖來(lái)解決該問(wèn)題;

有了意向鎖之后,事務(wù) A 在申請(qǐng)記錄鎖之前,數(shù)據(jù)庫(kù)會(huì)自動(dòng)先給事務(wù) A 先申請(qǐng)表的意向排他鎖,當(dāng)事務(wù) B 去申請(qǐng)表級(jí)排它鎖時(shí)就會(huì)失敗,因?yàn)楸砩嫌幸庀蚺潘i之后事務(wù) B 申請(qǐng)表級(jí)排它鎖時(shí)會(huì)被阻塞,這樣事務(wù) B 就避免了全表掃描操作了;

所以,總結(jié)一下意向鎖的作用:
當(dāng)一個(gè)事務(wù)在需要獲取資源的鎖定時(shí),數(shù)據(jù)庫(kù)會(huì)自動(dòng)給該事務(wù)申請(qǐng)一個(gè)該表的意向鎖,如果需要一個(gè)共享鎖定,就申請(qǐng)一個(gè)意向共享鎖,如果需要排他鎖定,則申請(qǐng)一個(gè)意向排他鎖,這樣其他事務(wù)再來(lái)申請(qǐng)資源的時(shí)候,就不用掃描全表來(lái)判斷是否有沖突了;

2.3 自增鎖

自增鎖是一種專門針對(duì) AUTO_INCREMENT 類型的列的鎖,用來(lái)保證自增主鍵的順序和唯一性,有幾種模式可選,通過(guò) innodb_autoinc_lock_mode 參數(shù)來(lái)設(shè)置模式,同一種模式對(duì)于不同的插入類型起到的作用會(huì)不同;

2.3.1 插入類型

Simple Insert(簡(jiǎn)單插入):
插入的記錄數(shù)以及內(nèi)容都確認(rèn),語(yǔ)句包括:insert into values、replace;

Bulk Insert(批量插入):
插入的記錄數(shù)不能馬上確認(rèn),語(yǔ)句包括:INSERT ... SELECT、REPLACE ... SELECT、LOAD DATA;

Mixed-mode Insert(混合插入):
指插入的值中有部分 value 的 id 確認(rèn),另一部分則默認(rèn)自增,如:

  • INSERT INTO t1 (c1,c2) VALUES (1,‘a(chǎn)‘), (NULL,‘b‘), (5,‘c‘), (NULL,‘d‘);
  • INSERT ... ON DUPLICATE KEY UPDATE;
2.3.2 自增模式

innodb_autoinc_lock_mode = 0
優(yōu)點(diǎn):極其安全;
缺點(diǎn):寫入性能差,任何一種 Insert 語(yǔ)句,都會(huì)產(chǎn)生一個(gè)自增鎖,即:所有的插入語(yǔ)句都串行執(zhí)行;

innodb_autoinc_lock_mode = 1
優(yōu)點(diǎn):非常安全,對(duì)于 “innodb_autoinc_lock_mode = 0”,性能要好很多;
缺點(diǎn):依然會(huì)產(chǎn)生自增鎖;
運(yùn)行原理:

  • 當(dāng)發(fā)生 Bulk Inserts 時(shí),會(huì)產(chǎn)生一個(gè)特殊的自增鎖直到語(yǔ)句結(jié)束,注意:(這里是語(yǔ)句結(jié)束就釋放鎖,并不是事務(wù)結(jié)束哦,因?yàn)橐粋€(gè)事務(wù)可能包含很多語(yǔ)句),對(duì)于 Simple Inserts,則使用的是一種輕量級(jí)鎖,只要獲取了相應(yīng)的自增 key 就釋放鎖,并不會(huì)等到語(yǔ)句結(jié)束;
  • 當(dāng)有自增鎖時(shí),這種輕量級(jí)的鎖也不會(huì)加鎖成功,會(huì)等待;

思考:這里的自增鎖起到什么作用呢?
他能保證 Bulk Insert 自增 id 的連續(xù)性,防止在 Bulk Insert 的時(shí)候,被其他的插入語(yǔ)句搶走自增值;

innodb_autoinc_lock_mode = 2
優(yōu)點(diǎn):性能最好;
缺點(diǎn):Bulk Insert 時(shí)可能得到不連續(xù)的自增 id,SBR 模式下,會(huì)導(dǎo)致復(fù)制出錯(cuò);
原理:當(dāng)進(jìn)行 Bulk Insert 的時(shí)候,不會(huì)產(chǎn)生自增鎖,因?yàn)樗窃试S其他插入語(yǔ)句同時(shí)進(jìn)行插入,來(lái)一個(gè)記錄,插入分配一個(gè)自增值,不會(huì)預(yù)分配;

2.4 MDL 讀鎖和 MDL 寫鎖

MDL 鎖也叫元數(shù)據(jù)鎖,不需要顯示添加,是在訪問(wèn)表的時(shí)候自動(dòng)添加,若在表上做增刪改查,則添加 MDL 讀鎖,若對(duì)表結(jié)構(gòu)進(jìn)行變更,則添加 MDL 寫鎖;

讀鎖之間不互斥,讀寫鎖、寫鎖之間互斥;

3、總結(jié)

  • InnoDB 和 MySIAM 都支持表級(jí)鎖;
  • 表級(jí)共享鎖和表級(jí)排它鎖可以主動(dòng)加鎖解鎖,其他表級(jí)鎖都不需要主動(dòng)操作;
  • 意向鎖解決了表級(jí)鎖和行級(jí)鎖共存的問(wèn)題;
  • 自增鎖有三種模式可選,我們可根據(jù)業(yè)務(wù)需要靈活配置;
  • MDL 鎖只在修改表結(jié)構(gòu)的時(shí)候起作用;

4、參考資料

5、遺留問(wèn)題

MySQL 的 SBR 模式是什么,如何工作,有什么優(yōu)缺點(diǎn)?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容