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

說說一致性讀實現(xiàn)原理?

開發(fā) 前端
這個問題是我當(dāng)初在面天貓的時候,2面的面試官問我的,我之前已經(jīng)寫過mvcc的文章了,但是在看到我筆記的里的這個問題的時候我準(zhǔn)備單獨理一遍,所以就有了這個文章。

 [[353788]]

本文轉(zhuǎn)載自微信公眾號「三太子敖丙」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系三太子敖丙公眾號。

這個問題是我當(dāng)初在面天貓的時候,2面的面試官問我的,我之前已經(jīng)寫過mvcc的文章了,但是在看到我筆記的里的這個問題的時候我準(zhǔn)備單獨理一遍,所以就有了這個文章。

現(xiàn)在,主流關(guān)系型數(shù)據(jù)庫產(chǎn)品基本都實現(xiàn)了MVCC的特性,快照在MVCC中起著重要的作用,代表某一時刻數(shù)據(jù)的版本,它是實現(xiàn)一致性讀的基礎(chǔ)。在更新操作沒提交前,數(shù)據(jù)的前鏡像存儲在Undo中,利用Undo可以實現(xiàn)一致性讀,事務(wù)回滾以及異常恢復(fù)等操作,下面就聊聊MySQL事務(wù),MVCC,快照及一致讀的原理與實現(xiàn)。

MySQL中的事務(wù)

事務(wù)在RDBMS系統(tǒng)中概念基本都是一樣的,是由一組DML語句構(gòu)的工作單元,要么全部成功,要么全部失敗。

開發(fā)過程中,比較關(guān)心長事務(wù),即包含DML語句多的工作單元,事務(wù)太長會導(dǎo)致一些錯誤,例如可能由于事務(wù)數(shù)據(jù)包大小超過參數(shù)max_allowed_packet設(shè)置會導(dǎo)致程序報錯,也可能有事務(wù)中某個SQL對應(yīng)接口報錯,導(dǎo)致整個服務(wù)調(diào)用失敗,在程序設(shè)計時,應(yīng)該考慮避免長事務(wù)帶來的業(yè)務(wù)影響。

事務(wù)的ACID

image-20201114221841801

原子性是事務(wù)隔離的基礎(chǔ),隔離性和持久性是手段,最終目的是為了保持?jǐn)?shù)據(jù)的一致性。

事務(wù)的并發(fā)問題

  • 臟讀:事務(wù)A讀取了事務(wù)B未提交的數(shù)據(jù)。
  • 不可重復(fù)度:事務(wù)A多次讀取同一份數(shù)據(jù),事務(wù)B在此過程中對數(shù)據(jù)修改并提交,導(dǎo)致事務(wù)A多次讀取同一份數(shù)據(jù)的結(jié)果不一致。
  • 幻讀:事務(wù)A修改數(shù)據(jù)的同時,事務(wù)B插入了一條數(shù)據(jù),當(dāng)事務(wù)A提交后發(fā)現(xiàn)還有數(shù)據(jù)沒被修改,產(chǎn)生了幻覺。

不可重復(fù)讀側(cè)重于update操作,幻讀側(cè)重于insert或delete。解決不可重復(fù)讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表。

事務(wù)隔離級別

事務(wù)隔離是數(shù)據(jù)庫處理的基礎(chǔ)之一,隔離級別在多個事務(wù)同時進(jìn)行更改和執(zhí)行查詢時,對性能與結(jié)果的可靠性、一致性和可再現(xiàn)性之間的平衡進(jìn)行調(diào)整,InnoDB利用不同的鎖策略支持不同隔離級別。MySQL中有四種隔離級別,分別是讀未提交(READ UNCOMMITTED),讀已提交(READ COMMITTED),可重復(fù)讀(REPEATABLE READ)以及串行化(SERIALIZABLE)。

隔離級別 臟讀 不可重復(fù)讀 幻讀
READ UNCOMMITTED Yes Yes Yes
READ COMMITTED No Yes Yes
REPEATABLE READ No No Yes
SERIALIZABLE No No No

InnoDB并發(fā)控制

MVCC特性

InnonDB是一個支持行鎖的存儲引擎,為了提供更好支持的并發(fā),使用了非鎖定讀,不需要等待訪問數(shù)據(jù)上的鎖釋放,而是讀取行的一個快照,該方法是通過InnonDB MVCC特性實現(xiàn)的。

