最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

mysql中的隔離性原理詳解

 更新時間:2023年08月09日 08:29:59   作者:meihaoshy  
這篇文章主要介紹了mysql隔離性的原理,多版本并發(fā)控制(MVCC)是一種用來解決?讀-寫沖突?的無鎖并發(fā)控制,為事務分配單向增長的事務ID,為每個修改保存一個版本,版本與事務ID關聯,讀操作只讀該事務開始前的數據庫的快照,需要的朋友可以參考下

數據庫并發(fā)的三種場景

  • 讀-讀 :不存在任何問題,也不需要并發(fā)控制
  • 讀-寫 :有線程安全問題,可能會造成事務隔離性問題,可能遇到臟讀,幻讀,不可重復讀
  • 寫-寫 :有線程安全問題,可能會存在更新丟失問題

在這三種場景中 讀-讀幾乎沒有任何問題 所以我們不需要并發(fā)控制

寫-寫并發(fā)只需要加鎖控制即可

所以說我們今天重點討論下讀-寫并發(fā)

MVCC

基本介紹

多版本并發(fā)控制( MVCC )是一種用來解決 讀-寫沖突 的無鎖并發(fā)控制

為事務分配單向增長的事務ID,為每個修改保存一個版本,版本與事務ID關聯,讀操作只讀該事務開始前的數據庫的快照。 所以 MVCC 可以為數據庫解決以下問題

  • 在并發(fā)讀寫數據庫時,可以做到在讀操作時不用阻塞寫操作,寫操作也不用阻塞讀操作,提高了數據庫并發(fā)讀寫的性能
  • 同時還可以解決臟讀,幻讀,不可重復讀等事務隔離問題,但不能解決更新丟失問題

在我們理解MVCC之前 我們需要知道三個前提知識

  • 3個記錄隱藏字段
  • undo 日志
  • Read View

我們下面就分別先介紹下這三個隱藏字段

三個前提知識介紹

三個隱藏字段

  • DB_TRX_ID :6 byte,最近修改( 修改/插入 )事務ID,記錄創(chuàng)建這條記錄/最后一次修改該記錄的事務ID
  • DB_ROLL_PTR : 7 byte,回滾指針,指向這條記錄的上一個版本(簡單理解成,指向歷史版本就行,這些數據一般在 undo log 中)
  • DB_ROW_ID : 6 byte,隱含的自增ID(隱藏主鍵),如果數據表沒有主鍵, InnoDB 會自動以DB_ROW_ID 產生一個聚簇索引
  • 實際還有一個刪除flag隱藏字段, 既記錄被更新或刪除并不代表真的刪除,而是刪除flag變了

假設我們現在創(chuàng)建并且插入了一條數據 代碼和顯示如下

mysql> create table if not exists student(
name varchar(11) not null,
age int not null
);
mysql> insert into student (name, age) values ('張三', 28);
Query OK, 1 row affected (0.05 sec)
mysql> select * from student;
+--------+-----+
| name | age |
+--------+-----+
| 張三 | 28 |
+--------+-----+
1 row in set (0.00 sec)

實際上在Linux隱藏字段的效果就是

在這里插入圖片描述

對于上圖做出一定解釋

  • 假設插入的事務ID是9 那么TRX_ID字段實際上就是9
  • 因為這是我們插入的第一個數據 所以說隱式主鍵就是1
  • 因為這是第一個數據 沒有更前面的數據了 所以說回滾指針指向的就是空
  • 其實還有其他的隱藏字段 比如說flag等 上面沒有標識出

undo log日志

mySQL 將來是以服務進程的方式,在內存中運行。我們之前所講的所有機制:索引,事務,隔離性,日志等,都是在內存中完成的,即在 MySQL 內部的相關緩沖區(qū)中,保存相關數據,完成各種判斷操作。然后在合適的時候,將相關數據刷新到磁盤當中的。

所以,我們這里理解undo log,簡單理解成,就是 MySQL 中的一段內存緩沖區(qū),用來保存日志數據的就行。

read view 快照

關于快照讀的知識下面模擬MVCC場景的時候會講

Read View就是事務進行 快照讀 操作的時候生產的 讀視圖 (Read View),在該事務執(zhí)行的快照讀的那一刻,會生成數據庫系統(tǒng)當前的一個快照,記錄并維護系統(tǒng)當前活躍事務的ID(當每個事務開啟時,都會被分配一個ID, 這個ID是遞增的,所以最新的事務,ID值越大)

Read View 在 MySQL 源碼中,就是一個類,本質是用來進行可見性判斷的。 即當我們某個事務執(zhí)行快照讀的時候,對該記錄創(chuàng)建一個 Read View 讀視圖,把它比作條件,用來判斷當前事務能夠看到哪個版本的數據,既可能是當前最新的數據,也有可能是該行記錄的 undo log 里面的某個版本的數據。

下面是 ReadView 結構,但為了減少同學們負擔,我們簡化一下

