MySQL知識(shí)點(diǎn)整理

1、事務(wù)

  • 事務(wù)四大特性

    • 原子性(Atomicity)
      • 事務(wù)是一個(gè)不可分割的最小工作單位,事務(wù)中的操作只有都發(fā)生和都不發(fā)生兩種情況
    • 一致性(Consistency)
      • 數(shù)據(jù)庫(kù)的完整性約束沒(méi)有被破壞,事務(wù)執(zhí)行的前后都是合法的數(shù)據(jù)狀態(tài)
    • 隔離性(Isolation)
      • 一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾,即一個(gè)事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對(duì)并發(fā)的其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾
    • 持久性(Durability)
      • 一個(gè)事務(wù)一旦提交成功,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變將是永久性的,接下來(lái)的其他操作或故障不應(yīng)對(duì)其有任何影響
  • 事務(wù)特性的技術(shù)實(shí)現(xiàn)

    • 原子性
      • 通過(guò)事務(wù)控制,保證一個(gè)事務(wù)里的任務(wù)要么全部成功,要么全部失敗,通過(guò)undo log來(lái)記錄上一次數(shù)據(jù)更新的狀態(tài),如果出現(xiàn)異常,可以通過(guò)undo log回滾到上一次的狀態(tài)
    • 隔離性
      • 通過(guò)事務(wù)隔離級(jí)別來(lái)保證相同事務(wù)讀取數(shù)據(jù)是一致的, 在Mysql的InnoDB存儲(chǔ)引擎中是可以通過(guò)MVCC與LBCC來(lái)實(shí)現(xiàn)隔離性, 通過(guò)生成一個(gè)類似快照的數(shù)據(jù)集,保證一個(gè)事務(wù)只能讀取到小于等于當(dāng)前事務(wù)id的數(shù)據(jù),以及之后其他事務(wù)刪除的數(shù)據(jù)
    • 持久性
      • 通過(guò)redo log與double write來(lái)確保一個(gè)事務(wù)中對(duì)數(shù)據(jù)的更新執(zhí)行成功后能永久的存儲(chǔ)在磁盤當(dāng)中,如果數(shù)據(jù)在刷盤之前崩潰,重啟后可以通過(guò)redo log恢復(fù)數(shù)據(jù),前提是數(shù)據(jù)頁(yè)本身沒(méi)有被破壞,是完整的,這個(gè)通過(guò)雙寫(xiě)緩沖(double write)保證
    • 一致性
      • 數(shù)據(jù)庫(kù)通過(guò)原子性、隔離性、持久性來(lái)保證一致性
      • ACID四大特性之中,C(一致性)是目的,A(原子性)、I(隔離性)、D(持久性)是手段,是為了保證一致性
  • 事務(wù)的并發(fā)問(wèn)題

    • 臟讀
      • 事務(wù)A讀取到了其他事務(wù)已經(jīng)修改但未提交的數(shù)據(jù),導(dǎo)致前后兩次讀取數(shù)據(jù)不一致
    • 不可重復(fù)讀
      • 事務(wù)A讀取到了其他事務(wù)修改或刪除且提交的數(shù)據(jù),導(dǎo)致前后兩次讀取數(shù)據(jù)不一致
    • 幻讀
      • 事務(wù)A讀取到了其他事務(wù)插入的數(shù)據(jù),導(dǎo)致前后兩次讀取數(shù)據(jù)不一致
  • 事務(wù)的隔離級(jí)別

    • 讀未提交(Read UnCommitted)
      • 這種隔離級(jí)別最低,這種級(jí)別一般是在理論上存在,數(shù)據(jù)庫(kù)隔離級(jí)別一般都高于該級(jí)別
      • 三種并發(fā)問(wèn)題都沒(méi)解決
    • 讀已提交(Read Committed)
      • 可以避免臟讀,但不可重復(fù)讀和幻讀的問(wèn)題仍然可能出現(xiàn)
    • 可重復(fù)度(Repeatable Read)
      • 可以避免臟讀和不可重復(fù)讀,但幻讀仍然存在
      • InnoDB中RR隔離級(jí)別通過(guò)間隙鎖+MVCC解決了大部分的幻讀問(wèn)題,只有一種特殊的幻讀情況無(wú)法解決
        • MVCC只能對(duì)快照讀起作用,而對(duì)于加鎖的讀請(qǐng)求,這種屬于當(dāng)前讀,當(dāng)前讀的話是可以查詢到其他事務(wù)的變更的,所以會(huì)產(chǎn)生幻讀
    • 串行化(Serializable)
      • 能解決臟讀、不可重復(fù)讀、幻讀問(wèn)題,會(huì)鎖住所有事務(wù),使每個(gè)事務(wù)串行執(zhí)行,一個(gè)事務(wù)結(jié)束另一個(gè)事務(wù)才能執(zhí)行
    • 以上隔離級(jí)別由上到下,執(zhí)行效率依次遞減

