真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

mysql怎么保證隔離性 mysql4種隔離級別操作過程

mysql事務(wù)隔離級別

mysql事務(wù)隔離級別如下:

創(chuàng)新互聯(lián)公司成立十多年來,這條路我們正越走越好,積累了技術(shù)與客戶資源,形成了良好的口碑。為客戶提供網(wǎng)站制作、成都網(wǎng)站建設(shè)、網(wǎng)站策劃、網(wǎng)頁設(shè)計、申請域名、網(wǎng)絡(luò)營銷、VI設(shè)計、網(wǎng)站改版、漏洞修補等服務(wù)。網(wǎng)站是否美觀、功能強大、用戶體驗好、性價比高、打開快等等,這些對于網(wǎng)站建設(shè)都非常重要,創(chuàng)新互聯(lián)公司通過對建站技術(shù)性的掌握、對創(chuàng)意設(shè)計的研究為客戶提供一站式互聯(lián)網(wǎng)解決方案,攜手廣大客戶,共同發(fā)展進步。

1.讀取未提交(READ-UNCOMMITTED):最低的隔離級別,允許讀取尚未提交的數(shù)據(jù)變更,可能造成臟讀、不可重復(fù)讀、幻讀。

2.讀取已提交(READ-COMMITTED):允許讀取并發(fā)事務(wù)已經(jīng)提交的數(shù)據(jù),可以避免臟讀,但是可能造成不可重復(fù)、幻讀。

3.可重復(fù)讀(REPEATABLE-READ):對同一字段多次讀取的結(jié)果都是一致的,除非本身事務(wù)修改,可以避免臟讀和不可重復(fù)讀,但是可能造成幻讀。

4.可串行化(SERIALIZABLE):最高的隔離級別,完全服從ACID的隔離級別,所以的事務(wù)依次執(zhí)行,可以避免臟讀、不可重復(fù)讀、幻讀。

事務(wù)的特性:

1.原子性:事務(wù)最小的執(zhí)行單位,不允許分割。事務(wù)的原子性確保動作要么全部執(zhí)行,要么全部不執(zhí)行。

2.一致性:執(zhí)行事務(wù)的前后,數(shù)據(jù)保持一致。例如轉(zhuǎn)賬的業(yè)務(wù)中,無論事務(wù)是否成功,轉(zhuǎn)賬者和收款人的總額應(yīng)該是不變的。

3.隔離性:并發(fā)訪問數(shù)據(jù)庫時,一個用戶的事務(wù)不應(yīng)該被其他事務(wù)所影響,各并發(fā)事務(wù)之間數(shù)據(jù)庫是獨立的。

4.持久性:一個事務(wù)被提交后,它對數(shù)據(jù)庫中數(shù)據(jù)的改變是持久的,即使數(shù)據(jù)庫發(fā)生故障也不應(yīng)該對其有影響。

Mysql隔離級別之MVCC的ReadView的理解

比較常用的兩種分別是讀已提交、可重復(fù)讀,那么Mysql是如何保證多個事務(wù)讀取一條數(shù)據(jù)的隔離性的?

當我們讀取一條被其他事務(wù)變更的數(shù)據(jù)時,會在undo Log中產(chǎn)生一條變更前的日志.這個日志可以專門用于回滾。

我們大概來看一下這個日志的大概結(jié)構(gòu):

前面三個字段屬于變更前的,另外:

trx_id : 代表是哪個事務(wù)編號修改的。

roll_pointer : 相當于一個鏈表,往下查找就是上一次更改前的。當一條數(shù)據(jù)被更改了多次之后,由該字段構(gòu)建成一個鏈表俗稱 版本鏈 。

有了undo Log的話可以很快追溯到更改之前的數(shù)據(jù),有了這個之后,假設(shè)多個事務(wù)都在讀同一條記錄,并且還發(fā)生了修改,這個時候

多版本并發(fā)控制,指的就是在使用讀提交和可重復(fù)讀隔離級別的事務(wù),在執(zhí)行普通select操作時,訪問記錄版本鏈的過程;使不同事務(wù)的讀寫、寫讀操作并發(fā)執(zhí)行,提高系統(tǒng)性能;

基于當前活躍事務(wù)列表構(gòu)成的ReadView,當某個事務(wù)創(chuàng)建ReadView時,會將當前活躍的事務(wù)也加入其中。