MVCC是Multi-Version Concurrency Control的簡稱,即多版本并發(fā)控制,作用是讓事務(wù)在并行發(fā)生時,在一定隔離級別前提下,可以保證在某個事務(wù)中能實現(xiàn)一致性讀,也就是該事務(wù)啟動時根據(jù)某個條件讀取到的數(shù)據(jù),直到事務(wù)結(jié)束時,再次執(zhí)行相同條件,還是讀到同一份數(shù)據(jù),不會發(fā)生變化。

MVCC的好處

讀不加鎖,讀寫不沖突。在讀多寫少的OLTP應(yīng)用中,讀寫不沖突是非常重要的,可以增加系統(tǒng)的并發(fā)性能。

在MVCC中,有兩種讀操作:快照度和當(dāng)前讀。

MVCC快照

MVCC內(nèi)部使用的一致性讀快照稱為Read View,在不同的隔離級別下,事務(wù)啟動時或者SQL語句開始時,看到的數(shù)據(jù)快照版本可能也不同,在RR、RC隔離級別下會用到 Read view。

InnoDB 里面每個事務(wù)有一個唯一的事務(wù)ID,稱為Transaction ID,它是在事務(wù)開始的時候向InnoDB的事務(wù)系統(tǒng)申請的,是按申請順序嚴(yán)格遞增的。而每行數(shù)據(jù)都有多個版本。每次事務(wù)更新數(shù)據(jù)的時候,都會生成一個新的數(shù)據(jù)版本Read View,并且把Transaction ID賦值給這個數(shù)據(jù)版本的事務(wù) ID,標(biāo)記為 row_trx_id。同時舊的數(shù)據(jù)版本要保留,并且在新的數(shù)據(jù)版本中,能夠有信息可以直接拿到它,數(shù)據(jù)表中的一行記錄,其實可能有多個數(shù)據(jù)版本 ,每個版本有自己的 row_trx_id。

InnoDB行格式

目前InnoDB默認(rèn)的行格式Dynamic,是Compat格式的增強(qiáng)版,記錄頭結(jié)構(gòu)信息占用5個字節(jié),事務(wù)ID和回滾指針分別占用6和7個字節(jié),行格式如下:

記錄頭結(jié)構(gòu)

項目 大小(bit) 描述
() 1 Unknown
() 1 Unknown
deleted_flag 1 數(shù)據(jù)行刪除標(biāo)記
min_rec_flag 1 =1如果該記錄被預(yù)先被定義為最小的記錄
n_owned 4 擁有的記錄數(shù)
heap_no 13 索引堆中該條記錄的排序位置
record_type 3 記錄類型;000:普通,001:B+樹葉子節(jié)點,010:偽列Infinum,011:Supernum,1xx:保留
next_record 16 page中下一條記錄的相對位置
Transaction ID 48 記錄中的事務(wù)ID,固定6個字節(jié)
Rollback Pointer 56 回滾指針,固定7個字節(jié)

數(shù)據(jù)行存儲

  1. #創(chuàng)建表 
  2. mysql> create table store_users (id int not null auto_increment primary key comment '主鍵id',name varchar(20) not null default '' comment '姓名'); 
  3. # 查看表狀態(tài)信息 
  4. mysql> show table status like 'store_users'\G 
  5.      Row_format: Dynamic    #默認(rèn)行格式為Dynamic 
  6.            Rows: 0          #行數(shù) 
  7.  Avg_row_length: 0          #平均行長度 
  8.     Data_length: 16384      #初始化段大小16K 
  9.      
  10. #開啟事務(wù),插入數(shù)據(jù) 
  11. mysql> begin
  12. mysql> insert into store_users values(null'aaaaa'),(null'bbbbb'); 
  13. #查看InnoDB分配的事務(wù)ID 
  14. mysql> select trx_id from information_schema.innodb_trx\G 
  15. trx_id: 8407246  #事務(wù)ID 