2、鎖

  • 鎖的分類
    • 按粒度區(qū)分
      • 行鎖
        • 鎖定是一行記錄
      • 表鎖
        • 鎖定是整張表
    • 按兼容性區(qū)分
      • 共享鎖
        • 也叫讀鎖,多個(gè)事務(wù)可以共享一把讀鎖,共享鎖會(huì)阻塞其他事務(wù)的修改
        • 手工在SQL后面加上LOCK IN SHARE MOD 進(jìn)行加鎖
      • 排它鎖
        • 也叫寫(xiě)鎖,一個(gè)事務(wù)獲取了一行數(shù)據(jù)的排它鎖,其他事務(wù)就不能再獲取這一行數(shù)據(jù)的共享鎖和排它鎖
        • 增刪改數(shù)據(jù)時(shí)會(huì)默認(rèn)加上排它鎖,也可以手工在SQL后面加上FOR UPDATE 加鎖
    • 按鎖的模式區(qū)分
      • 記錄鎖(Record Locks)
        • 屬于行鎖,表示對(duì)某一行記錄加鎖
        • 記錄鎖總是鎖定索引記錄(SELECT和UPDATE都會(huì)加鎖),即使表沒(méi)有定義索引。對(duì)于這種情況, InnoDB有一個(gè)隱藏的聚集索引進(jìn)行記錄鎖定。但因?yàn)榭赡軙?huì)掃描全表,那么該鎖也就會(huì)退化為表鎖
      • 間隙鎖(Gap Locks)
        • 鎖的是索引記錄之間的間隙,或者在第一個(gè)索引記錄之前或最后一個(gè)索引記錄之后的間隙上鎖
        • 對(duì)于具有唯一搜索條件的唯一索引,InnoDB只鎖定索引記錄,而不會(huì)鎖定間隙
        • 在RC隔離級(jí)別下,不會(huì)使用間隙鎖,在RR級(jí)別及以上才會(huì)使用它
        • 間隙鎖可以共存。一個(gè)事務(wù)采用的間隙鎖不會(huì)阻止另一個(gè)事務(wù)在同一間隙上采用間隙鎖。共享和排他間隙鎖之間沒(méi)有區(qū)別。它們彼此不沖突,并且執(zhí)行相同的功能
      • 臨鍵鎖(Next-Key Locks)
        • 臨鍵鎖是記錄鎖+間隙鎖的組合,鎖的是索引記錄上的記錄鎖和索引記錄之前間隙上的間隙鎖的組合
        • Next-Key 的鎖的范圍都是左開(kāi)右閉的
        • 只有在RR隔離級(jí)別中才會(huì)生效
      • 意向鎖(Intention Locks)
        • 意向鎖是表級(jí)鎖,指示事務(wù)稍后需要(或想要,表明鎖的意向)對(duì)表中的行使用哪種類型的鎖(共享鎖或獨(dú)占鎖),即用來(lái)標(biāo)識(shí)該表上面有數(shù)據(jù)被鎖住(或即將被鎖)
        • 意向共享鎖(IS):一個(gè)事務(wù)在獲?。ㄈ魏我恍?或者全表)S鎖之前,一定會(huì)先在所在的表上加IS鎖
        • 意向排它鎖(IX):一個(gè)事務(wù)在獲?。ㄈ魏我恍?或者全表)X鎖之前,一定會(huì)先在所在的表上加IX鎖
      • 插入意向鎖(Insert Intention Locks)
        • 插入意向鎖是在插入一條記錄行前,由 INSERT 操作產(chǎn)生的一種特別的間隙鎖
        • 該鎖用以表示插入意向,當(dāng)多個(gè)事務(wù)在同一區(qū)間插入位置不同的多條數(shù)據(jù)時(shí),事務(wù)之間并不會(huì)產(chǎn)生沖突
        • 雖然插入意向鎖中含有意向鎖三個(gè)字,但是它并不屬于意向鎖而屬于間隙鎖,因?yàn)橐庀蜴i是表鎖而插入意向鎖是行鎖
      • 自增鎖(AUTO-INC Locks)
        • 自增鎖是一種特殊的表級(jí)鎖,主要用于事務(wù)中插入自增字段