我們來看一下大概結(jié)構(gòu):

readview 中四個比較重要的概念:

m_ids :表示在生成readview時,當前系統(tǒng)中 活躍的讀寫事務(wù)id列表 ;

min_trx_id :表示在生成readview時,當前系統(tǒng)中活躍的讀寫事務(wù)中最小的事務(wù)id,也就是m_ids中最小的值;

max_trx_id :表示生成readview時,系統(tǒng)中應(yīng)該分配給下一個事務(wù)的id值;

creator_trx_id :表示生成該readview的事務(wù)的事務(wù)id;

有了readview,在訪問某條記錄時,按照以下步驟判斷記錄的某個版本是否可見:

下面是對于同一條數(shù)據(jù)的多個事務(wù)讀取流程:

ReadView( 簡稱RV )一旦創(chuàng)建是不可變的,即便其中某個線程事務(wù)提交了,也不會影響當前線程創(chuàng)建的ReadView,你可以理解為一個副本快照。

總的來說判斷就三個條件:

基于上述規(guī)則,很好的解決了一致性讀的問題;當前線程創(chuàng)建完RV之后,讀到的數(shù)據(jù)都是相同的;不會讀到其他事務(wù)未提交和后提交的數(shù)據(jù)。

可重復(fù)讀的RV是以一個事務(wù)的開始和結(jié)束作為它的生命周期的

讀提交級別是能夠讀到其他事務(wù)提交的數(shù)據(jù)的,那么這個時候上面的流程是不是滿足不了呀?因為假設(shè)ABC都在一個RV之中,C提交了數(shù)據(jù),但是B看不到呀,因為條件2就滿足不了呀;

這個時候Mysql就把這個級別的RV做了調(diào)整, 每次讀取數(shù)據(jù)的時候會創(chuàng)建一個新的ReadView

當RV中的事務(wù)B提交了事務(wù)的時候,A每次會創(chuàng)建一個新的RV來查看數(shù)據(jù)版本,新的RV的m_ids肯定是不包含已經(jīng)提交的事務(wù)B的,這個時候就能夠讀到事務(wù)B的數(shù)據(jù)了。

之前一直以為可重復(fù)讀沒有解決幻讀的問題,現(xiàn)在基于這個流程另外加上命令行調(diào)試之后發(fā)現(xiàn)應(yīng)該是解決了的。

因為一旦創(chuàng)建RV的話,當前活躍事務(wù)快照已經(jīng)生成,這個時候如果新來的事務(wù)或者快照內(nèi)的事務(wù)新增了數(shù)據(jù)也不會讀到:

如有問題,歡迎留言交流。

mysql默認事務(wù)隔離級別

SQL標準中支持4種事務(wù)隔離級別,READ_UNCOMMITTED(讀未提交),READ_COMMITTED(讀已提交),REPEATABLE_READ(可重復(fù)讀),SERIALIZABLE(串行讀),MySQL innodb引擎支持全部這4種事務(wù)隔離級別。

工具/原料:

聯(lián)想Y7000P

Windows10

MySQL6.0

1、啟動命令行窗口,連接MySQL數(shù)據(jù)庫

圖示,通過MySQL提供的客戶端命令mysql連接MySQL數(shù)據(jù)庫。

2、通過系統(tǒng)變量查詢數(shù)據(jù)庫當前事務(wù)隔離級別

圖示,通過查詢數(shù)據(jù)庫提供的系統(tǒng)變量?tx_isolation?或?transaction_isolation?的值即可獲取當前的事務(wù)隔離級別。MySQL數(shù)據(jù)庫默認的事務(wù)隔離級別是REPEATABLE_READ (可重復(fù)讀)。

3、設(shè)置本次會話的事務(wù)隔離級別

圖示,通過命令set session transaction isolation level可以設(shè)置本次會話的事務(wù)隔離級別,該設(shè)置不會影響其他會話,并且設(shè)置會隨著當前會話的結(jié)束而結(jié)束。

4、設(shè)置全局會話的事務(wù)隔離級別

圖示,通過命令set global transaction isolation level可以設(shè)置全局會話的事務(wù)隔離級別,該設(shè)置不會影響當前已經(jīng)連接的會話,設(shè)置完畢后,新打開的會話,將使用新設(shè)置的事務(wù)隔離級別。

