主頁 > 資料庫 > 如何實作資料庫讀一致性

如何實作資料庫讀一致性

2022-09-28 09:08:12 資料庫

1 導讀

資料的一致性是資料準確的重要指標,那如何實作資料的一致性呢?本文從事務特性和事務級別的角度和大家一起學習如何實作資料的讀寫一致性,

2 一致性

1.資料的一致性:通常指關聯資料之間的邏輯關系是否正確和完整,

舉個例子:某系統實作讀寫分離,讀資料庫是寫資料庫的備份庫,小李在系統中之前錄入的學歷資訊是高中,經過小李努力學習,成功獲得了本科學位,小李及時把資訊變成成了本科,可是由于今天系統備份時間較長,小李變更資訊時,資料已經開始備份,公司的HR通過系統查詢小李資訊時,發現還是本科,小李的申請被駁回,這就是資料不一致問題,

2.資料庫的一致性:是指資料庫從一個一致性狀態變到另一個一致性狀態,這是事務的一致性的定義,

舉個例子:倉庫中商品A有100件,門店中商品A有10件,上午10點,倉庫發送商品A50件到門店,最后倉庫中有商品A50件,門店有商品A60件,這樣商品的總是是不變的,不能門店收到貨后,倉庫的商品A還是100件,這樣就出現資料庫不一致問題,倉庫和門店商品A的總數是110才是正確的,這就是資料庫的一致性,

3 資料庫事務

資料庫事務( transaction)是訪問并可能操作各種資料項的一個資料庫操作序列,這些操作要么全部執行,要么全部不執行,是一個不可分割的作業單位,事務由事務開始與事務結束之間執行的全部資料庫操作組成,

事務的性質:

  • 原子性(Atomicity):事務中的全部操作在資料庫中是不可分割的,要么全部完成,要么全部不執行,
  • 一致性(Consistency):幾個并行執行的事務,其執行結果必須與按某一順序 串行執行的結果相一致,
  • 隔離性(Isolation):事務的執行不受其他事務的干擾,事務執行的中間結果對其他事務必須是透明的,
  • 持久性(Durability):對于任意已提交事務,系統必須保證該事務對資料庫的改變不被丟失,即使資料庫出現故障

4 并發問題

資料庫在并發環境下會出現臟讀、重復讀和幻讀問題,

1.臟讀

事務A讀取了事務B未提交的資料,如果事務B回滾了,事務A讀取的資料就是臟的,
舉例:訂單A需要商品A20件,訂單B需要商品A10件,倉庫中有商品A庫存是20件,訂單B先查詢,發現庫存夠,進行扣減,在扣減的程序中,訂單A進行查詢,發現庫存只有10個不夠訂單數量,拋出例外,這時候訂單B提交失敗了,庫存數量又變成20了,這時候,倉庫人員去查庫存,發現數量是20,可是訂單A卻說庫存不足,這就讓人很奇怪,

2.不可重復讀

復讀指的是在一個事務內,最開始讀到的資料和事務結束前的任意時刻讀到的同一批資料出現不一致的情況,
舉例:庫房管理員查詢商品A的數量,讀取結果是20件,這是訂單A出庫,扣減了商品10件,這時管理員再去查商品A時,發現商品A的數量時10件和第一此查詢的結果不同了,

3.幻讀

事務A在執行讀取操作,需要兩次統計資料的總量,前一次查詢資料總量后,此時事務B執行了新增資料的操作并提交后,這個時候事務A讀取的資料總量和之前統計的不一樣,就像產生了幻覺一樣,平白無故的多了幾條資料,成為幻讀,
舉例:操作員查詢可生產單量10個,呼叫介面下發10個訂單,事務A增加10個訂單,操作員獲取10個訂單落庫,查詢 發現變成30個訂單,

5 事務隔離級別

Read Uncommitted(未提交讀)
一個事務可以讀取到其他事務未提交的資料,會出現臟讀,所以叫做 RU,它沒有解決任何的問題,

Read Committed(已提交讀)
一個事務只能讀取到其他事務已提交的資料,不能讀取到其他事務未提交的資料,它解決了臟讀的問題,但是會出現不可重復讀的問題,

Repeatable Read(可重復讀)
它解決了不可重復讀的問題,也就是在同一個事務里面多次讀取同樣的資料結果是一樣的,但是在這個級別下,沒有定義解決幻讀的問題,

