校招面試題mysql鎖總結(jié)

目錄

  • 鎖定義
  • 鎖分類
  • 讀鎖和寫鎖
  • 表鎖和行鎖
  • InnoDB共享鎖和排他鎖
  • InnoDB意向鎖和排他鎖
  • InnoDB行鎖
  • InnoDB間隙鎖
    • 概念
    • InnoDB使用間隙鎖目的
  • InnoDB行鎖實(shí)現(xiàn)方式
  • 閑聊
  • 【邁莫coding】

鎖定義

鎖是計(jì)算機(jī)協(xié)調(diào)多個(gè)進(jìn)程或線程并發(fā)訪問某一資源的機(jī)制。

在數(shù)據(jù)庫中,除了傳統(tǒng)的計(jì)算資源(如CPU, RAM, I/O等)的爭用以外,數(shù)據(jù)也是一種供需要用戶共享的資源。鎖沖突也是影響數(shù)據(jù)庫并發(fā)訪問性能的一個(gè)重要因素。

鎖分類

  • 從性能上分為樂觀鎖(用版本對(duì)比來實(shí)現(xiàn))和悲觀鎖
  • 從數(shù)據(jù)庫操作的類型分為讀鎖和寫鎖(都屬于悲觀鎖)
  • 從對(duì)數(shù)據(jù)操作的粒度分:分為表鎖和行鎖

讀鎖和寫鎖

  • 讀鎖(共享鎖):針對(duì)同一份數(shù)據(jù),多個(gè)讀操作可以同時(shí)進(jìn)行而不會(huì)互相影響,但是會(huì)阻塞寫操作
  • 寫鎖(互斥鎖):當(dāng)前寫操作沒有完成前,它會(huì)阻斷其他寫鎖和讀鎖

表鎖和行鎖

表鎖

  • 每次操作時(shí)會(huì)鎖住整張表。開銷小,加鎖快;不會(huì)發(fā)生死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高;并發(fā)度最低;
  • 表鎖更適合于以查詢?yōu)橹?,并發(fā)用戶少,只有少量按索引條件更新數(shù)據(jù)的應(yīng)用,如Web應(yīng)用

行鎖

  • 每次操作鎖住一行數(shù)據(jù)。開銷大,加鎖慢;會(huì)出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低;并發(fā)度最高;
  • 行級(jí)鎖只在存儲(chǔ)引擎層實(shí)現(xiàn),而mysql服務(wù)器沒有實(shí)現(xiàn)。
  • 行級(jí)鎖更適合于有大量按索引條件并發(fā)更新少量不同數(shù)據(jù),同時(shí)又有并發(fā)查詢的應(yīng)用,如一些- 在線事務(wù)處理(OLTP)系統(tǒng)

InnoDB共享鎖和排他鎖

InnoDB實(shí)現(xiàn)了兩種類型的行鎖:

  • 共享鎖(S): 允許一個(gè)事務(wù)去讀一行,阻止其他事務(wù)獲得相同數(shù)據(jù)集的排他鎖
  • 排他鎖(X): 允許獲得排他鎖的事務(wù)更新數(shù)據(jù),阻止其他事務(wù)取得相同數(shù)據(jù)集的共享讀鎖和排他寫鎖

為了允許行鎖和表鎖共存,實(shí)現(xiàn)多粒度鎖機(jī)制,InnoDB還有兩種內(nèi)部使用的意向鎖(Intention Locks),這兩種意向鎖都是表鎖:

  • 意向共享鎖(IS):事務(wù)打算給數(shù)據(jù)行加行共享鎖,事務(wù)在給一個(gè)數(shù)據(jù)行加共享鎖前必須先取得該表的IS鎖
  • 意向排他鎖(IX):事務(wù)打算給數(shù)據(jù)行加行排他鎖,事務(wù)在給一個(gè)數(shù)據(jù)行加排他鎖前必須先取得該表的IX鎖

