1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        再有人問(wèn)你MySql 的隔離級(jí)別是什么,就把這篇文章發(fā)給他!

        共 3789字,需瀏覽 8分鐘

         ·

        2021-06-03 09:11

        △Hollis, 一個(gè)對(duì)Coding有著獨(dú)特追求的人△
        這是Hollis的第 356 篇原創(chuàng)分享
        作者 l zyz1992
        來(lái)源 l Hollis(ID:hollischuang)



        首先要明白什么是事務(wù)?

        事務(wù)是程序中一系列嚴(yán)密的操作,所有的操作必須完成,否則在所有的操作中所做的所有的更改都會(huì)被撤銷。也就是事務(wù)的原子性,一個(gè)事務(wù)中的一系列的操作要么全部成功,要么就是失敗。

        事務(wù)的結(jié)束有兩種,當(dāng)事務(wù)中所有的步驟全部成功執(zhí)行的時(shí)候,事務(wù)提交。如果其中一個(gè)步驟失敗,將會(huì)發(fā)生回滾操作,撤銷到事務(wù)開(kāi)始之前的所有的操作。


         

        事務(wù)的ACID

        事務(wù)具有四個(gè)特征

        1. 原子性 事務(wù)是數(shù)據(jù)庫(kù)的邏輯工作單位,事務(wù)中包含多個(gè)操作,要么都做完,要么都不做
        2. 隔離性(隔離性也是本文的重點(diǎn)) 事務(wù)彼此之間是不能互相干擾的,即一個(gè)事務(wù)的操作對(duì)該數(shù)據(jù)庫(kù)的其他事務(wù)操作是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)時(shí)間互補(bǔ)干擾
        3. 持久性 事務(wù)一旦提交,其變更是永久性的
        4. 一致性 事務(wù)執(zhí)行的結(jié)果必須滿足從一個(gè)狀態(tài)變到另一個(gè)狀態(tài),因此當(dāng)數(shù)據(jù)庫(kù)只包含成功事務(wù)提交的結(jié)果時(shí),就說(shuō)數(shù)據(jù)庫(kù)處于一致性的狀態(tài)。如果數(shù)據(jù)庫(kù)系統(tǒng)在運(yùn)行時(shí)發(fā)生系統(tǒng)故障,有些未完成的事務(wù)被迫中止,而有一部分修改已經(jīng)寫入數(shù)據(jù)庫(kù),這個(gè)時(shí)候數(shù)據(jù)庫(kù)就處于一種不正確的狀態(tài)。
        其實(shí)以上三個(gè)條件(原子性、隔離性、持久性)最終都是為了保持?jǐn)?shù)據(jù)庫(kù)數(shù)據(jù)的一致性服務(wù)的



        MySQL的四種隔離級(jí)別
        SQL標(biāo)準(zhǔn)定義了四種隔離級(jí)別,用來(lái)限定事務(wù)內(nèi)外的哪些改變是可見(jiàn)的,哪些是不可見(jiàn)的。
        1. 讀取未提交的數(shù)據(jù)【Read Uncommitted】 在該隔離級(jí)別,所有的事務(wù)都可以看到其他事務(wù)沒(méi)有提交的執(zhí)行結(jié)果。(實(shí)際生產(chǎn)中不可能使用這種隔離級(jí)別的)
        2. 讀取提交的內(nèi)容【Read Committed】 該隔離級(jí)別是大多數(shù)數(shù)據(jù)庫(kù)的默認(rèn)的隔離級(jí)別(不是 MySQL 默認(rèn)的)。它滿足了隔離的簡(jiǎn)單定義:一個(gè)事務(wù)只能看到其他的已經(jīng)提交的事務(wù)所做的改變。這種隔離級(jí)別也支持不可重復(fù)讀,即同一個(gè) select 可能得到不同的結(jié)果
        3. 可重讀【Repeatable Read】 這是 MySQL 默認(rèn)的隔離級(jí)別,它確保同一個(gè)事務(wù)在并發(fā)讀取數(shù)據(jù)時(shí),會(huì)看到同樣的數(shù)據(jù)行。不過(guò)理論上會(huì)導(dǎo)致另外一個(gè)問(wèn)題,【幻讀】?;米x:相同的條件查詢一些數(shù)據(jù),然后其他事務(wù)【新增】或者是【刪除】了該條件的數(shù)據(jù),然后導(dǎo)致讀取的結(jié)果不一樣多。InnoDB 存儲(chǔ)引擎通過(guò)多版本控制(MVCC)機(jī)制解決了該問(wèn)題
        4. 可串行化【serializable】 這是事務(wù)的最高隔離級(jí)別,它通過(guò)強(qiáng)制事務(wù)排序,使之不可能相互沖突,從而解決了幻讀的問(wèn)題。它在每個(gè)讀的數(shù)據(jù)行上面加上共享鎖,。但是可能會(huì)導(dǎo)致超時(shí)和鎖競(jìng)爭(zhēng)(這種隔離級(jí)別太極端,實(shí)際生產(chǎn)基本不使用)
        這四種隔離級(jí)別采用不同的鎖類型來(lái)實(shí)現(xiàn)
        1. 臟讀 讀取了前一個(gè)事務(wù)未提交的或者是回滾的數(shù)據(jù)
        2. 不可重復(fù)度 同樣的 select 查詢,但是結(jié)果不同,過(guò)程中有事務(wù)更新了原有的數(shù)據(jù)
        3. 幻讀 兩次查詢的結(jié)果數(shù)量不一樣,過(guò)程中有事務(wù)新增或者是刪除數(shù)據(jù)
        下面對(duì)不同的隔離級(jí)別產(chǎn)生的不同的問(wèn)題做一個(gè)匯總




        各個(gè)隔離級(jí)別的詳細(xì)測(cè)
        查看數(shù)據(jù)庫(kù)的隔離級(jí)別

        show variables like '%isolation%'

        設(shè)置數(shù)據(jù)庫(kù)的隔離級(jí)別

        set session transaction isolation level Read Uncommitted;

        設(shè)置數(shù)據(jù)庫(kù)的隔離級(jí)別為:Read Uncommitted

        實(shí)驗(yàn)一:Read Uncommitted

        Read Uncommitted 即:讀取未提交
        前置條件:將數(shù)據(jù)庫(kù)的隔離級(jí)別設(shè)置為read uncomitted;

        set session transaction isolation level Read Uncommitted;


        img
        img
        第一步:A開(kāi)啟事務(wù):start tracsaction;
        img
        第二步:A查詢數(shù)據(jù):select * from test;
        img
        第三步:B開(kāi)啟事務(wù):start transaction;
        img
        第四步:B查詢數(shù)據(jù):select * from test;
        img
        第五步:B更新數(shù)據(jù):update test set num =10 where id = 1;B沒(méi)有提交事務(wù)
        img
        第六步:A讀取數(shù)據(jù)----A讀取到了B未提交的數(shù)據(jù)(當(dāng)前數(shù)據(jù)庫(kù)的隔離級(jí)別是:Read Uncommitted
        img
        第七步:B回滾數(shù)據(jù):rollback;
        img
        第八步:B查詢數(shù)據(jù):select * from test;
        img
        第九步:A查詢數(shù):select * from test;
        img
        結(jié)論:事務(wù)B更新了數(shù)據(jù),但是沒(méi)有提交,事務(wù)A讀取到的是B未提交的記錄。因?yàn)樵斐膳K讀。Read Uncommitted是最低的隔離級(jí)別

        實(shí)驗(yàn)二:讀取已提交-Read Committed

        前置條件:將數(shù)據(jù)庫(kù)的隔離級(jí)別設(shè)置為:Read Committed;

        set session transaction isolaction level Read Committed;


        img
        img
        第一步:A開(kāi)始事務(wù):start transaction;
        img
        第二步:A查詢數(shù)據(jù):select *from test;
        img
        第三步:B開(kāi)啟事務(wù):start transaction;
        img
        第四步:B查詢數(shù)據(jù):select * from test;
        img
        第五步:B更新數(shù)據(jù):update test set num =10 where id=1
        查看結(jié)果:
        img
        第六步:A查詢數(shù)據(jù):select * from test;
        img
        第七步:B提交數(shù)據(jù):commit;
        img
        第八步:A查詢數(shù)據(jù):select * from test;
        img
        結(jié)論:Read Committed 讀已提交的隔離級(jí)別解決了臟讀的問(wèn)題,但是出現(xiàn)了不可重復(fù)讀的問(wèn)題,即事務(wù)A在兩次查詢的結(jié)果不一致,因?yàn)樵趦纱尾樵冎g事務(wù)B更新了一條數(shù)據(jù)。
        讀已提交的只允許讀取已經(jīng)提交的記錄 ,但是不要求可重復(fù)讀

        實(shí)驗(yàn)三:可重讀度-Repeatable Read

        前置條件:將數(shù)據(jù)庫(kù)的級(jí)別設(shè)置為可重復(fù)度
        set session transaction isolation level repeatable read;
        img
        第一步:A開(kāi)始事務(wù):start transaction;
        img
        第二步:A查詢數(shù)據(jù):select * from test;
        img
        第三步:B開(kāi)啟事務(wù):start transaction;
        img
        第四步:B查詢數(shù)據(jù):select * from test;
        img
        第五步:B更新數(shù)據(jù):update test set num=10 where id=1;
        img
        此時(shí)B并沒(méi)有提交事務(wù)
        第六步:B查詢數(shù)據(jù):select * from test;
        img
        第七步:A查詢數(shù)據(jù)
        img
        結(jié)果仍然是之前的結(jié)果(因?yàn)锽事務(wù)還沒(méi)有提交)
        第八步:B提交事務(wù):commit;
        img
        第九步:A查詢數(shù)據(jù):select * from test;此時(shí)A查詢的記錄仍然和之前一樣
        img
        第十步:B插入一條數(shù)據(jù)并提交事務(wù):inset into test(num) value(4);
        img
        第十一步:A查詢數(shù)據(jù),發(fā)現(xiàn)結(jié)果還是和之前的一樣:select * from test;
        img
        第十二步:A提交事務(wù)并查詢數(shù)據(jù)
        img
        此時(shí)發(fā)現(xiàn)A查詢的數(shù)據(jù)已經(jīng)和B查詢的結(jié)果一致了;
        結(jié)論:Repeatable Read隔離級(jí)別只允許讀取已經(jīng)提交的事務(wù)的記錄,

        實(shí)驗(yàn)四:串行化-Serializable

        前置條件:將數(shù)據(jù)庫(kù)的隔離級(jí)別設(shè)置為可串行化
        img
        第一步:A開(kāi)始事務(wù)并查詢數(shù)據(jù)
        img
        第二步:B開(kāi)啟事務(wù)并insert數(shù)據(jù),發(fā)現(xiàn)只能等待,并不能執(zhí)行下去
        img
        第三步:A提交事務(wù)
        img
        第四步:B插入數(shù)據(jù)
        img
        結(jié)論:serializable完全鎖定字段,若一個(gè)事務(wù)來(lái)操作同一份數(shù)據(jù),那么就必須等待,直到前一個(gè)事務(wù)完成并解除鎖為止。是完整的隔離級(jí)別,會(huì)鎖住對(duì)應(yīng)的數(shù)據(jù)表,因?yàn)闀?huì)導(dǎo)致效率問(wèn)題。



        本文小結(jié)
        本片文章并沒(méi)有深入的去講解原理,而是讓大家能夠從更直觀的從隔離級(jí)別的表面去了解隔離級(jí)別,因?yàn)槲野l(fā)現(xiàn)我的很多同事對(duì)此是模模糊糊,模棱兩可的,但是這個(gè)是不可以的,因?yàn)榧夹g(shù)本身是不允許存在這種歧義的,懂就是懂,才能合理運(yùn)用,如果模棱兩可,那么在實(shí)際運(yùn)用中一定也是漏洞百出,所以這也是這篇文章誕生的原因。
        我們可以先拋開(kāi)原理與底層的具體實(shí)現(xiàn),先能夠清晰且明了的搞清楚各個(gè)專業(yè)術(shù)語(yǔ)的含義,這未嘗不是一種進(jìn)步。
        最后以一句不積跬步無(wú)以至千里,不積小流無(wú)以成江河與諸君共勉!
        推薦閱讀:
        MySQL索引原理
        由淺入深逐步講解Java并發(fā)的半壁江山AQS
        ThreadLocal內(nèi)存溢出代碼演示和原因分析!

        關(guān)號(hào)互聯(lián)網(wǎng)全棧架構(gòu),價(jià)。

        瀏覽 36
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            日本黄色成熟视频 | 日韩在线二区 | 欧美日韩一二三四区 | 国产操逼视频免费 | 久久五月天AV | 操嫩穴视频 | 国产免费久久久久 | 撸一撸在线视频 | 韩国一级成a人片在线第26集 | 操逼片网址 |