日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

本文主要探討MySQL的ACID是如何實現的,對于什么是事務,隔離個別以及鎖相關的只是不做過多的
討論。

MySQL作為當下最受歡迎的關系型數據庫,可應用于JAVA,Python,C++等諸多平臺,了解其底層實現,對于每一個軟件開發者是必不可少的過程。接下來就以Innodb為例,介紹一下MySQL的ACID在底層是如何實現的。

  • Atomicity(原子性):一系列的SQL語句組成的邏輯單元,要么全部執行,要么全部都不執行。
  • Consistency(一致性):事務執行前后,數據保持一致性。(如果把數據類比為能量,那么數據也遵循能量守恒定理)
  • Isolation(隔離性):多個事務并發執行時,多個事務之間是相互隔離,不可見的。
  • Durability(持久性):事務一旦提交,將會永久持久化到磁盤上,并不會由于操作系統宕機,MySQL服務器下線,硬件問題,或者斷電導致數據丟失。

隔離性

先簡單說說隔離性中的四種隔離級別:Read UnCommited<Read Commited<Repetable Read<Serialiable(可見性,描述的是不同事務之間能否獲取其他事務對數據庫數據所做的修改)

隔離級別

說明

Read UnCommited

讀未提交,一個事務的修改,不管是否已將提交,對于其他事務都是可見的

Read Commited

讀已提交,一個事務的修改,在提交之前,對于其他事務都是不可見的

Repetable Read

可重復讀,一個事務中對相同查詢條件數據的多次讀取,結果都是一樣的

Serializable

串行化,同步執行,效率太低,意義不大,一般不推薦使用

接下來了解一下,不同隔離級別產生的不同問題:臟讀,不可重復讀,幻讀

隔離級別

臟讀

不可重復讀

幻讀

讀未提交

讀已提交

×

可重復讀

×

×

串行化

×

×

×

那么多種隔離級別,隔離性是如何實現的,為什么不同事務之間能夠做到互不干擾?接下來就來了解一下隔離性的實現方案:鎖與MVCC


先來說說鎖的種類,看看MySQL中有哪些鎖

粒度

從粒度來區分鎖有表鎖,行鎖,頁鎖。表鎖又分為:共享鎖,排他鎖,自增鎖等。行鎖是在引擎層由各個引擎自己實現的,但是并不是所有的存儲引擎都包含行鎖,MyISAM就沒有行鎖。

行鎖的種類

在Innodb中,行鎖是通過給索引中的索引項加鎖來實現的,也就是只有通過使用索引來檢索數據才會使用到行鎖,否則使用的還是表鎖。行鎖同樣分為兩種:共享鎖和排他鎖,以及獲取鎖之前必須獲取當前表的意向共享鎖和意向排他鎖(先獲取表的意向共享鎖和意向排他鎖或者更強的鎖,然后才能給表中的每行記錄添加共享鎖和排他鎖)。

1、共享鎖:讀鎖,允許事務添加S鎖,不允許事務添加X鎖,即允許事務讀數據,不允許事務寫數據。
加鎖方式:select locak in share mode
2、排他鎖:寫鎖,不允許其他事務添加S鎖或者X鎖。加鎖方式:insert,delete,update,select  for update

行鎖是在需要的時候才加鎖的,但并不是在不需要了就立刻釋放,而是要等到事務結束時才釋放。這個就是鎖的兩階段提交。

鎖之隔離性

大致介紹了一下鎖,我們可以知道,有了鎖,當事務正在寫數據時,其事務獲取不到寫鎖就無法寫數據,一定程度上保證了事務的隔離性。但是在數據庫的使用中,我們發現在寫數據的同時,我們還能讀數據,這就說明了MySQL中并不是單單依靠鎖來實現事務的隔離性。接下來我們就倆了解一種實現隔離性的一種比較折中的方式-----MVCC


MVCC

前面說到,有了鎖,事務就不能寫數據,但是還可讀數據,而且當其他事務已經對當前行進行了修改并提交,還是可以讀到重復數據。這就是多版本的并發控制,MVCC(Multi-Version Cocurrenty Controller)

版本連

innodb中的行記錄存儲格式中還有一些額外的字段:RowId,Data_trx_id和Data_roll_ptr

Data_trx_id:最后一次修改該行記錄的事務的事務ID
Data_roll_ptr:回滾指針。指向該行記錄的前一個版本。在undo log中以鏈表的形式組織
MySQL中的ACID是如何實現的?

行記錄的信息圖

ReadView(讀視圖)

在每次查詢數據之前都會創建一個ReadView,具有以下一個屬性:

trx_ids:當前系統中活躍的事務ID的集合
low_trx_id:最晚創建的事務,當前事務鏈中最大的事務編號ID,也就是最近創建的,除本身之外最大的事務編號ID
up_trx_id:最先開始的事務,當前事務連中最小的事務編號ID,也就是當前系統中創建最早但還未提交的事務
creator_trx_ic:當前創建ReadView的事務ID編號
up_trx_id <= low_trx_id <= creator_trx_id
MySQL中的ACID是如何實現的?

ReadView數據模型

開始查詢

一條SELECT語句過來,找到一行數據:

/*注意:最后修改包括:update | delete | insert*/
1、Data_tx_id < up_trx_id:說明最后修改該行記錄的事務之前就存在,并已提交,對其他事務可見的
2、Data_trx_id > low_trx_id : 說明最后修改改行記錄的事務還沒開始,對于其他事務不可見
up_trx_id < Data_trx_id < low_trx_id:查看trx_ids是否存在Data_trx_id,如果存在,說明最后修改改行記錄的
3、事務還沒提交,其他事務不可見,如果不存在,說明該條事務已經提交,其他事務可見
MySQL中的ACID是如何實現的?

版本鏈示意圖

RR級別的幻讀

RR級別如何在RC級別上解決幻讀的:

事務A

事務B

 

事務A

事務B

開始事務

開始事務

 

開始事務

開始事務

快照讀查詢金額為500

快照讀查詢金額為500

 

快照讀查詢金額為500

 

更新金額為400

 

 

更新金額為400

 

提交事務

 

 

提交事務

 

 

select快照讀金額為500

 

 

select快照讀當前金額為400

 

select lock in share mode當前讀金額為400

 

 

select lock in share mode當前讀金額為400

1、左表與右標的唯一區別在于左表中事務B在事務A提交前做了一次快照讀,而右在事務A修改金額提交事務之前沒有進行一次快照讀。所以我們知道事務快照讀的結果非常依賴第一次事務快照讀的結果,既事務首次出現快照讀的結果非常關鍵,它決定該事務后續快照讀的結果

2、當一個事務中同時出現快照讀和當前讀時才會出現幻讀

3、MVCC并沒有徹底解決幻讀


原子性

在隔離性中MVCC依靠undo log中的版本鏈查找舊版本數據。在原子性的實現中同樣依賴于undo log。當事務對數據進行修改時innodb生成相應的undo log;如果事務執行失敗或者顯示調用rollback,便可以利用undo log將數據恢復到舊版本時的數據。undo log屬于邏輯日志,它記錄了SQL執行相關的信息。

  • 對于每個insert,回滾會執行delete
  • 對于每個delete,回滾時會執行insert
  • 對于每個update,回滾時會執行一個相反的update將數據改回去

以update為例:當執行update時,undo log中會包含被修改行的主鍵(以便知道修改了哪些行),哪些列,以及相關的值,回滾時便可根據這些信息修改成update之前的狀態。


持久性

MySQL中有很多的日志文件,持久性依賴于redo log。

一條SQL更新語句怎么運行

持久性跟寫有關,MySQL中提供了WAL即使。WAL技術全稱Write-ahead logging,他的關鍵點在刷新磁盤之前,必須要先寫redo log.

Redo log

更新一行記錄的時候,Innodb會先將這條記錄寫到redo log(并更新內存),這個時候更新就算完成了。在適當的時候將這個操作記錄更新到磁盤中,這個往往是在比較空閑的時候進行,redo log有兩個特點:

1、大小固定,循環寫
2、crash-safe

Redo log有兩個狀態,稱為兩階段提交,如果不適用兩階段提交,會導致在數據庫狀態和用他的日志恢復處理的狀態不一致。

Buffer Pool

Innodb中還提供額緩存,Buffer pool保存了磁盤中部分數據頁的映射,作為訪問數據庫的緩沖。

讀取數據時,會向讀取buffer pool中的數據,如果沒有才會讀取磁盤中的數據
向數據庫寫入數據時,會先將數據寫入buffer pool,然后定期將buffer pool中寫入的書記刷新到磁盤

Buffer pool大大提高了數據可的讀寫效率,但也帶來了問題,當Buffer pool中的數據還沒有刷新到磁盤時,數據庫宕機,那么Buffer pool中的數據就丟失了,事務的持久性無法保證。所以還需借助redo log的輔助,更新數據時除了將數據更新到Buffer pool中,還會將此次更新操作計入到redo log當中。當提交事務時,會調用fsync將redo log刷新到磁盤中。

如果MySQL宕機時,重啟服務器時會讀取redo log中的數據,恢復數據庫中的數據。redo log采用WAL技術,所有的修改都會先寫入redo log中,再更新到buffer pool中,保證MySQL不會因為宕機導致MySQL丟失了持久性。而且這樣做有兩個優點:

1、刷臟也時隨機IO,redo log是順序IO
2、刷臟頁頁頁為單位,一條數據的修改整頁都要修改,redo log只包含真正需要修改的數據,減少了無效IO

bin log與redo log的區別

1、層次:redo log是Innodb存儲引擎特有的,而binlog是server中的,叫做歸檔日志文件
2、內容:redo log是物理文件,記錄某個數據頁上做了什么修改;而bin log是物理文件,
是語句的原始邏輯,如:給ID=2的這行記錄的c字段加2
3、寫入:redo log是循環寫,寫入世紀比較多,bin log是追加,再事務提交的時候寫入

一致性

一致性是事務追求的最終目標,有前面的原子性,持久性,隔離性保證。當然一致性除了數據庫的保障還要有業務層的保障,比如購買商品,除了扣除用戶余額之外,還要減少庫存,這樣才能保證數據一致性。

總結

MySQL 都很熟, ACID 也知道是個啥,但 MySQL 的 ACID 怎么實現的?

有時候,就像你知道了有 undo log、redo log 但可能并不太清楚為什么有,當知道了設計的目的,了解起來就會更加清晰了。

分享到:
標簽:ACID
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定