Serializable(串行化)
在這個隔離級別里面,所有的事務都是串行執行的,也就是對資料的操作需要排隊,已經不存在事務的并發操作了,所以它解決了所有的問題,

6 解決資料讀一致性

有兩個方案可以解決讀一致性問題:基于鎖的并發操作(LBCC)和基于多版本的并發操作(MVCC)

6.1 LBCC

既然要保證前后兩次讀取資料一致,那么讀取資料的時候,鎖定我要操作的資料,不允許其他的事務修改就行了,這種方案叫做基于鎖的并發控制 Lock Based Concurrency Control(LBCC),

LBCC是通過悲觀鎖來實作并發控制的,

如果事務A對資料進行加鎖,在鎖釋放前,其他事務就不能對資料進行讀寫操作,這樣并發呼叫,改成了順序呼叫,對目前的大多數系統來說,性能完全不能滿足要求,

6.2 MVCC

要讓一個事務前后兩次讀取的資料保持一致,那么我們可以在修改資料的時候給它建立一個備份或者叫快照,后面再來讀取這個快照就行了,不管事務執行多長時間,事務內部看到的資料是不受其它事務影響的,根據事務開始的時間不同,每個事務對同一張表,同一時刻看到的資料可能是不一樣的,這種方案我們叫做多版本的并發控制 Multi Version Concurrency Control(MVCC),

MVCC是基于樂觀鎖的,

在 InnoDB 中,MVCC 是通過Undo log中的版本鏈和Read-View一致性視圖來實作的,

6.2.1 Undo log

undo log是innodb引擎的一種日志,在事務的修改記錄之前,會把該記錄的原值先保存起來再做修改,以便修改程序中出錯能夠恢復原值或者其他的事務讀取,undo log是一種用于撤銷回退的日志,在事務沒提交之前,MySQL會先記錄更新前的資料到 undo log日志檔案里面,當事務回滾時或者資料庫崩潰時,可以利用 undo log來進行回退,

對資料變更的操作不同,undo log記錄的內容也不同:

  • 新增一條記錄的時候,在創建對應undo日志時,只需要把這條記錄的主鍵值記錄下來,如果要回滾插入操作,只需要根據對應的主鍵值對記錄進行洗掉操作,
  • 洗掉一條記錄的時候,在創建對應undo日志時,需要把這條資料的所有內容都記錄下來,如果要回滾洗掉陳述句,需要把記錄的資料內容生產相應的insert陳述句,并插入到資料庫中,
  • 更新一條記錄的時候,如果沒有更新主鍵,在創建對應undo日志時,如果要回滾更新陳述句,需要把變更前的內容記錄下來,如果要回滾更新陳述句,需要根據主鍵,把記錄的資料更新回去,
  • 更新一條記錄的時候,如果有更新主鍵,在創建對應undo日志時,需要把資料的所有內容都記錄下來,如果要回滾更新陳述句,先把變更后的資料刪掉,再執行插入陳述句,把備份的資料插入到資料庫中,

undo log版本鏈

每條資料有兩個隱藏欄位,trx_id 和 roll_pointer,trx_id表示最近一次事務的id,roll_pointer表示指向你更新這個事務之前生成的undo log,
事務ID:MySQL維護一個全域變數,當需要為某個事務分配事務ID時,將該變數的值作為事務id分配給事務,然后將變數自增1,

舉例:

  • 事務A id是1 插入一條資料X,這條資料的trx_id =1 ,roll_pointer 是空(第一次插入),
  • 事務B id 是2 對這條資料進行了更新,這條資料的 trx_id =2 ,roll_pointer 指向 事務A的undo log.
  • 事務C id 是3 又對資料進行了更新操作,這條資料的trx_id =3,roll_pointer 指向 事務B的undo log.

所以當多個事務串行執行的時候,每個事務修改了一行資料,都會更新隱藏欄位trx_id 和 roll_pointer,同時多個事務的undo log會通過roll_pointer指標串聯起來,形成undo log版本鏈,

6.2.2 Read-View一致性視圖

InnoDB為每個事務維護了一個陣列,這個陣列用來保存這個事務啟動的瞬間,當前活躍的事務ID,這個陣列里有兩個水位值: 低水位(事務ID 最小值)和 高水位(事務ID 最大值 + 1);這兩個水位值就構成了當前事務的一致性視圖(Read-View)

