偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

MySQL事務詳解

數(shù)據(jù)庫 MySQL
MySQL的InnoDB存儲引擎支持扁平事務、帶有保存點的事務、鏈事務、分布式事務。

什么是事務?

  • 事務是一個不可分割的工作單元,工作單元要么工作完成,要么什么也不做。
  • 從應用層面來說一個事務對應了一個完整的業(yè)務功能。
  • 從數(shù)據(jù)庫層面的來講事務就是由一批DML語句構成。

事務的分類

MySQL的InnoDB存儲引擎支持扁平事務、帶有保存點的事務、鏈事務、分布式事務。

  • 扁平事務(Flat Transactions)

扁平事務應用最為廣泛,實現(xiàn)最為簡單,扁平事務的所有操作都是在同一個層級,這些操作要么全部成功,要么全部回滾,不能存在部分提交或者部分回滾的的場景。

扁平事務

  • 帶保存點的扁平事務(Flat Transactions with Sacepoint)

扁平事務的限制就在于不能部分回滾或者提交,而有的場景是這么做是代價非常大的。比如我們舉個例子:

我們玩生存類游戲,如果我們意外失敗就必須從出生地開始玩,那么這會是讓人崩潰的,我們希望有一個游戲存檔,如果游戲失敗我們可以從最近的一個存檔重新加載游戲。

帶保存點的扁平事務就是,除了支持扁平事務的操作外,允許事務執(zhí)行過程中回滾到該事務較早的一個狀態(tài),而這個較早的狀態(tài)就是保存點來記錄的。

帶保存點的扁平事務

  • 鏈事務(Chained Transaction)

鏈事務是一種保存點事務的變種,兩者的最大區(qū)別是,帶保存點的事務可以回滾到較早前的任意保存點,而鏈式事務只能回滾到最近一個保存點;帶保存點的事務因為需要回滾到任意保存點,固其事務執(zhí)行期間所占用的資源是不會被釋放的,而鏈事務則在執(zhí)行完成當前節(jié)點后會釋放掉不需要的資源,并將下一個節(jié)點需要的資源隱士傳遞下去。鏈事務可以參考Flink流式計算的Checkpoint機制,兩者非常的相似。

鏈事務

  • 嵌套事務(Nested Transaction)

嵌套事務顧名思義,事務結構看上去就像一棵樹,根節(jié)點就是一個頂層事務,所有的葉子節(jié)點都是扁平事務(也就是說葉子節(jié)點才是真正干活兒的),事務的嵌套層級不受限制。子事務可以提交也可以回滾,但是其提交不會立即生效,只有在頂層事務提交之后所有子事務才會被真正的提交。

嵌套事務

  • 分布式事務(Distributed Transactions)

分布式事務是指一個在分布式環(huán)境下運行的扁平事務,在本章中主要介紹本地事務,分布式事務我會在后續(xù)章節(jié)是介紹。

事務的ACID特性

  • A(Atomicity)原子性:整個事務操作是一個完整的不可分割的整體,只有事務中的所有操作都執(zhí)行成功,事務才算執(zhí)行成功,否則就要回滾到事務執(zhí)行前的狀態(tài),即要么全部都做,要么全都不做。

例如:轉賬場景,自己賬戶扣除轉賬額度與對方賬戶收到轉賬這兩個操作必須是原子的。

  • C(Consistency)一致性:事務將數(shù)據(jù)庫從一種狀態(tài)轉變?yōu)榱硪环N狀態(tài),在事務執(zhí)行前和事務執(zhí)行后,數(shù)據(jù)庫的完整性約束沒有被破壞。

例如:用戶表的用戶ID列有unique約束,即用戶ID不可重復,如果事務執(zhí)行插入了一樣的用戶ID,那么就產(chǎn)生了不一致的狀態(tài)。

  • I(Isolation)隔離性:隔離性(又稱并發(fā)控制)非常好理解,就是兩個事務之間不能相互影響,即當前事務提交之前所作出的修改對其他事務都不可見,上一章我們講到了MySQL鎖,它就可以起到控制并發(fā)的作用。
  • D(Durability)持久性:持久性是指事務一旦提交,其結果就是永久性的,即使是服務器宕機,數(shù)據(jù)也必須能夠得到恢復,除了硬件故障,數(shù)據(jù)物理損壞,否則必須保證事務執(zhí)行結果的永久性,也就是保證高可靠性(High Reliablility)。