3、MVCC

    MVCC是Multiversion Concurrency Control的縮寫(xiě),翻譯過(guò)來(lái)是多版本并發(fā)控制,他也是一種并發(fā)控制的解決方案

    對(duì)數(shù)據(jù)的操作主要有2中,分別是讀和寫(xiě),而在并發(fā)場(chǎng)景下,就可能出現(xiàn)三種情況:`讀-讀并發(fā)`,`讀-寫(xiě)并發(fā)`,`寫(xiě)-寫(xiě)并發(fā)`。

    在沒(méi)有寫(xiě)的情況下`讀-讀并發(fā)`是不會(huì)出現(xiàn)問(wèn)題的,而`寫(xiě)-寫(xiě)并發(fā)`這種情況比較常用的就是通過(guò)加鎖的方式實(shí)現(xiàn)。那么`讀-寫(xiě)并發(fā)`則可以通過(guò)MVCC的機(jī)制解決
  • 快照讀和當(dāng)前讀

    • 快照讀就是讀取的是快照數(shù)據(jù),即快照生成的那一刻的數(shù)據(jù),像我們常用的普通的SELECT語(yǔ)句在不加鎖情況下就是快照讀
    • 當(dāng)前讀就是讀取最新數(shù)據(jù),所以加鎖的 SELECT,或者對(duì)數(shù)據(jù)進(jìn)行增刪改都會(huì)進(jìn)行當(dāng)前讀
    • 快照讀是MVCC實(shí)現(xiàn)的基礎(chǔ),而當(dāng)前讀是悲觀鎖實(shí)現(xiàn)的基礎(chǔ)
  • Undo Log

    • undo log是Mysql中比較重要的事務(wù)日志之一。是一種用于回退的日志,在事務(wù)沒(méi)提交之前,MySQL會(huì)先記錄更新前的數(shù)據(jù)到 undo log日志文件里面,當(dāng)事務(wù)回滾時(shí)或者數(shù)據(jù)庫(kù)崩潰時(shí),可以利用 undo log來(lái)進(jìn)行回退
    • 上面提到的存在undo log中的 更新前的數(shù)據(jù) 就是我們前面提到的快照
    • 行記錄的隱式字段
      • 據(jù)庫(kù)中的每行記錄中,除了保存了我們自己定義的一些字段,還有重要的隱式字段
        • db_row_id:隱藏主鍵,如果我們沒(méi)有給這個(gè)表創(chuàng)建主鍵,那么會(huì)以這個(gè)字段來(lái)創(chuàng)建聚簇索引
        • db_trx_id:對(duì)這條記錄做了最新一次修改的事務(wù)的ID
        • db_roll_ptr:回滾指針,指向這條記錄的上一個(gè)版本,其實(shí)他指向的就是Undo Log中的上一個(gè)版本的快照的地址
    • 每一次記錄變更之前都會(huì)先存儲(chǔ)一份快照到undo log中,那么這幾個(gè)隱式字段也會(huì)跟著記錄一起保存在undo log中
  • Read View

    • Read View 主要來(lái)幫我們解決可見(jiàn)性的問(wèn)題的,他會(huì)來(lái)告訴我們本次事務(wù)應(yīng)該看到哪個(gè)快照,不應(yīng)該看到哪個(gè)快照
    • 在 Read View 中有幾個(gè)重要的屬性
      • trx_ids:系統(tǒng)當(dāng)前未提交的事務(wù) ID 的列表。
      • low_limit_id:未提交的事務(wù)中最大的事務(wù) ID。
      • up_limit_id:未提交的事務(wù)中最小的事務(wù) ID。
      • creator_trx_id:創(chuàng)建這個(gè) Read View 的事務(wù) ID
    • 每開(kāi)啟一個(gè)事務(wù),我們都會(huì)從數(shù)據(jù)庫(kù)中獲得一個(gè)事務(wù) ID,這個(gè)事務(wù) ID 是自增長(zhǎng)的,通過(guò) ID 大小,我們就可以判斷事務(wù)的時(shí)間順序,事務(wù)ID大的事務(wù)應(yīng)該能看到事務(wù)ID小的事務(wù)的變更結(jié)果,反之則不能
    • 根據(jù)不同的事務(wù)隔離級(jí)別,Read View的獲取時(shí)機(jī)是不同的,在RC下,一個(gè)事務(wù)中的每一次SELECT都會(huì)重新獲取一次Read View,而在RR下,一個(gè)事務(wù)中只在第一次SELECT的時(shí)候會(huì)獲取一次Read View
    • 所以在RR這種事務(wù)隔離級(jí)別之下,因?yàn)橛蠱VCC機(jī)制,就可以解決不可重復(fù)讀的問(wèn)題,因?yàn)樗挥性诘谝淮蜸ELECT的時(shí)候才會(huì)獲取一次Read View,天然不存在重復(fù)讀的問(wèn)題了
  • MVCC就是通過(guò)Read View + Undo Log來(lái)實(shí)現(xiàn)的,undo log中保存了歷史快照,而Read View 用來(lái)判斷具體哪一個(gè)快照是可見(jiàn)的