分析表的行頭信息以及隱藏的事務(wù)ID和回滾指針。

  1. # 用Linux下的工具h(yuǎn)exdump進(jìn)行分析 
  2. $ hexdump -C -v /usr/local/var/mysql/test/store_users.ibd > store_users.txt  
  3. $ vi store_users.txt 
  4. 00010060  02 00 1b 69 6e 66 69 6d  75 6d 00 03 00 0b 00 00  |...infimum......| 
  5. 00010070  73 75 70 72 65 6d 75 6d  05 00 00 10 00 1c 80 00  |supremum........| 
  6. 00010080  00 01 00 00 00 80 48 ce  83 00 00 01 d8 01 10 61  |......H........a|   #Record Header信息 
  7. 00010090  61 61 61 61 05 00 00 18  ff d6 80 00 00 02 00 00  |aaaa............| 
  8. 000100a0  00 80 48 ce 83 00 00 01  d8 01 1d 62 62 62 62 62  |..H........bbbbb| 
  9. 000100b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
  • 10表示變長字段長度,只有一個varchar(20)沒有超過256字節(jié),且沒有NULL值。
  • 00代表NULL標(biāo)志位,第一行沒有為NULL數(shù)據(jù)。
  • 字符a的十六進(jìn)制是61,即61 61 61 61 61代表的是字段值aaaaa
  • 00 00 00 80 48 ce 6個字節(jié)就是Transaction ID,轉(zhuǎn)換成十進(jìn)制8407246,正是上面information_schema.innodb_trx.trx_id列的值,trx_id: 8407246 。
  • 83 00 00 01 d8 01 10 7個字節(jié)是Rollback Pointer。
  • 1c 80 00 00 01 是5個字節(jié),代表Record Header信息。

隔離級別與快照

REPEATABLE READ

默認(rèn)的隔離級別,一致讀快照(Read View)是在第一次SELECT發(fā)起時建立,之后不會再發(fā)生變化。如果在同一個事務(wù)中發(fā)出多個非 鎖定SELECT語句,那么這些SELECT語句在事務(wù)提交前返回的結(jié)果是一致的。

在RR下快照Read View不是事務(wù)發(fā)起時創(chuàng)建,而是在第一個SELECT發(fā)起后創(chuàng)建。

READ COMMITTED

在READ COMMITTED讀已提交下,一致讀快照(Read View)是在每次SELECT后都會生成最新的Read View,即每次SELECT都能讀取到已COMMIT的數(shù)據(jù),就會存在不可重復(fù)讀、幻讀 現(xiàn)象。

Undo回滾段

當(dāng)開啟事務(wù)執(zhí)行更新語句(insert/update/deeldte),會經(jīng)過Server層的處理生成執(zhí)行計劃,然后調(diào)用存儲引擎層接口去讀寫數(shù)據(jù),用戶沒有觸發(fā)COMMIT或ROLLBACK之前,這些Uncommitted Data的數(shù)據(jù)稱為前鏡像(Post Image),數(shù)據(jù)存儲在Undo Log,以便用戶回滾或者M(jìn)ySQL Server Crash的恢復(fù),同時Undo Log是循環(huán)覆蓋使用。

  1. #開啟事務(wù),更新賬戶余額,不提交事務(wù)。 
  2. mysql> start transaction
  3. mysql> update account set balance = 100000 where account_no = 10001; 
  4. Rows matched: 1  Changed: 1  Warnings: 0 

上面在RR隔離級別下,開啟一個事務(wù),做update更新操作,不提交事務(wù),通過show engine innodb status\G查看undo情況。

  1. Trx id counter 8407258 
  2. Purge done for trx's n:o < 8407257 undo n:o < 0 state: running but idle 
  3. History list length 33 
  4. ...... 
  5. ---TRANSACTION 8407257, ACTIVE 154 sec 
  6. 2 lock struct(s), heap size 1136, 4 row lock(s), undo log entries 1 

Trx id counter 8407258當(dāng)前的事務(wù)ID,undo log entries 1使用了的undo entries,ACTIVE 154 sec事務(wù)持續(xù)時間,事務(wù)commit后,會調(diào)用Purge Thread把undo中的老數(shù)據(jù)清理掉。

回滾記錄

insert:反向操作是delete,undo里記錄的是delete相關(guān)信息,存儲主鍵id即可。

udpate:反向操作是update,undo里記錄的是update前的相關(guān)數(shù)據(jù)。

delete:反向操作是insert,undo里記錄的是insert values(…..)相關(guān)的記錄。

從這里可以知道,更新操作占用Undo空間的大小排序如下:

delete > update > insert

所以不建議物理delete刪除數(shù)據(jù),會產(chǎn)生大量的Undo Log,Undo快被寫滿就會發(fā)生切換,在次期間會有大量的IO操作,導(dǎo)致業(yè)務(wù)的DML都會變得很慢。

一致性讀

MySQL官方文檔對一致讀的描述:

讀操作基于某個時間點得到一份那時的數(shù)據(jù)快照,而不管同時其他事務(wù)對數(shù)據(jù)的修改。查詢過程中,若其他事務(wù)修改了數(shù)據(jù),那么就需要從 undo log中獲取舊版本的數(shù)據(jù)。這么做可以有效避免因為需要加鎖(來阻止其他事務(wù)同時對這些數(shù)據(jù)的修改)而導(dǎo)致事務(wù)并行度下降的問題。

