久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL中的事務隔離是什么意思

160次閱讀
沒有評論

共計 4796 個字符,預計需要花費 12 分鐘才能閱讀完成。

本篇內(nèi)容介紹了“MySQL 中的事務隔離是什么意思”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓丸趣 TV 小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

事務就是要保證一組數(shù)據(jù)庫操作,要么全部成功,要么全部失敗。在 MySQL 中,事務支持是在引擎層實現(xiàn)的,但并不是所有的引擎都支持事務。比如 MySQL 原生的 MyISAM 引擎就不支持事務。

一、事務的特性

原子性:一個事務中的所有操作,要么全部完成,要么全部不完成,不會結(jié)束在中間某個環(huán)節(jié)。事務在執(zhí)行過程中發(fā)生錯誤,會被回滾到事務開始前的狀態(tài),就像這個事務從來沒有執(zhí)行過一樣

一致性:在事務開始之前和事務結(jié)束以后,數(shù)據(jù)庫的完整性沒有被破壞

隔離性:數(shù)據(jù)庫允許多個并發(fā)事務同時對數(shù)據(jù)進行讀寫和修改的能力,隔離性可以防止多個事務并發(fā)執(zhí)行時由于交叉執(zhí)行而導致數(shù)據(jù)的不一致

持久性:事務處理結(jié)束后,對數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會丟失

二、隔離級別

1. 當數(shù)據(jù)庫上有多個事務同時執(zhí)行的時候,就可能出現(xiàn)臟讀、不可重復讀、幻讀的問題

臟讀:B 事務讀取到了 A 事務尚未提交的數(shù)據(jù)

不可重復讀:一個事務讀取到了另一個事務中提交的 update 的數(shù)據(jù)

幻讀 / 虛讀:一個事務讀取到了另一個事務中提交的 insert 的數(shù)據(jù)

2. 事務的隔離級別包括:讀未提交、讀提交、可重復讀和串行化

讀未提交:一個事務還沒提交時,它做的變更就能被別的事務看到

讀提交:一個事務提交之后,它做的變更才會被其他事務看到(解決臟讀,Oracle 默認的隔離級別)

可重復讀:一個事務執(zhí)行過程中看到的數(shù)據(jù),總是跟這個事務在啟動時看到的數(shù)據(jù)是一致的,而且未提交變更對其他事務也是不可見的(解決臟讀和不可重復讀,MySQL 默認的隔離級別)

串行化:對于同一行記錄,寫會加寫鎖,讀會加讀鎖,當出現(xiàn)讀寫鎖沖突的時候,后訪問的事務必須等前一個事務執(zhí)行完成,才能繼續(xù)執(zhí)行(解決臟讀、不可重復讀和幻讀)

安全性依次提交,性能依次降低

3. 假設數(shù)據(jù)表 T 中只有一列,其中一行的值為 1

create table T(c int) engine=InnoDB;
insert into T(c) values(1);

下面是按照時間順序執(zhí)行兩個事務的行為:

若隔離級別是讀未提交,則 V1 是 2。這時候事務 B 雖然還沒提交,但是結(jié)果已經(jīng)被 A 看到了。V2、V3 都是 2

若隔離級別是讀提交,則 V1 是 1,V2 是 2。事務 B 的更新在提交后才能被 A 看到。V3 也是 2

若隔離級別是可重復讀,則 V1、V2 是 1,V3 是 2。之所以 V2 是 1,遵循的是事務在執(zhí)行期間看到的數(shù)據(jù)前后必須是一致的

若隔離級別是串行化,V1、V2 值是 1,V3 是 2

在實現(xiàn)上,數(shù)據(jù)庫里面會創(chuàng)建一個視圖,訪問的時候以視圖的邏輯結(jié)果為準。在可重復讀隔離級別下,這個視圖是在事務啟動時創(chuàng)建的,整個事務存在期間都用這個視圖。在讀提交隔離級別下,這個視圖是在每個 SQL 語句開始執(zhí)行的時候創(chuàng)建的。讀未提交隔離級別下直接返回記錄上的最新值,沒有視圖概念;而串行化隔離級別下直接用加鎖的方式來避免并行訪問

三、事務隔離的實現(xiàn)(以可重復讀為例)

在 MySQL 中,每條記錄在更新的時候都會同時記錄一條回滾操作。記錄上的最新值,通過回滾操作,都可以得到前一個狀態(tài)的值

假設一個值從 1 被按順序改成了 2、3、4,在回滾日志里面就會有類似下面的記錄

當前值是 4,但是在查詢這條記錄的時候,不同時刻啟動的事務會有不同的 read-view。如圖中看到的,在視圖 A、B、C 里面,這一個記錄的值分別是 1、2、4,同一條記錄在系統(tǒng)中可以存在多個版本,就是數(shù)據(jù)庫的多版本并發(fā)控制(MVCC)。對于 read-viewA,要得到 1,就必須將當前值一次執(zhí)行圖中所有的回滾操作得到

即使現(xiàn)在有另外一個事務正在將 4 改成 5,這個事務跟 read-view A、B、C 對應的事務是不會沖突的