4、InnoDB 內(nèi)存結(jié)構(gòu)

image.png
  • Buffer Pool

    • Buffer Pool 緩存的是頁(yè)面信息,包括數(shù)據(jù)頁(yè)、索引頁(yè)、鎖信息等
    • MySQL表數(shù)據(jù)是以頁(yè)為單位,查詢一條記錄,會(huì)從硬盤把一頁(yè)的數(shù)據(jù)加載出來(lái),加載出來(lái)的數(shù)據(jù)叫數(shù)據(jù)頁(yè),會(huì)放入到 Buffer Pool
    • 后續(xù)的查詢先從 Buffer Pool 中找,沒(méi)有命中再去硬盤加載,減少硬盤 IO 開(kāi)銷,提升性能。更新表數(shù)據(jù)的時(shí),如果 Buffer Pool 里命中數(shù)據(jù),就直接在 Buffer Pool 里更新
    • 緩沖池使用最近最少使用的 (LRU) 算法的變體進(jìn)行緩存數(shù)據(jù)頁(yè)
    • 后續(xù)對(duì)數(shù)據(jù)的增刪改查都是在Buffer Pool里操作
      • 查詢:從磁盤加載到緩存,后續(xù)直接查緩存
      • 插入:直接寫(xiě)入緩存
      • 更新刪除:緩存中存在直接更新,不存在加載數(shù)據(jù)頁(yè)到緩存更新
    • 直接更新數(shù)據(jù)的緩存頁(yè)稱為臟頁(yè),緩存頁(yè)刷盤后稱為干凈頁(yè)
  • Change Buffer(寫(xiě)緩沖)

    • 如果數(shù)據(jù)頁(yè)不是唯一索引,不存在數(shù)據(jù)重復(fù)的情況,就不需要從磁盤加載索引頁(yè)判斷數(shù)據(jù)是不是重復(fù)(唯一性檢查)

    • 這種情況下可以先把修改記錄在內(nèi)存的緩沖池中,從而提升更新語(yǔ)句(Insert、Delete、Update)的執(zhí)行速度

    • Change Buffer 記錄刷到數(shù)據(jù)頁(yè)的操作叫做 merge

      • 訪問(wèn)這個(gè)數(shù)據(jù)頁(yè)時(shí)觸發(fā)
      • 后臺(tái)線程定時(shí)觸發(fā)
      • 數(shù)據(jù)庫(kù) shut down時(shí)觸發(fā)
      • redo log 寫(xiě)滿時(shí)觸發(fā)

      redo log 寫(xiě)滿時(shí)觸發(fā)

  • Log Buffer(Redo Log)日志緩存

    • 對(duì)表數(shù)據(jù)進(jìn)行更新時(shí)會(huì)把 在某個(gè)數(shù)據(jù)頁(yè)上做了什么修改 記錄到 redo log buffer 里,之后會(huì)刷盤到redo log文件中

    • 刷盤時(shí)機(jī)

      InnoDB存儲(chǔ)引擎為redo log的刷盤策略提供了innodb_flush_log_at_trx_commit參數(shù),它支持三種策略

      • 設(shè)置為0(延遲寫(xiě))
        • 事務(wù)提交的時(shí)不會(huì)主動(dòng)觸發(fā)刷盤操作
      • 設(shè)置為1(默認(rèn)值,實(shí)時(shí)寫(xiě),實(shí)時(shí)刷)
        • 每次事務(wù)提交時(shí)都將進(jìn)行刷盤操作
      • 設(shè)置為2(實(shí)時(shí)寫(xiě),延遲刷)
        • 表示每次事務(wù)提交時(shí)都只把redo log buffer內(nèi)容寫(xiě)入page cache
      • InnoDB存儲(chǔ)引擎有一個(gè)后臺(tái)線程,每隔1秒,就會(huì)把redo log buffer中的內(nèi)容寫(xiě)到文件系統(tǒng)緩存(page cache),然后調(diào)用fsync刷盤
      • redo log buffer占用的空間即將達(dá)到innodb_log_buffer_size一半的時(shí)候,后臺(tái)線程會(huì)主動(dòng)刷盤