事務如何實現(xiàn)

事務的原子性、一致性、持久性通過redo log與undo log來完成,事務的隔離性由鎖與MVCC來完成。

Redo log(重做日志)

Redo log是用來實現(xiàn)事務的持久性,為了更好的讀寫性能,InnoDB會將數(shù)據(jù)緩存在內(nèi)存中,對磁盤數(shù)據(jù)的修改也會落后于內(nèi)存,如果進程或系統(tǒng)崩潰,則數(shù)據(jù)面臨丟失的風險,這時重做日志就起到了保證數(shù)據(jù)的一致性與持久性作用。重做日志主要記錄了以頁為單位的數(shù)據(jù)修改信息,其結構如下:

redo log 結構

  • 重做日志在Buffer中是連續(xù)寫入的,Buffer中的數(shù)據(jù)會適時地刷新到物理文件中;
  • 文件順序寫入,每個事務的重做日志追加到文件末尾;
  • 單個文件大小固定,寫滿以后會切回到文件組的下一個文件;
  • 重做日志文件組的文件個數(shù)是固定的,寫完最后一個文件則繼續(xù)回到第一個文件開始寫入;
  • 每個重做文件有固定2K的文件頭,文件頭的之后是以一個個512bytes的Block,每個Block有16bytes的頭尾信息;
  • 重做日志有一個全局的日志序列號(LSN:Log Sequence Number),單調(diào)遞增,表示事務寫入的重做日志的字節(jié)總量,也就是一個日志偏移量。

Undo log(回滾日志)

重做日志記錄了事務的行為,可以在需要的時候對頁進行“重做”,但是事務有時是需要被回滾的,當語句執(zhí)行失敗或者用戶請求回滾,就可以通過undo log將數(shù)據(jù)回滾到修改前的樣子,undo log是存儲了行記錄的變更。其主要包含兩類undo log:

兩種undo log結構

  • insert undo log:insert操作時產(chǎn)生,只對當前事務本身可見,在事務提交之后可直接刪除。
  • update undo log:delete與update操作產(chǎn)生,需要提供歷史版本,為后續(xù)章節(jié)要講到的MVCC服務,其交由purge線程統(tǒng)一刪除。
  • undo log需要通過group commit 操作將數(shù)據(jù)fsync到磁盤,以保證事務的持久性。

下面是一個事務與undo log的關系結構:

事務與undo log關系結構

事務隔離

事務在并發(fā)場景下很難保證事務的隔離性一致性,主要有以下一些事務的并發(fā)一致性問題。