5、設(shè)置一次操作的事務(wù)隔離級別

圖示,通過命令set transaction isolation level可設(shè)置下一次事務(wù)操作的隔離級別,該設(shè)置會隨著下一次事務(wù)的提交而失效。

mysql的事務(wù)四個特性以及事務(wù)的四個隔離級別

分別是原子性、一致性、隔離性、持久性。

原子性是指事務(wù)包含的所有操作要么全部成功,要么全部失敗回滾,因此事務(wù)的操作如果成功就必須要完全應(yīng)用到數(shù)據(jù)庫,如果操作失敗則不能對數(shù)據(jù)庫有任何影響。

一致性是指事務(wù)必須使數(shù)據(jù)庫從一個一致性狀態(tài)變換到另一個一致性狀態(tài),也就是說一個事務(wù)執(zhí)行之前和執(zhí)行之后都必須處于一致性狀態(tài)。舉例來說,假設(shè)用戶A和用戶B兩者的錢加起來一共是1000,那么不管A和B之間如何轉(zhuǎn)賬、轉(zhuǎn)幾次賬,事務(wù)結(jié)束后兩個用戶的錢相加起來應(yīng)該還得是1000,這就是事務(wù)的一致性。

隔離性是當多個用戶并發(fā)訪問數(shù)據(jù)庫時,比如同時操作同一張表時,數(shù)據(jù)庫為每一個用戶開啟的事務(wù),不能被其他事務(wù)的操作所干擾,多個并發(fā)事務(wù)之間要相互隔離。關(guān)于事務(wù)的隔離性數(shù)據(jù)庫提供了多種隔離級別,稍后會介紹到。

持久性是指一個事務(wù)一旦被提交了,那么對數(shù)據(jù)庫中的數(shù)據(jù)的改變就是永久性的,即便是在數(shù)據(jù)庫系統(tǒng)遇到故障的情況下也不會丟失提交事務(wù)的操作。例如我們在使用JDBC操作數(shù)據(jù)庫時,在提交事務(wù)方法后,提示用戶事務(wù)操作完成,當我們程序執(zhí)行完成直到看到提示后,就可以認定事務(wù)已經(jīng)正確提交,即使這時候數(shù)據(jù)庫出現(xiàn)了問題,也必須要將我們的事務(wù)完全執(zhí)行完成。否則的話就會造成我們雖然看到提示事務(wù)處理完畢,但是數(shù)據(jù)庫因為故障而沒有執(zhí)行事務(wù)的重大錯誤。這是不允許的。

在數(shù)據(jù)庫操作中,在并發(fā)的情況下可能出現(xiàn)如下問題:

正是為了解決以上情況,數(shù)據(jù)庫提供了幾種隔離級別。

數(shù)據(jù)庫事務(wù)的隔離級別有4個,由低到高依次為Read uncommitted(未授權(quán)讀取、讀未提交)、Read committed(授權(quán)讀取、讀提交)、Repeatable read(可重復(fù)讀?。?、Serializable(序列化),這四個級別可以逐個解決臟讀、不可重復(fù)讀、幻象讀這幾類問題。

雖然數(shù)據(jù)庫的隔離級別可以解決大多數(shù)問題,但是靈活度較差,為此又提出了悲觀鎖和樂觀鎖的概念。

悲觀鎖,它指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當前的其他事務(wù),以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度。因此,在整個數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機制。也只有數(shù)據(jù)庫層提供的鎖機制才能真正保證數(shù)據(jù)訪問的排他性,否則,即使在本系統(tǒng)的數(shù)據(jù)訪問層中實現(xiàn)了加鎖機制,也無法保證外部系統(tǒng)不會修改數(shù)據(jù)。

商品t_items表中有一個字段status,status為1代表商品未被下單,status為2代表商品已經(jīng)被下單(此時該商品無法再次下單),那么我們對某個商品下單時必須確保該商品status為1。假設(shè)商品的id為1。

如果不采用鎖,那么操作方法如下:

但是上面這種場景在高并發(fā)訪問的情況下很可能會出現(xiàn)問題。例如當?shù)谝徊讲僮髦?,查詢出來的商品status為1。但是當我們執(zhí)行第三步Update操作的時候,有可能出現(xiàn)其他人先一步對商品下單把t_items中的status修改為2了,但是我們并不知道數(shù)據(jù)已經(jīng)被修改了,這樣就可能造成同一個商品被下單2次,使得數(shù)據(jù)不一致。所以說這種方式是不安全的。