系統(tǒng)會判斷,當沒有事務再需要用到這些回滾日志時,回滾日志會被刪除

四、事務啟動的方式

MySQL 的事務啟動方式有以下幾種:

顯示啟動事務語句,begin 或 start transaction。提交語句是 commit,回滾語句是 rollback

set autocommit=0,這個命令將這個線程的自動提交關掉。意味著如果只執(zhí)行一個 select 語句,這個事務就啟動了,而且不會自動提交事務。這個事務持續(xù)存在直到主動執(zhí)行 commit 或 rollback 語句,或者斷開連接

建議使用 set autocommit=1,通過顯示語句的方式來啟動事務

可以在 information_schema 庫中的 innodb_trx 這個表中查詢長事務,如下語句查詢持續(xù)時間超過 60s 的事務

select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started)) 60

五、事務隔離還是不隔離

下面是一個只有兩行的表的初始化語句:

mysql  CREATE TABLE `t` ( `id` int(11) NOT NULL,
 `k` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, k) values(1,1),(2,2);

事務 A、B、C 的執(zhí)行流程如下,采用可重復讀隔離級別

begin/start transaction 命令:不是一個事務的起點,在執(zhí)行到它們之后的第一個操作 InnoDB 表的語句,事務才真正啟動,一致性視圖是在執(zhí)行第一個快照讀語句時創(chuàng)建的

start transaction with consistent snapshot 命令:馬上啟動一個事務,一致性視圖是在執(zhí)行這條命令時創(chuàng)建的

按照上圖的流程執(zhí)行,事務 B 查到的 k 的值是 3,而事務 A 查到的 k 的值是 1

1、快照在 MVCC 里是怎么工作的?

在可重復讀隔離級別下,事務啟動的時候拍了個快照。這個快照是基于整個庫的,那么這個快照是如何實現(xiàn)的?

InnoDB 里面每個事務有一個唯一的事務 ID,叫做 transaction id。它在事務開始的時候向 InnoDB 的事務系統(tǒng)申請,是按申請順序嚴格遞增的

每行數(shù)據(jù)也都是有多個版本的。每次事務更新數(shù)據(jù)的時候,都會生成一個新的數(shù)據(jù)版本,并且把 transaction id 賦值給這個數(shù)據(jù)版本的事務 ID,記作 row trx_id。同時,舊的數(shù)據(jù)版本要保留,并且在新的數(shù)據(jù)版本中,能夠有信息可以直接拿到它。也就是說,數(shù)據(jù)表中的一行記錄,其實可能有多個版本,每個版本有自己的 row trx_id

下圖是一個記錄被多個事務連續(xù)更新后的狀態(tài):

語句更新生成的 undo log(回滾日志)就是上圖中的是哪個虛線箭頭,而 V1、V2、V3 并不是物理上真實存在的,而是每次需要的時候根據(jù)當前版本和 undo log 計算出來的。比如,需要 V2 的時候,就是通過 V4 依次執(zhí)行 U3、U2 算出來的

按照可重復讀的定義,一個事務啟動的時候,能夠看到所以已經(jīng)提交的事務結(jié)果。但是之后,這個事務執(zhí)行期間,其他事務的更新對它不可見。在實現(xiàn)上,InnoDB 為每個事務構(gòu)造了一個數(shù)組,用來保存這個事務啟動瞬間,當前在啟動了但還沒提交的所有事務 ID。數(shù)組里面事務 ID 的最小值記為低水位,當前系統(tǒng)里面已經(jīng)創(chuàng)建過的事務 ID 的最大值加 1 記為高水位。這個視圖數(shù)組和高水位就組成了當前事務的一致性視圖。而數(shù)據(jù)的可見性規(guī)則,就是基于數(shù)據(jù)的 row trx_id 和這個一致性視圖的對比結(jié)果得到的

這個視圖數(shù)組把所有的 row trx_id 分成了幾種不同的情況

對于當前事務的啟動瞬間來說,一個數(shù)據(jù)版本的 row trx_id,有以下幾種可能:

1)如果落在綠色部分,表示這個版本是已提交的事務或者是當前事務自己生成的,這個數(shù)據(jù)是可見的

2)如果落在紅色部分,表示這個版本是由將來啟動的事務生成的,肯定不可見

3)如果落在黃色部分,那就包括兩種情況

若 row trx_id 在數(shù)組中,表示這個版本是由還沒提交的事務生成的,不可見

若 row trx_id 不在數(shù)組中,表示這個版本是已經(jīng)提交了的事務生成的,可見

InnoDB 利用了所有數(shù)據(jù)都有多個版本的這個特性,實現(xiàn)了秒級創(chuàng)建快照的能力

2、為什么事務 A 的查詢語句返回的結(jié)果是 k =1?

假設:

1. 事務 A 開始時,系統(tǒng)里面只有一個活躍事務 ID 是 99

2. 事務 A、B、C 的版本號分別是 100、101、102

3. 三個事務開始前,(1,1)這一行數(shù)據(jù)的 row trx_id 是 90

這樣,事務 A 的是數(shù)組就是[99,100],事務 B 的視圖數(shù)組是[99,100,101],事務 C 的視圖數(shù)組是[99,100,101,102]