class ReadView {
	// 省略...
private:
	/** 高水位:大于等于這個ID的事務均不可見*/
	trx_id_t m_low_limit_id;
	/** 低水位:小于這個ID的事務均可見 */
	trx_id_t m_up_limit_id;
	/** 創(chuàng)建該 Read View 的事務ID*/
	trx_id_t m_creator_trx_id;
	/** 創(chuàng)建視圖時的活躍事務id列表*/
	ids_t m_ids;
	/** 配合purge,標識該視圖不需要小于m_low_limit_no的UNDO LOG,
	* 如果其他視圖也不需要,則可以刪除小于m_low_limit_no的UNDO LOG*/
	trx_id_t m_low_limit_no;
	/** 標記視圖是否被關閉*/
	bool m_closed;
	// 省略...
};
m_ids; //一張列表,用來維護Read View生成時刻,系統(tǒng)正活躍的事務ID
up_limit_id; //記錄m_ids列表中事務ID最小的ID
low_limit_id; //ReadView生成時刻系統(tǒng)尚未分配的下一個事務ID,也就是目前已出現過的事務ID的最大值+1
creator_trx_id //創(chuàng)建該ReadView的事務ID

我們在實際讀取數據版本鏈的時候,是能讀取到每一個版本對應的事務ID的,即:當前記錄的DB_TRX_ID 。

那么,我們現在手里面有的東西就有,當前快照讀的 ReadView 和 版本鏈中的某一個記錄的DB_TRX_ID 。

那么 現在我們的問題就是 當前快照讀,應不應該讀到當前版本記錄。一張圖,解決所有問題!

在這里插入圖片描述

如果查到不應該看到當前版本,接下來就是遍歷下一個版本,直到符合條件,即可以看到。上面的readview 是當你進行select的時候,會自動形成。

看到這里有的同學可能會產生這樣一個疑問 如何遍歷下個版本呢?

我們之前說過 undo log其實就是一個緩沖區(qū) 并且里面有著回滾指針連接著的各種數據 (實際上就是單鏈表連接的各種數據)

再次總結下

  • 我們第一次開啟事務的時候會生成一個read view的結構體
  • 該結構體中會記錄活躍的最小事務id和比最大事務id還要大一的事務id
  • 當我們第一次select讀的時候會形成一個快照
  • 如果說當前版本的TRX_ID小于最小的id 那么我們就可以見到
  • 如果當前版本的TRX_ID大于等于最大ID我們就不能見到
  • 如果說在最小和最大區(qū)間里面 并且該TRX_ID不是活躍ID(已提交) 則我們可以看到
  • 如果說在最小和最大區(qū)間里面 并且TRX_ID還是活躍ID(未提交) 則我們不能看到

轉化成現實中的例子

現在的我們能夠看到我們出生之前所有人寫的作品 但是我們不能看到還未出生的人寫的作品

如果說寫書的人跟我們同一個時代 我們就要判斷這本書有沒有發(fā)表 (是否提交) 如果提交了我們就能看見 如果沒有提交 我們就不能看見

模擬MVCC場景

MVCC場景中有增刪改查 下面我們分別進行討論

我們插入的時候只需要形成一條新的undo log版本鏈 將回滾指針指向前面的數據 如果需要回滾直接通過回滾指針找到需要覆蓋的數據進行覆蓋即可

我們前面說過了 mysql中還有一個隱藏的falg字段 因此 如果需要刪除的話 只需要將flag標志位設置即可

這是最麻煩的一個環(huán)節(jié) 我們使用一個例子來說明MVCC中的改

現在一個表中有如下的記錄

在這里插入圖片描述

現在有一個事務ID為10的事務 要修改表中的name張三為李四

  • 因為要修改 所以我們肯定要先給記錄上鎖
  • 修改之前 我們要將改之前的數據拷貝一份要undo log當中 假設地址為0x11223344
  • 之后我們修改原始數據中name為李四 并且將回滾指向0x11223344這個地址
  • 事務10commit提交 釋放鎖

過程圖如下

在這里插入圖片描述

如果還有事務要修改新的數據就參考上面的步驟即可

于是乎我們就形成了一條基于鏈表記錄的歷史版本鏈 undo log里面的一個個歷史版本就稱為快照

現在我們明白了

  • 所謂的回滾其實就是拿歷史版本鏈中的某條數據覆蓋當前數據

首先我們要理解兩個概念 當前讀和快照讀

  • 當前讀:讀取最新的記錄,就是當前讀。增刪改,都叫做當前讀,select也有可能當前讀,比如select lock in share mode(共享鎖), select for update
  • 快照讀:讀取歷史版本??煺兆x不會被加鎖。

多個事務同時增刪改的時候是當前讀 需要加鎖 在串行化的隔離級別下 select也是當前讀 需要加鎖

如果select是快照讀 那么和增刪改的當前讀不沖突 所以說并行效率高 事務的隔離級別決定了select是當期讀還是快照讀 具體的判斷方法可以參考前面read view部分的知識

RR和RC的區(qū)別

RR級別測試

演示一 兩邊開啟事務 右邊先進行快照讀 左邊插入數據之后commit 右邊再進行快照讀和當前讀

在這里插入圖片描述

在這里插入圖片描述