在上面的場景中,商品信息從查詢出來到修改,中間有一個處理訂單的過程,使用悲觀鎖的原理就是,當我們在查詢出t_items信息后就把當前的數(shù)據(jù)鎖定,直到我們修改完畢后再解鎖。那么在這個過程中,因為t_items被鎖定了,就不會出現(xiàn)有第三者來對其進行修改了。需要注意的是,要使用悲觀鎖,我們必須關(guān)閉mysql數(shù)據(jù)庫的自動提交屬性,因為MySQL默認使用autocommit模式,也就是說,當你執(zhí)行一個更新操作后,MySQL會立刻將結(jié)果進行提交。我們可以使用命令設(shè)置MySQL為非autocommit模式: set autocommit=0;

設(shè)置完autocommit后,我們就可以執(zhí)行我們的正常業(yè)務(wù)了。具體如下:

上面的begin/commit為事務(wù)的開始和結(jié)束,因為在前一步我們關(guān)閉了mysql的autocommit,所以需要手動控制事務(wù)的提交。

上面的第一步我們執(zhí)行了一次查詢操作: select status from t_items where id=1 for update; 與普通查詢不一樣的是,我們使用了 select…for update 的方式,這樣就通過數(shù)據(jù)庫實現(xiàn)了悲觀鎖。此時在t_items表中,id為1的那條數(shù)據(jù)就被我們鎖定了,其它的事務(wù)必須等本次事務(wù)提交之后才能執(zhí)行。這樣我們可以保證當前的數(shù)據(jù)不會被其它事務(wù)修改。需要注意的是,在事務(wù)中,只有 SELECT ... FOR UPDATE 或 LOCK IN SHARE MODE 操作同一個數(shù)據(jù)時才會等待其它事務(wù)結(jié)束后才執(zhí)行,一般 SELECT ... 則不受此影響。拿上面的實例來說,當我執(zhí)行 select status from t_items where id=1 for update; 后。我在另外的事務(wù)中如果再次執(zhí)行 select status from t_items where id=1 for update; 則第二個事務(wù)會一直等待第一個事務(wù)的提交,此時第二個查詢處于阻塞的狀態(tài),但是如果我是在第二個事務(wù)中執(zhí)行 select status from t_items where id=1; 則能正常查詢出數(shù)據(jù),不會受第一個事務(wù)的影響。

使用 select…for update 會把數(shù)據(jù)給鎖住,不過我們需要注意一些鎖的級別,MySQL InnoDB默認Row-Level Lock,所以只有「明確」地指定主鍵或者索引,MySQL 才會執(zhí)行Row lock (只鎖住被選取的數(shù)據(jù)) ,否則MySQL 將會執(zhí)行Table Lock (將整個數(shù)據(jù)表單給鎖住)。舉例如下:

1、 select * from t_items where id=1 for update;

這條語句明確指定主鍵(id=1),并且有此數(shù)據(jù)(id=1的數(shù)據(jù)存在),則采用row lock。只鎖定當前這條數(shù)據(jù)。

2、 select * from t_items where id=3 for update;

這條語句明確指定主鍵,但是卻查無此數(shù)據(jù),此時不會產(chǎn)生lock(沒有元數(shù)據(jù),又去lock誰呢?)。

3、 select * from t_items where name='手機' for update;

這條語句沒有指定數(shù)據(jù)的主鍵,那么此時產(chǎn)生table lock,即在當前事務(wù)提交前整張數(shù)據(jù)表的所有字段將無法被查詢。

4、 select * from t_items where id0 for update; 或者 select * from t_items where id1 for update; (注:在SQL中表示不等于)

上述兩條語句的主鍵都不明確,也會產(chǎn)生table lock。

5、 select * from t_items where status=1 for update; (假設(shè)為status字段添加了索引)

這條語句明確指定了索引,并且有此數(shù)據(jù),則產(chǎn)生row lock。