在可重復(fù)讀(REPEATABLE READ,簡稱RR)隔離級別下,數(shù)據(jù)快照版本是在第一個讀請求發(fā)起時創(chuàng)建的。在讀已提交(READ COMMITTED,簡稱RC)隔離級別下,則是在每次讀請求時都會重新創(chuàng)建一份快照。

一致性讀是InnoDB在RR和RC下處理SELECT請求的默認(rèn)模式。由于一致性讀不會在它請求的表上加鎖,其他事務(wù)可以同時修改數(shù)據(jù)不受影響。

一行數(shù)據(jù)有多個版本,每個數(shù)據(jù)版本有自己的trx_id,每個事務(wù)或者查詢通過trx_id生成自己的一致性視圖。普通select語句是一致性讀,一致性讀會根據(jù)row trx_id和一致性視圖確定數(shù)據(jù)版本的可見性,圖中UR1,UR2就是undo,存儲在Undo Log中,每次查詢時根據(jù)當(dāng)前data page和 Undo page構(gòu)造出一致性數(shù)據(jù)頁(Consistent Read Page),通過讀取CR Page將數(shù)據(jù)返回給用戶。

總結(jié)

介紹了MySQL事務(wù),快照,MVCC以及Undo,雖然這些東西比較抽象,但是搞清楚這些東西是一件很有意義的事,能夠幫助我們更好的理解和使用MySQL,也可以把這種設(shè)計思想用在自己業(yè)務(wù)系統(tǒng)中。其中Undo在MySQL中的作用很重要,它是MVCC能夠快速創(chuàng)建快照基礎(chǔ),支撐系統(tǒng)的高并發(fā)。

好啦,以上就是本期的全部內(nèi)容了,我是敖丙,你知道的越多,你不知道的越多,我們下期見。

 

責(zé)任編輯:武曉燕 來源: 三太子敖丙
相關(guān)推薦

2017-07-25 14:38:56

數(shù)據(jù)庫一致性非鎖定讀一致性鎖定讀

2022-03-22 09:54:22

Hash算法

2011-05-04 10:19:13

MVCC

2018-08-08 15:51:44

Hash分布式算法

2020-09-10 16:50:32

mysqldump數(shù)據(jù)庫熱備

2024-04-10 10:34:34

Cache系統(tǒng)GPU

2022-12-14 08:23:30

2011-05-04 09:43:23

當(dāng)前模式讀一致性讀

2022-11-10 07:49:09

hash算法代碼

2016-12-19 18:41:09

哈希算法Java數(shù)據(jù)

2021-02-05 08:00:48

哈希算法?機(jī)器

2021-02-02 12:40:50

哈希算法數(shù)據(jù)

2021-11-12 08:38:26

一致性哈希算法數(shù)據(jù)結(jié)構(gòu)

2023-08-14 08:10:33

CPU緩存RFO

2021-05-19 21:50:46

Hash算法測試

2020-05-12 10:43:22

Redis緩存數(shù)據(jù)庫

2021-06-30 21:13:49

CPUCache數(shù)據(jù)

2022-10-19 12:22:53

并發(fā)扣款一致性

2020-09-10 10:26:44

MySQL數(shù)據(jù)庫MVCC

2021-02-04 06:30:26

Python編程語言
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 精品中文在线 | 天天拍天天操 | 成人国产精品久久 | 四虎影院新网址 | 欧美日韩国产精品 | 亚洲 欧美 另类 综合 偷拍 | 欧美性猛交一区二区三区精品 | 久久国产精品免费一区二区三区 | 精品少妇一区二区三区在线播放 | 国产一级在线视频 | 亚洲伊人久久综合 | 天天想天天干 | 在线欧美| 久草中文在线 | 欧洲一区二区视频 | 国产在线精品一区二区三区 | 999热精品| 综合天天久久 | 天堂在线www | 伊人久久综合 | 国产精品美女久久久久久免费 | 久久精点视频 | 亚洲视频 欧美视频 | 国产精品99久 | 国产视频久久久 | 美女在线观看国产 | 国产第一区二区 | 成人日韩av | 婷婷毛片| 欧洲一级视频 | 午夜视频网| 欧美日韩在线播放 | 射久久| 亚洲资源站 | 成人精品在线视频 | jav成人av免费播放 | 久久精品国产久精国产 | 欧美1—12sexvideos| 成人亚洲一区 | 亚洲乱码一区二区三区在线观看 | 香蕉大人久久国产成人av |