ReadView中主要包含4個比較重要的內容:

  • m_ids:表示在生成ReadView時當前系統中活躍的讀寫事務的事務id串列,
  • min_trx_id:表示在生成ReadView時當前系統中活躍的讀寫事務中最小的事務id,也就是m_ids中的最小值,
  • max_trx_id:表示生成ReadView時系統中應該分配給下一個事務的id值,
  • creator_trx_id:表示生成該ReadView的事務的事務id,

有了這些資訊,這樣在訪問某條記錄時,只需要按照下邊的步驟判斷記錄的某個版本是否可見:

  • 如果被訪問版本的trx_id屬性值與ReadView中的creator_trx_id值相同,意味著當前事務在訪問它自己修改過的記錄,所以該版本可以被當前事務訪問,
  • 如果被訪問版本的trx_id屬性值小于ReadView中的min_trx_id值,表明生成該版本的事務在當前事務生成ReadView前已經提交,所以該版本可以被當前事務訪問,
  • 如果被訪問版本的trx_id屬性值大于ReadView中的max_trx_id值,表明生成該版本的事務在當前事務生成ReadView后才開啟,所以該版本不可以被當前事務訪問,
  • 如果被訪問版本的trx_id屬性值在ReadView的min_trx_id和max_trx_id之間,那就需要判斷一下trx_id屬性值是不是在m_ids串列中,如果在,說明創建ReadView時生成該版本的事務還是活躍的,該版本不可以被訪問;如不在,說明創建ReadView時生成該版本的事務已經被提交,該版本可以被訪問,
  • 如果某個版本的資料對當前事務不可見的話,那就順著版本鏈找到下一個版本的資料,繼續按照上邊的步驟判斷可見性,依此類推,直到版本鏈中的最后一個版本,如果最后一個版本也不可見的話,那么就意味著該條記錄對該事務完全不可見,查詢結果就不包含該記錄,
6.2.3 資料的查找方式
1.快照讀

快照讀又叫一致性讀,讀取的是歷史版本的資料,不加鎖的簡單的SELECT都屬于快照讀,即不加鎖的非阻塞讀,只能查找創建時間小于等于當前事務ID的資料或者洗掉時間大于當前事務ID的行(或未洗掉),

2.當前讀

當前讀查找的是記錄的最新資料,加鎖的SELECT、對資料進行增刪改都會進行當前讀,

6.2.4 資料舉例

如圖所示:

事務A id =1 初始化了資料
事務B id=2 進行了查詢操作(MVCC只讀取創建時間小于當前事務ID的資料或者洗掉時間大于當前事務ID的行)
事務B的結果是 (商品A:10,商品B:5)

事務C id =3 插入了商品C
事務B id=2 進行了查詢操作(MVCC只讀取創建時間小于當前事務ID的資料或者洗掉時間大于當前事務ID的行)
事務B的結果是 (商品A:10,商品B:5)

事務D id =4 洗掉商品B
事務B id=2 進行了查詢操作(MVCC只讀取創建時間小于當前事務ID的資料或者洗掉時間大于當前事務ID的行)
事務B的結果是 (商品A:10,商品B:5)

事務E id =4 修改商品A的數量
事務B id=2 進行了查詢操作(MVCC只讀取創建時間小于當前事務ID的資料或者洗掉時間大于當前事務ID的行)
事務B的結果是 (商品A:10,商品B:5)

所以當事務E提交后,當前讀獲取的資料和事務B讀取的快照資料明顯不同,

6.2.5 可解決問題

MVCC可以很好的解決讀一致問題,只能看到這個時間點之前事務提交更新的結果,而不能看到這個時間點之后事務提交的更新結果,而且降低了死鎖的概率和解決讀寫之間堵塞問題,

7 小結

LBCC和MVCC都可以解決讀一致問題,具體使用哪種方式,要結合業務場景選擇最合適的方式,MVCC和鎖也可以結合使用,沒有最好只有更好,

作者:陳昌浩

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/509726.html

標籤:其他

上一篇:記一次批量更新整型型別的列 → 探究 UPDATE 的使用細節

下一篇:?小長假要到了,來偶遇嗎?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more