6、 select * from t_items where status=3 for update; (假設(shè)為status字段添加了索引)

這條語句明確指定索引,但是根據(jù)索引查無此數(shù)據(jù),也就不會產(chǎn)生lock。

樂觀鎖( Optimistic Locking ) 相對悲觀鎖而言,樂觀鎖假設(shè)認為數(shù)據(jù)一般情況下不會造成沖突,所以只會在數(shù)據(jù)進行提交更新的時候,才會正式對數(shù)據(jù)的沖突與否進行檢測,如果發(fā)現(xiàn)沖突了,則返回用戶錯誤的信息,讓用戶決定如何去做。實現(xiàn)樂觀鎖一般來說有以下2種方式:

MySQL 是如何實現(xiàn)四大隔離級別的

SQL標準定義了4類隔離級別,包括了一些具體規(guī)則,用來限定事務(wù)內(nèi)外的哪些改變是可見的,哪些是不可見的。低級別的隔離級一般支持更高的并發(fā)處理,并擁有更低的系統(tǒng)開銷。

Read Uncommitted(讀取未提交內(nèi)容)

在該隔離級別,所有事務(wù)都可以看到其他未提交事務(wù)的執(zhí)行結(jié)果。本隔離級別很少用于實際應(yīng)用,因為它的性能也不比其他級別好多少。讀取未提交的數(shù)據(jù),也被稱之為臟讀(Dirty Read)。

Read Committed(讀取提交內(nèi)容)

這是大多數(shù)數(shù)據(jù)庫系統(tǒng)的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個事務(wù)只能看見已經(jīng)提交事務(wù)所做的改變。這種隔離級別 也支持所謂的不可重復(fù)讀(Nonrepeatable Read),因為同一事務(wù)的其他實例在該實例處理其間可能會有新的commit,所以同一select可能返回不同結(jié)果。

Repeatable Read(可重讀)

這是MySQL的默認事務(wù)隔離級別,它確保同一事務(wù)的多個實例在并發(fā)讀取數(shù)據(jù)時,會看到同樣的數(shù)據(jù)行。不過理論上,這會導(dǎo)致另一個棘手的問題:幻讀 (Phantom Read)。簡單的說,幻讀指當用戶讀取某一范圍的數(shù)據(jù)行時,另一個事務(wù)又在該范圍內(nèi)插入了新行,當用戶再讀取該范圍的數(shù)據(jù)行時,會發(fā)現(xiàn)有新的“幻影” 行。InnoDB和Falcon存儲引擎通過多版本并發(fā)控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。

Serializable(可串行化)

這是最高的隔離級別,它通過強制事務(wù)排序,使之不可能相互沖突,從而解決幻讀問題。簡言之,它是在每個讀的數(shù)據(jù)行上加上共享鎖。在這個級別,可能導(dǎo)致大量的超時現(xiàn)象和鎖競爭。

這四種隔離級別采取不同的鎖類型來實現(xiàn),若讀取的是同一個數(shù)據(jù)的話,就容易發(fā)生問題。例如:

臟讀(Drity Read):某個事務(wù)已更新一份數(shù)據(jù),另一個事務(wù)在此時讀取了同一份數(shù)據(jù),由于某些原因,前一個RollBack了操作,則后一個事務(wù)所讀取的數(shù)據(jù)就會是不正確的。

不可重復(fù)讀(Non-repeatable read):在一個事務(wù)的兩次查詢之中數(shù)據(jù)不一致,這可能是兩次查詢過程中間插入了一個事務(wù)更新的原有的數(shù)據(jù)。

幻讀(Phantom Read):在一個事務(wù)的兩次查詢中數(shù)據(jù)筆數(shù)不一致,例如有一個事務(wù)查詢了幾列(Row)數(shù)據(jù),而另一個事務(wù)卻在此時插入了新的幾列數(shù)據(jù),先前的事務(wù)在接下來的查詢中,就會發(fā)現(xiàn)有幾列數(shù)據(jù)是它先前所沒有的。

在MySQL中,實現(xiàn)了這四種隔離級別,分別有可能產(chǎn)生問題如下所示:


網(wǎng)頁題目:mysql怎么保證隔離性 mysql4種隔離級別操作過程
網(wǎng)頁網(wǎng)址:http://weahome.cn/article/dooshjs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部