事務并發(fā)問題

  • 臟讀(Dirty Read):事務A讀取了另外一個并行事務B未提交的數(shù)據(jù)。
  • 不可重復讀(Non-Repeatable Read:在解決臟讀問題之后,能夠保證讀事務讀取到的數(shù)據(jù)都是持久的數(shù)據(jù),如果事務A多次讀取同一數(shù)據(jù),正好在兩次讀取之間,另外一個并行事務B提交了這一數(shù)據(jù)的修改,這就導致事務A多次讀取到的同一數(shù)據(jù)內(nèi)容不一樣。
  • 幻讀(Phantom):與不可重復讀類似,事務A多次查詢一個范圍,另外一個并行事務B向該范圍內(nèi)插入或刪除了數(shù)據(jù)并提交,當事務A再次查詢時發(fā)現(xiàn)記錄變多或者丟失。
  • 更新丟失(Lost Updates):兩個事務A和B修改了同一數(shù)據(jù),由于未提交事務之間看不到對方的修改,因此都以一個舊的前提去更新了同一數(shù)據(jù)。
  • 寫偏差(Write Skew):與更新丟失類似,都是寫前提被改變,寫偏差則是事務A讀取某些數(shù)據(jù),作為另一些寫入的前提條件(更新丟失是針對同一數(shù)據(jù)),但這時另外一個事務B對事務A已讀取的數(shù)據(jù)做了修改并提交,從而導致事務A做了錯誤的commit操作。
  • 讀偏差(Read Skew):如事務A讀取某兩個數(shù)據(jù)求和,事務B在事務A讀取期間對已讀取數(shù)據(jù)做了增減,此時事務A求和得到的結果就會與實際的結果不一致。

針對上面的并發(fā)問題,InnoDB存儲引擎通過MVCC(當然MVCC本質上也是一種樂觀鎖)與鎖(關于鎖的介紹可以閱讀我的上一篇文章)來解決事務的隔離性一致性問題。

事務隔離級別

事務隔離級別是MySQL對ACID的實現(xiàn)程度上的分級,分為了四個等級,等級越高數(shù)據(jù)庫越安全,每種隔離級別解決了不同事務并發(fā)一致性的問題,具體如下:

  • READ UNCOMMITTED(讀未提交):這是一個最差的隔離級別,該級別下事務可以讀到其它事務未提交的數(shù)據(jù),也就是說在該事務隔離級別下會發(fā)生上述的所有并發(fā)一致性問題。
  • READ COMMITTED(讀已提交):事務只能讀取到已提交的修改,也就是說多個并發(fā)的事務之間的修改是相互不可見的,該事務隔離級別解決了臟讀問題。
  • REPEATABLE READ(可重復讀):該級別保證同一個事務中多次讀取同一數(shù)據(jù)的結果是一致的,該級別是InnoDB默認的隔離級別,該隔離級別解決了臟讀與不可重復讀問題,但是仍可能出現(xiàn)幻讀的情況(InnoDB存儲引擎在該隔離級別下使用了Next-Key Lock解決了幻讀問題)。
  • SERIALIZABLE(串行化):強制事務串行化執(zhí)行,沒有并發(fā),那么并發(fā)問題自然就不存在了,當然在該級別下的事務性能非常低。

關于事務隔離的實現(xiàn)會在后續(xù)文章詳細講解,本文不在展開。

事務的執(zhí)行過程

事務的執(zhí)行過程

  • 查詢數(shù)據(jù),若數(shù)據(jù)不存在于buffer,則從磁盤加載;
  • 數(shù)據(jù)更新前,先將當前數(shù)據(jù)記錄到undo log重,以便后續(xù)可能出現(xiàn)的回滾做準備;
  • 更新Buffer Pool中的數(shù)據(jù);
  • 將更新的數(shù)據(jù)寫入到Redo Log Buffer中;
  • 準備提交事務,調(diào)用fsync將Redo Log Buffer的數(shù)據(jù)寫入到redo log文件中,狀態(tài)記為prepared;
  • 準備提交事務,binlog寫入到磁盤中;
  • binlog寫入成功后,將redo log的狀態(tài)更新為commit;

binlog的開啟時會存在一個內(nèi)部XA的問題(binlog是在MySQL層,而redo log在存儲引擎層),這里引入了2PC(二階段提交):

  • prepare階段:redo log持久化到磁盤,同時設置狀態(tài)為prepared,binlog此時不錯任何操作。
  • commit階段:存儲引擎釋放鎖,是否回滾段,然后binlog持久化到磁盤,然后存儲引擎層提交,更改redo log的狀態(tài)為commit。
責任編輯:武曉燕 來源: 今日頭條
相關推薦

2024-12-02 08:37:04

2023-06-25 08:05:09

MySQL事務并發(fā)

2010-11-19 16:13:06

oracle事務隔離級

2020-09-21 18:44:35

MySQL

2024-11-13 19:03:14

2022-05-20 10:20:17

Spring事務MyBatis

2024-03-15 11:59:25

SQL數(shù)據(jù)庫ACID

2009-06-08 17:56:00

SpringJDBC事務

2023-03-27 10:40:09

2023-09-27 16:22:51

SpringMySQL原子性

2010-11-22 16:40:00

MySQL事務表

2011-08-12 13:33:31

Oracle數(shù)據(jù)庫自治事務

2021-07-13 07:31:26

Springboot編程事務管理

2010-06-18 10:58:28

UML模型元素

2022-07-10 20:24:48

Seata分布式事務

2010-10-11 09:25:06

定義MySQL事務

2018-12-19 16:46:38

MySQL事務隔離數(shù)據(jù)庫

2024-06-13 09:25:14

2017-08-22 17:10:45

數(shù)據(jù)庫MySQL事務模型

2020-06-17 16:56:36

數(shù)據(jù)庫MySQL跨行事務
點贊
收藏

51CTO技術棧公眾號