InnoDB意向鎖和排他鎖

  • 意向鎖是 InnoDB 引擎自動(dòng)加的,不需要用戶干預(yù)

  • 對(duì)于 UPDATE INSERT DELETE 語句,InnoDB引擎會(huì)自動(dòng)給涉及數(shù)據(jù)集加排他鎖(X)

  • 對(duì)于普通 SELECT 語句,InnoDB不會(huì)加任何鎖

  • 事務(wù)可以通過以下語句顯式地給結(jié)果集加共享鎖或排它鎖

    • 共享鎖(S): SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE 。 其他 session 仍然可以查詢記錄,并也可以對(duì)該記錄加 share mode 的共享鎖。但是如果當(dāng)前事務(wù)需要對(duì)該記錄進(jìn)行更新操作,則很有可能造成死鎖。
    • 排它鎖(X): SELECT * FROM table_name WHERE ... FOR UPDATE。其他 session 可以查詢?cè)撚涗洠遣荒軐?duì)該記錄加共享鎖或排他鎖,而是等待獲得鎖

InnoDB行鎖

  • innoDB行鎖通過索引上的索引項(xiàng)加鎖來實(shí)現(xiàn)的,這一點(diǎn) MySQL 與 Oracle 不同,后者是通過在數(shù)據(jù)塊中對(duì)相應(yīng)數(shù)據(jù)行加鎖來實(shí)現(xiàn)的。InnoDB 這種行鎖實(shí)現(xiàn)特點(diǎn)意味著:只有通過索引條件檢索數(shù)據(jù),InnoDB 才使用行級(jí)鎖,否則,InnoDB 將使用表鎖!
  • 不論是使用主鍵索引、唯一索引或普通索引,InnoDB 都會(huì)使用行鎖來對(duì)數(shù)據(jù)加鎖。
  • 只有執(zhí)行計(jì)劃真正使用了索引,才能使用行鎖:即便在條件中使用了索引字段,但是否使用索引來檢索數(shù)據(jù)是由 MySQL 通過判斷不同執(zhí)行計(jì)劃的代價(jià)來決定的,如果 MySQL 認(rèn)為全表掃描效率更高,比如對(duì)一些很小的表,它就不會(huì)使用索引,這種情況下 InnoDB 將使用表鎖,而不是行鎖。
  • 由于 MySQL 的行鎖是針對(duì)索引加的鎖,不是針對(duì)記錄加的鎖,所以雖然多個(gè)session訪問不同行的記錄, 但是如果是使用相同的索引鍵, 是會(huì)出現(xiàn)鎖沖突的(后使用這些索引的session需要等待先使用索引的session釋放鎖后,才能獲取鎖)。 應(yīng)用設(shè)計(jì)的時(shí)候要注意這一點(diǎn)。

InnoDB間隙鎖

概念

當(dāng)我們用范圍條件而不是相等條件檢索數(shù)據(jù),并請(qǐng)求共享或排他鎖時(shí),InnoDB會(huì)給符合條件的已有數(shù)據(jù)記錄的索引項(xiàng)加鎖;對(duì)于鍵值在條件范圍內(nèi)但并不存在的記錄,叫做“間隙(GAP)”,InnoDB也會(huì)對(duì)這個(gè)“間隙”加鎖,這種鎖機(jī)制就是所謂的間隙鎖(Next-Key鎖)。

很顯然,在使用范圍條件檢索并鎖定記錄時(shí),InnoDB這種加鎖機(jī)制會(huì)阻塞符合條件范圍內(nèi)鍵值的并發(fā)插入,這往往會(huì)造成嚴(yán)重的鎖等待。因此,在實(shí)際應(yīng)用開發(fā)中,尤其是并發(fā)插入比較多的應(yīng)用,我們要盡量優(yōu)化業(yè)務(wù)邏輯,盡量使用相等條件來訪問更新數(shù)據(jù),避免使用范圍條件。

