成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

阿里面試官:MySQL是如何實現ACID的?

數據庫 MySQL
今天,筆者簡單談談自己對ACID特性實現原理的理解。本文主要探討MYSQL InnoDB引擎下的ACID實現原理,對什么是事務,隔離級別簡單回顧一下。

[[425940]]

 作為二本上岸大廠的后端應屆生,深知沒人帶一路摸索的艱辛,想把自己的心路歷程與經驗心得收獲分享給大家。后期大廠面試系列持續更新中.....

1前文

之前有同學在面阿里二面被問到:MYSQL是如何實現ACID的?其實,如果叫簡單介紹什么是ACID,大家肯定都能回答,但是,想要答好底層如何實現ACID特性的,還得考考功力啦!

今天,筆者簡單談談自己對ACID特性實現原理的理解。本文主要探討MYSQL InnoDB引擎下的ACID實現原理,對什么是事務,隔離級別簡單回顧一下。

2事務與ACID

何為事務呢?書上給予的概念多而難于理解,筆者對事務的理解:一系列操作組成,要么全部成功,要么全部失敗。它具備ACID四大特性,在并發下,可能存在臟讀、幻讀、不可重復讀的并發問題,于是又引出了四大隔離級別。

01事務ACID特性

MYSQL作為一個關系型數據庫,以最常見的InnoDB引擎來說,是如何保證ACID的。

(Atomicity)原子性:一些列操作要么全部成功,要么全部失敗

(Isolation)隔離性:事務的結果只有提交了其他事務才可見

(Consistency)一致性:數據庫總時從一個一致狀態變到另一個一致狀態(事務修改前后的數據總體保證一致 轉賬)

(Durability)持久性:事務提交后,對數據修改永久的

02原子性

在聊原子性之前,我得先給大家普及一個東西——undo log,這是啥玩意兒呢?如果想要詳細了解或則想知道它具體內部咋實現的可以仔細去看書,這里我就簡單分享我的理解,知道這些,面試基本夠用啦。

undo log,它是一種回滾日志,既可以用來實現隔離性MVCC,也可以保證原子性。MVCC待會談論。實現原子性的關鍵,是事務回滾時能夠撤銷所有已經成功執行的sql語句。

當事務對數據庫進行修改時,InnoDB會生成對應的undo log,undo log會保存事務開始前老版本的數據,當事務發生異常,便會rollback回滾到老版本狀態。當發生回滾時,InnoDB會根據undo log的內容做相反邏輯操作。

  • insert語句,回滾時會執行 delete;
  • delete語句,回滾時會執行insert;
  • update語句,回滾時便執行相反的update,把數據改回來。

總之,MYSQL的原子性便是由undo log來保證,undo log的作用我做了一下歸納總結:

作用:undolog記錄事務開始前老版本數據,用于實現回滾,保證原子性,實現MVCC,會將數據修改前的舊版本保存在undolog,然后行記錄有個隱藏字段回滾指針指向老版本。

03持久性

在聊持久性之前,我們得先知道redo log。老規矩,想深入學習理解看書噢,這里只做筆者面試回答分享。

我們以一個生活小案例來理解一下下:

redo log,是一種物理日志。它類似于一個卸貨的小推車,我們卸貨若是每下一件物品就拿著去入庫,那豈不是特浪費時間(效率低、還要找到合適存庫位置)。此時,若有一個小推車,我們將貨物首先存放在小推車,當推車滿了再往庫里存,豈不大大增加了效率。

MYSQL中也用了類似思想,我們再更新數據庫時,先將更新操作記錄在redo log日志,等redo log滿了或則MYSQL空閑了再刷盤。

其實就是MySQL里經常說到的WAL技術,WAL的全稱是Write-Ahead Logging,它的關鍵點就是先寫日志,再寫磁盤,也就是先裝小推車,等不忙的時候再裝庫。

總之,MYSQL的持久性便是由redo log來保證,redo log的作用我做了一下歸納總結:

redo log

物理日志

作用:會記錄事務開啟后對數據做的修改,crash-safe

特性:空間一定,寫完后會循環寫,有兩個指針write pos指向當前記錄位置,checkpoint指向將擦除的位置,redolog相當于是個取貨小車,貨物太多時來不及一件一件入庫太慢了這樣,就先將貨物放入小車,等到貨物不多或則小車滿了或則店里空閑時再將小車貨物送到庫房。用于crash-safe,數據庫異常斷電等情況可用redo log恢復。

以下只作了解:

寫入流程:先寫redo log buffer,然后wite到文件系統的page cache,此時并沒有持久化,然后fsync持久化到磁盤

