中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何淺析mysql事務和隔離級別底層原理

發布時間:2021-12-07 16:46:13 來源:億速云 閱讀:138 作者:柒染 欄目:開發技術

本篇文章給大家分享的是有關如何淺析mysql事務和隔離級別底層原理,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

    前言

    首先回顧一下什么是事務,事務是數據庫操作的最小工作單元,是作為單個邏輯工作單元執行的一系列操作;這些操作作為一個整體一起向系統提交,要么都執行、要么都不執行;事務是一組不可再分割的操作集合(工作邏輯單元)。

    事務的特性:

    原子性(Atomicity):原子性是指事務包含的所有操作要么全部成功,要么全部失敗回滾。一致性(Consistency):事務執行的結果必須是使數據庫從一個一致性狀態變到另一個一致性狀態。隔離性(Isolation):一個事務的執行不能其它事務干擾。即一個事務內部的操作及使用的數據對其它并發事務是隔離的,并發執行的各個事務之間不能互相干擾。持久性(Durability):指一個事務一旦提交,它對數據庫中的數據的改變就應該是永久性的。接下來的其它操作或故障不應該對其執行結果有任何影響。

    一、事務底層原理淺析

    原子性:

    實現原理:undo log

    undo log也被成為回滾日志,它是事務實現原子性和隔離性的基礎。當事務對數據庫進行修改時,InnoDB會生成對應的undo log;如果事務執行失敗或調用了rollback,導致事務需要回滾,便可以利用undo log中的信息將數據回滾到修改之前的樣子。

    undo log屬于邏輯日志,它記錄的是sql執行相關的信息。當發生回滾時,InnoDB會根據undo log的內容做與之前相反的工作:對于每個insert,回滾時會執行delete;對于每個delete,回滾時會執行insert;對于每個update,回滾時會執行一個相反的update,把數據改回去。

    undo 存放在數據庫內部的一個特殊段segment中,這個段稱為undo段。undo段位于共享表空間中。undo是邏輯日志,因此只是將數據庫邏輯的恢復到原來的樣子。undo log會產生redo log,也就是undo log的產生會伴隨著redo log的產生,因為undo log也需要持久性的保護。

    undo log執行記錄是在每次寫入數據或者修改數據之前。

    如何淺析mysql事務和隔離級別底層原理

    undo log使用原理:數據庫表每行數據會多兩列DATA_TRX_ID和DATA_ROLL_PTR(可能還有一列DB_ROW_ID,當沒有默認主鍵時會自動加上這列)。DATA_TRX_ID表示當前數據的事務版本, DATA_ROLL_PTR 則指向剛剛拷貝到

    undo log 鏈中的舊版本記錄,undo log是個鏈表,如果多個事務多次修改會繼續生成undo log并通過DATA_ROLL_PTR建立指向關系。用圖說明一下:

    如何淺析mysql事務和隔離級別底層原理

    這樣,一旦事務發生回滾,mysql便可以借助undo log實現數據還原,從而保證未提交事務的原子性。

    持久性

    實現原理:redo log

    由于InnoDB作為MySQL的存儲引擎,數據是存放在磁盤中的,為了減少磁盤IO,提高讀取性能InnoDB提供了緩存池——Buffer Pool。Buffer Pool中包含了磁盤中部分數據頁的映射,作為訪問數據庫的緩沖:當從數據庫讀取數據時,會首先從Buffer Pool中讀取,如果Buffer Pool中沒有,則從磁盤讀取后放入Buffer Pool;當向數據庫寫入數據時,會首先寫入Buffer Pool,Buffer Pool中修改的數據會定期刷新到磁盤中(這一過程稱為刷臟)。

    不過這也帶來了一個新的問題,如果MySQL宕機,而此時Buffer Pool中修改的數據還沒有刷新到磁盤,就會導致數據的丟失,事務的持久性無法保證。

    為了解決這個問題就引入了redo log,也叫重做日志。當數據修改時,除了修改Buffer Pool中的數據,還會在redo log記錄這次操作;當事務提交時,會調用fsync接口對redo log進行刷盤。如果MySQL宕機,重啟時可以讀取redo log中的數據,對數據庫進行恢復。redo log采用的是WAL(Write-ahead logging,預寫式日志),所有修改在提交前先寫入日志,保證了數據不會因MySQL宕機而丟失,從而滿足了持久性要求。redo log是針對物理頁的,并發執行,最后一次提交會覆蓋未提交的數據。本地redo log:

    如何淺析mysql事務和隔離級別底層原理

    redo log也是有緩沖區的——redo log buffer,當事務提交之后會把所有修改信息都刷新到磁盤上。用戶也可以通過控制通過變量 innodb_flush_log_at_trx_commit 的值來修改刷新策略(默認1),如設置值為2,控制成每秒刷新,這樣事務提

    交就會較快,不過可能面臨日志丟失的風險。

    redo log是在SQL語句執行之后記錄的。

    如何淺析mysql事務和隔離級別底層原理

    既然redo log也需要存儲,也涉及磁盤IO為啥還用它?

    (1)redo log 的存儲是順序存儲,而緩存同步是隨機操作。

    (2)緩存同步是以數據頁為單位的,每次傳輸的數據大小大于redo log。

    redo log是用來恢復數據的 用于保障已提交事務的持久化特性。

    隔離性:

    原理:
    (1). 寫操作對寫操作的影響:鎖機制保證隔離性
    (2). 寫操作對讀操作的影響:MVCC保證隔離性

    一致性:

    一致性比較特殊,前面的原子性、持久性和隔離性都是為一致性服務的,除此之外,一致性還依賴于數據庫自我提供的保障,如SQL語法驗證,列類型插入數據類型驗證,同時也依賴于應用層的保障,如轉賬操作,需要開發人員進行轉賬者的余額扣除和接受者的余額增加,如果應用層面出現問題,那么一致性也是無法保障的。

    二、隔離級別底層原理淺析

    在事務底層原理淺析中,關于隔離性的原理沒有過多深入,在此我們簡單介紹一下。

    首先介紹一下mysql的MVCC(MultiVersion Concurrency Control) 叫做多版本并發控制。它是依賴undo logread view實現的。undo log上文已經介紹過了,不再贅述,read view(可讀視圖),這與我們平時理解的數據庫視圖不同,它是用來判斷當前數據版本的可見性的。

    readview主要有四個屬性:

    (1). m_ids 代表生成ReadView時,當前所有活躍的事務ID,活躍的意思就是事務開啟了還沒提交;

    (2). min_trx_id 表示當前活躍的mIds中最小的事務ID;

    (3). max_trx_id 表示生成ReadView時,最大的事務ID,它不一定是mIds中最大的事務ID;

    (4).creator_trx_id表示創建該ReadView的事務ID。

    如何淺析mysql事務和隔離級別底層原理

    注意:每開啟一個事務,事務ID就自增一次,事務ID可以看做一個全局自增變量。最先開啟的事務不一定比后開啟的事務先提交,比如長連接,所以不要認為max_trx_id就是mIds中的最大值。

    read view是怎樣借助上面四個屬性,判斷事務應該讀取那個版本的數據呢?

    如果被訪問版本的 data_trx_id 小于 m_ids 中的最小值,說明生成該版本的事務在 ReadView 生成前就已經提交了,那么該版本可以被當前事務訪問。

    如果被訪問版本的 data_trx_id 屬性值與ReadView中的creator_trx_id值相同,意味著當前事務在訪問它自己修改過的記錄,所以該版本可以被當前事務訪問。

    如果被訪問版本的 data_trx_id 屬性值大于ReadView中的max_trx_id值,表明生成該版本的事務在當前事務生成ReadView后才開啟,所以該版本不可以被當前事務訪問。

    如果被訪問版本的 data_trx_id 屬性值在ReadView的min_trx_id和max_trx_id之間,那就需要判斷一下trx_id屬性值是不是在m_ids列表中,如果在,說明創建ReadView時生成該版本的事務還是活躍的,該版本不可以被訪問;如果不在,說明創建ReadView時生成該版本的事務已經被提交,該版本可以被訪問。

    當一個事務要讀取一行數據,首先用上面規則判斷數據的最新版本也就是那行記錄,如果發現可以訪問就直接讀取了,如果發現不能訪問,就通過DATA_ROLL_PTR指針找到undo log,遞歸往下去找每個版本,知道讀取到自己可以讀取的版本為止,如果讀取不到就返回空。

    所以訪問數據時,數據庫里面會創建一個視圖,訪問的時候以視圖的邏輯結果為準:

    READ UNCOMMITED (未提交讀):此隔離級別下直接返回記錄上的最新值,沒有視圖概念。因為讀不會加任何鎖,所以寫操作在讀的過程中修改數據,所以會造成臟讀。好處是可以提升并發處理性能,能做到讀寫并行。

    READ COMMITED (提交讀):此隔離級別下,這個視圖是在每個 SQL語句開始執行的時候創建的。InnoDB在 READ COMMITTED,使用排它鎖,讀取數據不加鎖而是使用了MVCC機制。或者換句話說他采用了讀寫分離機制。

    REPEATABLE READ (可重復讀):此隔離級別下,這個視圖是在事務啟動時創建的,整個事務存在期間都用這個視圖。

    SERIALIZABLE (串行化):此隔離級別下直接用加鎖的方式來避免并行訪問。

    寫到這里,你也許發現了,MySQL中借助MVCC在可重復讀隔離級別下其實也杜絕了幻讀的發生。

    三、總結

    原子性:使用 undo log (回滾日志)實現回滾,從而保障未提交事務的原子性;

    持久性:使用 redo log(重做日志)實現數據恢復,從而保障已提交事務的持久性;

    隔離性:使用鎖以及MVCC思想實現讀寫分離,讀讀并行,讀寫并行;

    一致性:通過回滾、恢復和在并發環境下的隔離做到一致性。

    以上就是如何淺析mysql事務和隔離級別底層原理,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    新沂市| 太仆寺旗| 余庆县| 黄骅市| 科技| 广东省| 抚松县| 吉林省| 南安市| 曲周县| 错那县| 泰州市| 青阳县| 平塘县| 敦化市| 宜兰市| 南岸区| 三穗县| 石屏县| 崇礼县| 分宜县| 信丰县| 化德县| 诸暨市| 沛县| 灌云县| 庆元县| 乡宁县| 房山区| 湟源县| 三台县| 同江市| 华坪县| 景德镇市| 阿拉善右旗| 固阳县| 台北县| 元谋县| 朝阳市| 龙江县| 汉寿县|