InnoDB使用間隙鎖的目的:

  • 防止幻讀,以滿足相關(guān)隔離級(jí)別的要求;滿足恢復(fù)和復(fù)制的需要

  • MySQL 通過 BINLOG 錄入執(zhí)行成功的 INSERT 、 UPDATE 、 DELETE 等更新數(shù)據(jù)的 SQL 語句,并由此實(shí)現(xiàn) MySQL 數(shù)據(jù)庫的恢復(fù)和主從復(fù)制。MySQL 的恢復(fù)機(jī)制(復(fù)制其實(shí)就是在 Slave Mysql 不斷做基于 BINLOG 的恢復(fù))有以下特點(diǎn):

    • 一是 MySQL 的恢復(fù)是 SQL 語句級(jí)的,也就是重新執(zhí)行 BINLOG 中的 SQL 語句。
    • 二是 MySQL 的 Binlog 是按照事務(wù)提交的先后順序記錄的, 恢復(fù)也是按這個(gè)順序進(jìn)行的。

由此可見,MySQL 的恢復(fù)機(jī)制要求:在一個(gè)事務(wù)未提交前,其他并發(fā)事務(wù)不能插入滿足其鎖定條件的任何記錄,也就是不允許出現(xiàn)幻讀。

InnoDB加鎖方式

- 隱式鎖定:

InnoDB在事務(wù)執(zhí)行過程中,使用兩階段鎖協(xié)議:

隨時(shí)都可以執(zhí)行鎖定,InnoDB會(huì)根據(jù)隔離級(jí)別在需要的時(shí)候自動(dòng)加鎖;

鎖只有在執(zhí)行commit或者rollback的時(shí)候才會(huì)釋放,并且所有的鎖都是在同一時(shí)刻被釋放。

- 顯式鎖定 :

select ... lock in share mode //共享鎖 
select ... for update //排他鎖 

- select for update:

在執(zhí)行這個(gè) select 查詢語句的時(shí)候,會(huì)將對(duì)應(yīng)的索引訪問條目進(jìn)行上排他鎖(X 鎖),也就是說這個(gè)語句對(duì)應(yīng)的鎖就相當(dāng)于update帶來的效果。

- select *** for update 的使用場景

為了讓自己查到的數(shù)據(jù)確保是最新數(shù)據(jù),并且查到后的數(shù)據(jù)只允許自己來修改的時(shí)候,需要用到 for update 子句。

- select lock in share mode

in share mode 子句的作用就是將查找到的數(shù)據(jù)加上一個(gè) share 鎖,這個(gè)就是表示其他的事務(wù)只能對(duì)這些數(shù)據(jù)進(jìn)行簡單的select 操作,并不能夠進(jìn)行 DML 操作。

- select *** lock in share mode 使用場景

為了確保自己查到的數(shù)據(jù)沒有被其他的事務(wù)正在修改,也就是說確保查到的數(shù)據(jù)是最新的數(shù)據(jù),并且不允許其他人來修改數(shù)據(jù)。但是自己不一定能夠修改數(shù)據(jù),因?yàn)橛锌赡芷渌氖聞?wù)也對(duì)這些數(shù)據(jù) 使用了 in share mode 的方式上了 S 鎖。

- 性能影響

  • select for update 語句,相當(dāng)于一個(gè) update 語句。在業(yè)務(wù)繁忙的情況下,如果事務(wù)沒有及時(shí)的commit或者rollback 可能會(huì)造成其他事務(wù)長時(shí)間的等待,從而影響數(shù)據(jù)庫的并發(fā)使用效率。
  • select lock in share mode 語句是一個(gè)給查找的數(shù)據(jù)上一個(gè)共享鎖(S 鎖)的功能,它允許其他的事務(wù)也對(duì)該數(shù)據(jù)上S鎖,但是不能夠允許對(duì)該數(shù)據(jù)進(jìn)行修改。如果不及時(shí)的commit 或者rollback 也可能會(huì)造成大量的事務(wù)等待。

閑聊

  • 讀完文章,自己是不是和mysql鎖的cp率又提高了
  • 我是邁莫,歡迎大家和我交流

文章也會(huì)持續(xù)更新,可以微信搜索「 邁莫coding 」第一時(shí)間閱讀。

最后編輯于
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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