寫入策略:根據innodb_flush_log_at_trx_commit參數控制(我的記憶:innodb以事務的什么提交方式刷新日志)

0——>事務提交時只把redo log留在redo log buffer

1——>將redo log直接持久化到磁盤(所以有個雙“1”配置,后面會講)

2——>只是把redo log寫到page cache

04隔離性

說到隔離性,我們都知道MYSQL有四種隔離級別,用來解決存在的并發問題。臟讀、幻讀、不可重復讀。

那么不同隔離級別,隔離性是怎樣實現的呢?具體實現原理是怎樣的呢?接下來我們就談談,看不懂沒關系,老規矩,結尾會進行總結滴!

一句話:鎖+MVCC。

1、表鎖

  • lock table table_name read/write
  • myisam執行select自動加讀鎖,執行update/delete/insert自動加寫鎖
  • 表加了讀鎖,不會阻塞其他線程的讀操作,阻塞寫操作
  • 表加了寫鎖,讀寫操作都阻塞

2、行鎖

鎖的類型

  • 間隙鎖-gap lock:鎖定區間范圍,防止幻讀,左開右開,只在可重復讀隔離級別下生效—|—為了阻止多個事務將記錄插入到同一范圍內,而這會導致幻讀問題的產生
  • 記錄鎖-record Lock:鎖定行記錄,索的索引,索引失效,為表鎖
  • 臨鍵鎖-next-key Lock:record lock+gap lock 左開右閉(解決幻讀)

鎖的模式

  • select .... for update
  • 持有寫鎖,別的不可加讀鎖,也不可加寫鎖
  • select .... lock in share mode
  • 持有讀鎖,別的可以再加讀鎖,不可加寫鎖
  • 共享鎖-讀鎖-S鎖
  • 排他鎖-寫鎖-X鎖
  • 意向鎖:讀意向鎖+寫意向鎖
  • 自增鎖

需要的時候加上,并不是馬上釋放,等事務提交才釋放,兩階段鎖協議

3、全局鎖——全庫邏輯備份

4、死鎖

  • 兩個或多個事務在同一資源上相互占用,并請求加鎖時,造成相互等待,無限阻塞
  • innodb回滾擁有最少排他行級鎖的事務
  • 設置鎖等待超時時間

樂觀鎖與悲觀鎖

  • 悲觀鎖用數據庫自帶鎖機制——寫多
  • 樂觀鎖用version版本機制或CAS算法——讀多寫少,很少發生沖突情況

MVCC

是什么:多版本并發控制。

原理提煉總結:使用版本鏈+Read View

詳解:

版本鏈:同一行數據可能有多個版本

innodb數據表每行數據記錄會有幾個隱藏字段,row_id,事務ID,回滾指針。

1、Innodb采用主鍵索引(聚簇索引),會利用主鍵維護索引,若表沒有主鍵,就用第一個非空唯一索引,若沒有唯一索引,則用row_id這個隱藏字段作為主鍵索引。

2、事務開啟會向系統申請一個事務ID,嚴格遞增,會向行記錄插入最近操作它的那個事務的ID

3、undolog會記錄事務前老版本數據,然后行記錄中回滾指針會指向老版本位置,如此形成一條版本鏈。因此可以利用undo log實現回滾,保證原子性,同時用于實現MVCC版本鏈。

圖3 版本鏈形成

Read View讀已提交隔離級別下,會在每次查詢都生成一個Read View,可重讀讀只在事務開始時生成一個Read View,以后每次查詢都用這個Read View,以此實現不同隔離界別。

Read View里面包含些什么?(一致性視圖)

一個數組+up_limit_id(低水位)+low_limit_id(高水位)(這里的up,low沒寫錯,就是這么定義的)

1、數組里包含事務啟動時當前活躍事務ID(未提交事務),低水位就是活躍事務最小ID,高水位就是下一次將分配的事務ID,也就是目前最大事務ID+1。

數據可見性規則是怎樣實現的?

數據版本的可見性規則,就是基于數據的row trx_id和這個一致性視圖(Read View)的對比結果得到的。

視圖數組把所有的trx_id 分成了幾種不同的情況

圖4 數據版本可見性規則

讀取原理:

某事務T要訪問數據A,先獲取該數據A中的事務id(獲取最近操作它的事務的事務ID),對比該事務T啟動時刻生成的readview:

1、如果在readview的左邊(比readview都小),表示這個事務可以訪問這數據(在左邊意味著該事務已經提交)

2、如果在readview的右邊(比readview都大),表示這個版本是由將來啟動的事務生成的,是肯定不可見的;

3、如果當前事務在未提交事務集合中:

a、若 row trx_id在數組中,表示這個版本是由還沒提交的事務生成的,不可見;

b. 若 row trx_id不在數組中,表示這個版本是已經提交了的事務生成的,可見。

不可以訪問,獲取roll_pointer,通過版本鏈取上一版本。

根據數據歷史版本事務ID再重新與視圖數組對比。

這樣執行下來,雖然期間這一行數據被修改過,但是事務A不論在什么時候查詢,看到這行數據的結果都是一致的,所以我們稱之為一致性讀。

總之,MYSQL的隔離性便是由MVCC+鎖來保證,各個隔離級別實現原理我做了一下歸納總結:

隔離級別原理及解決問題分析:

  • 讀未提交:原理:直接讀取數據,不能解決任何并發問題
  • 讀已提交:讀操作不加鎖,寫操作加排他鎖,解決了臟讀。原理:利用MVCC實現,每一句語句執行前都會生成Read View(一致性視圖)
  • 可重復讀:MVCC實現,只有事務開始時會創建Read View,之后事務里的其他查詢都用這個Read View。解決了臟讀、不可重復讀,快照讀(普通查詢,讀取歷史數據)使用MVCC解決了幻讀,當前讀(讀取最新提交數據)通過間隙鎖解決幻讀(lock in share mode、for update、update、detete、insert),間隙鎖在可重復讀下才生效。(默認隔離級別)
  • 可串行化:原理:使用鎖,讀加共享鎖,寫加排他鎖,串行執行

總結:讀已提交和可重復讀實現原理就是MVCC Read View不同的生成時機。可重復讀只在事務開始時生成一個Read View,之后都用的這個;讀已提交每次執行前都會生成Read View

05一致性

一致性是事務追求的最終目標,前問所訴的原子性、持久性和隔離性,其實都是為了保證數據庫狀態的一致性。

當然,上文都是數據庫層面的保障,一致性的實現也需要應用層面進行保障。也就是你的業務,比如購買操作只扣除用戶的余額,不減庫存,肯定無法保證狀態的一致。

你把周圍的人看作魔鬼,你就生活在地獄;你把周圍的人看作天使,你就生活在天堂。

本文轉載自微信公眾號「小龍coding」,可以通過以下二維碼關注。轉載本文請聯系小龍coding公眾號。

 

 

責任編輯:武曉燕 來源: 小龍coding
相關推薦

2024-12-30 13:58:14

2024-02-04 10:08:34

2024-12-25 15:44:15

2023-11-27 08:32:02

元素HashMap

2021-09-17 12:50:10

MySQL數據庫ACID

2019-11-21 08:40:44

面試官優化性能

2024-10-15 10:00:06

2025-02-26 12:19:52

2021-11-05 10:07:13

Redis哈希表存儲

2021-01-20 07:16:07

冪等性接口token

2024-02-20 14:10:55

系統緩存冗余

2024-09-11 22:51:19

線程通訊Object

2023-11-20 10:09:59

2015-08-13 10:29:12

面試面試官

2023-11-29 08:00:53

JavaTreeMap底層

2024-05-11 15:11:44

系統軟件部署

2025-04-14 11:41:12

RocketMQ長輪詢配置

2024-04-09 10:40:04

2024-01-19 14:03:59

Redis緩存系統Spring

2024-01-26 13:16:00

RabbitMQ延遲隊列docker
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一区二区精品在线观看 | 二区欧美| 成人永久免费视频 | 欧美综合精品 | 激情六月丁香 | 夜夜爽99久久国产综合精品女不卡 | 天天射网站 | 国产精品久久欧美久久一区 | 在线看无码的免费网站 | 久草网址 | 欧美一区二区三区 | www.国产精品 | 久久久精彩视频 | 精品国产一区二区三区四区在线 | 国产一区二区精品在线观看 | 自拍偷拍一区二区三区 | 99久久国产 | 国产精品久久久久久久久久久久冷 | 成人亚洲精品久久久久软件 | 亚洲狠狠 | 日韩免费在线观看视频 | 美女福利网站 | 日本三级网站在线 | 在线免费观看黄网 | 亚洲精品久久久久久一区二区 | 亚洲一区二区久久 | 一区二区三区 在线 | 久久精品视频91 | 欧美在线视频一区二区 | 久久区二区 | 国产一区二区小视频 | 久久一二 | 玖玖操 | 日韩无| 中文字幕日韩一区二区 | 天天综合久久网 | 亚洲永久入口 | 亚洲成人精品影院 | 亚洲精品久久久一区二区三区 | 日韩在线欧美 | 午夜国产羞羞视频免费网站 |