我們可以發(fā)現的是 當右邊使用快照讀的時候不管左邊有沒有commit 讀取到的數據是一樣的

而使用當前讀的時候 我們可以發(fā)現讀取的數據就是最新的數據了 光靠這個一個試驗我們看不出來什么 接下來我們看演示二

演示二: 左右兩邊同時開啟一個事務 左邊先插入數據之后提交 右邊在左邊提交之后進行快照讀

在這里插入圖片描述

我們發(fā)現 這個時候右邊的快照讀 讀取了最新的數據

對比這兩次試驗加上之前的read view部分學習我們不難做出以下的推斷

在RR級別下 第一次select快照讀的時候會生成一個read view快照 之后的讀取就按照這個快照進行

而實際上在RC級別中 每一次的select快照都都會生成一個最新的read view快照

所以說RR和RC最本質的區(qū)別就是 RR只會生成依次read view快照 而RC快照讀幾次就會生成幾次快照

四種隔離級別的不同處理方式

讀–未提交

直接當前讀 不加鎖

串行化

當前讀 加鎖

讀 提交

在RC級別中 每次的select讀取都是快照讀 每次都會生成一個最新的read view快照

可重復讀

在RR級別中 每次select讀取都是快照讀 并且都會遵循第一次select讀取時生成的read view快照

總結

在這里插入圖片描述

到此這篇關于mysql隔離性的原理的文章就介紹到這了,更多相關mysql隔離性內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • mysql日期和時間的間隔計算實例分析

    mysql日期和時間的間隔計算實例分析

    這篇文章主要介紹了mysql日期和時間的間隔計算,結合實例形式分析了mysql日期和時間間隔計算的相關操作技巧與注意事項,需要的朋友可以參考下
    2019-12-12
  • MySQL?的ANALYZE與?OPTIMIZE命令(最佳實踐指南)

    MySQL?的ANALYZE與?OPTIMIZE命令(最佳實踐指南)

    MySQL的ANALYZE?TABLE更新統(tǒng)計信息優(yōu)化查詢性能,OPTIMIZE TABLE重組表結構回收空間,二者鎖級別與執(zhí)行時間不同,建議定期維護、備份并監(jiān)控,結合工具跟蹤表健康狀況以保持數據庫穩(wěn)定運行,本文給大家介紹MySQL的ANALYZE與OPTIMIZE命令,感興趣的朋友一起看看吧
    2025-07-07
  • mysql 5.7.23 安裝配置方法圖文教程

    mysql 5.7.23 安裝配置方法圖文教程

    這篇文章主要為大家詳細介紹了mysql 5.7.23安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • MySQL?字符串截取函數及用法詳解

    MySQL?字符串截取函數及用法詳解

    在MySQL中,字符串截取是常見的操作,主要用于從字符串中提取特定部分,MySQL?提供了多種函數來實現這一功能,包括?LEFT()、RIGHT()、SUBSTRING()、MID()、SUBSTR()?和?SUBSTRING_INDEX()?等,本文將詳細介紹這些函數的用法,并通過示例進行說明,需要的朋友可以參考下
    2025-05-05
  • mysql之觸發(fā)器使用

    mysql之觸發(fā)器使用

    這篇文章主要介紹了mysql之觸發(fā)器使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2017-09-09
  • B-Tree的性質介紹

    B-Tree的性質介紹

    今天小編就為大家分享一篇關于B-Tree的性質介紹,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • mysql數據被誤刪的恢復方案以及預防措施

    mysql數據被誤刪的恢復方案以及預防措施

    這篇文章主要介紹了幾種常見的MySQL數據恢復方法,包括使用備份、二進制日志、InnoDB表空間恢復以及第三方工具,每種方法都有其優(yōu)缺點,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-02-02
  • MySQL快速對比數據技巧

    MySQL快速對比數據技巧

    這篇文章主要介紹了MySQL快速對比數據的方法以及技巧分享,如果對此有興趣,一起跟著小編學習下吧。
    2018-02-02
  • linux mysql5.5升級至mysql5.7的步驟與踩到的坑

    linux mysql5.5升級至mysql5.7的步驟與踩到的坑

    這篇文章主要介紹了linux mysql5.5升級至mysql5.7的詳細步驟,后面腳本之家小編為大家整理了多個補充,大家可以參考一下
    2021-01-01
  • mysql表空間結構和日志的用途詳解

    mysql表空間結構和日志的用途詳解

    這篇文章主要介紹了mysql表空間結構和日志的用途,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-06-06

最新評論

达孜县| 彝良县| 周口市| 柳江县| 张家口市| 藁城市| 大埔区| 大埔区| 汉川市| 江口县| 汉沽区| 东山县| 历史| 淅川县| 白银市| 类乌齐县| 淳安县| 铜梁县| 中卫市| 闽清县| 彝良县| 开江县| 布拖县| 西藏| 永胜县| 札达县| 儋州市| 普兰县| 海口市| 丹寨县| 洛阳市| 眉山市| 镇平县| 达拉特旗| 武夷山市| 本溪市| 巧家县| 五河县| 曲阳县| 大化| 织金县|