最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 工作中,我們一直是通過(guò)前端工具連接公司的數(shù)據(jù)庫(kù)系統(tǒng)進(jìn)行數(shù)據(jù)查詢。 最近,對(duì)sql的知識(shí)框架進(jìn)行了初步的整理(mys...
    祥云的簡(jiǎn)書(shū)閱讀 186評(píng)論 0 1
  • 0. MySQL邏輯架構(gòu) 最上層是一些客戶端和連接服務(wù),包含本地sock通信和大多數(shù)基于客戶端/服務(wù)端工具實(shí)現(xiàn)的類...
    beg4閱讀 1,116評(píng)論 0 1
  • 感覺(jué)好久沒(méi)有看MySQL相關(guān)的書(shū)了,最近邊復(fù)習(xí),邊整理下感覺(jué)重要的知識(shí)點(diǎn),一點(diǎn)點(diǎn)的由簡(jiǎn)入繁,先從整體概念上理解下,...
    架構(gòu)技術(shù)專欄閱讀 1,379評(píng)論 0 50
  • 索引相關(guān) 索引類型 主鍵索引:數(shù)據(jù)列不允許重復(fù),不允許為NULL。一個(gè)表只能有一個(gè)主鍵索引。InnoDB的主鍵索引...
    zhong0316閱讀 1,996評(píng)論 0 20
  • MySQL 數(shù)據(jù)庫(kù)認(rèn)知數(shù)據(jù)庫(kù)認(rèn)知數(shù)據(jù)庫(kù):存放數(shù)據(jù)的倉(cāng)庫(kù),本質(zhì)是一個(gè)文件系統(tǒng),將數(shù)據(jù)以特定的格式存儲(chǔ)在一張張表中。特...
    CherisFan閱讀 241評(píng)論 0 4

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