從上圖中可以看到,第一個有效更新是事務 C,從數(shù)據(jù)從 (1,1) 改成了(1,2)。這時候,這個數(shù)據(jù)的最新版本的 row trx_id 是 102,而 90 這個版本已經(jīng)成為了歷史版本

第二個有效更新是事務 B,把數(shù)據(jù)從 (1,2) 改成了(1,3)。這時候,這個數(shù)據(jù)的最新版本是 101,而 102 又成為了歷史版本

在事務 A 查詢的時候,其實事務 B 還沒提交,但是它生成的 (1,3) 這個版本已經(jīng)變成當前版本了。但這個版本對事務 A 必須是不可見的,否則就變成臟讀了

現(xiàn)在事務 A 要讀數(shù)據(jù)了,它的視圖數(shù)組是[99,100]。讀數(shù)據(jù)都是從當前版本讀起的。所以,事務 A 查詢語句的讀數(shù)據(jù)流程是這樣的:

找到 (1,3) 的時候,判斷出 row trx_id=101,比高水位大,處于紅色區(qū)域,不可見

接著,找到上一個歷史版本,一看 row trx_id=102,比高水位大,處于紅色區(qū)域,不可見

再往前找,終于找到了(1,1),它的 row trx_id=90,比低水位小,處于綠色區(qū)域,可見

雖然期間這一行數(shù)據(jù)被修改過,但是事務 A 不論在什么時候查詢,看到這行數(shù)據(jù)的結(jié)果都是一致的,我們稱之為一致性讀

一個數(shù)據(jù)版本,對于一個事務視圖來說,除了自己的更新總是可見以外,有三種情況:

版本未提交,不可見

版本已提交,但是是在視圖創(chuàng)建后提交的,不可見

版本已提交,而且是在視圖創(chuàng)建前提交的,可見

事務 A 的查詢語句的視圖數(shù)組是在事務 A 啟動的時候生成的,這時候:

(1,3)還沒提交,屬于情況 1,不可見

(1,2)雖然提交了,但是是在視圖數(shù)組創(chuàng)建之后提交的,屬于情況 2,不可見

(1,1)是在視圖數(shù)組創(chuàng)建之前提交的,可見

3、為什么事務 B 的查詢語句返回的結(jié)果是 k =3?

事務 B 要去更新數(shù)據(jù)的時候,就不能再在歷史版本上更新了,否則事務 C 的更新就丟失了。因此,事務 B 此時的 set k=k+ 1 是在 (1,2) 的基礎上進行的操作

更新數(shù)據(jù)都是先讀后寫的,而這個讀,只能讀當前的值,稱為當前讀。除了 update 語句外,select 語句如果加鎖,也是當前讀

假設事務 C 不是馬上提交的,而是變成了下面的事務 C’,會怎么樣?

上圖中,事務 C 更新后沒有馬上提交,在它提交前,事務 B 的更新語句先發(fā)起了。雖然事務 C 還沒提交,但是 (1,2) 這個版本也已經(jīng)生成了,并且是當前的最新版本

這時候涉及到了兩階段鎖協(xié)議,事務 C 沒提交,也就是說 (1,2) 這個版本上的寫鎖還沒釋放。而事務 B 是當前讀,必須要讀最新版本,而且必須加鎖,因此就被鎖住了,必須等到事務 C 釋放這個鎖,才能繼續(xù)它的當前讀

七、事務的可重復讀的能力是怎么實現(xiàn)的?

可重復讀的核心就是一致性讀;而事務更新數(shù)據(jù)的時候,只能用當前讀。如果當前的記錄的行鎖被其他事務占用的話,就需要進入鎖等待

而讀提交的邏輯和可重復讀的邏輯類似,它們最主要的區(qū)別是:

在可重復讀隔離級別下,只需要在事務開始的時候創(chuàng)建一致性視圖,之后事務里的其他查詢都共用這個一致性視圖

在讀提交隔離級別下,每一個語句執(zhí)行前都會重復算出一個新的視圖

“MySQL 中的事務隔離是什么意思”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注丸趣 TV 網(wǎng)站,丸趣 TV 小編將為大家輸出更多高質(zhì)量的實用文章!

正文完
 
丸趣
版權聲明:本站原創(chuàng)文章,由 丸趣 2023-08-01發(fā)表,共計4796字。
轉(zhuǎn)載說明:除特殊說明外本站除技術相關以外文章皆由網(wǎng)絡搜集發(fā)布,轉(zhuǎn)載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 潜山县| 兴文县| 赤水市| 紫阳县| 阳曲县| 长垣县| 中方县| 上蔡县| 瑞金市| 新民市| 任丘市| 运城市| 阿拉善盟| 客服| 巴东县| 晋城| 柳江县| 嵊州市| 天水市| 临高县| 阿荣旗| 中江县| 凤阳县| 蓝田县| 绍兴市| 淳化县| 正镶白旗| 当阳市| 旺苍县| 黑水县| 鄂温| 尉氏县| 西畴县| 余庆县| 安阳县| 泰州市| 镇巴县| 兴山县| 峨边| 洪雅县| 龙游县|