日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

再有人问你MySql 的隔离级别是什么,就把这篇文章发给他!

發(fā)布時間:2025/3/16 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 再有人问你MySql 的隔离级别是什么,就把这篇文章发给他! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

△Hollis, 一個對Coding有著獨特追求的人△

這是Hollis的第?356?篇原創(chuàng)分享

作者 l zyz1992

來源 l Hollis(ID:hollischuang)

首先要明白什么是事務?

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

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

?

事務的ACID

事務具有四個特征

  • 原子性 事務是數(shù)據(jù)庫的邏輯工作單位,事務中包含多個操作,要么都做完,要么都不做

  • 隔離性(隔離性也是本文的重點) 事務彼此之間是不能互相干擾的,即一個事務的操作對該數(shù)據(jù)庫的其他事務操作是隔離的,并發(fā)執(zhí)行的各個事務時間互補干擾

  • 持久性 事務一旦提交,其變更是永久性的

  • 一致性 事務執(zhí)行的結果必須滿足從一個狀態(tài)變到另一個狀態(tài),因此當數(shù)據(jù)庫只包含成功事務提交的結果時,就說數(shù)據(jù)庫處于一致性的狀態(tài)。如果數(shù)據(jù)庫系統(tǒng)在運行時發(fā)生系統(tǒng)故障,有些未完成的事務被迫中止,而有一部分修改已經(jīng)寫入數(shù)據(jù)庫,這個時候數(shù)據(jù)庫就處于一種不正確的狀態(tài)。

  • 其實以上三個條件(原子性、隔離性、持久性)最終都是為了保持數(shù)據(jù)庫數(shù)據(jù)的一致性服務的

    MySQL的四種隔離級別

    SQL標準定義了四種隔離級別,用來限定事務內(nèi)外的哪些改變是可見的,哪些是不可見的。

  • 讀取未提交的數(shù)據(jù)【Read Uncommitted】 在該隔離級別,所有的事務都可以看到其他事務沒有提交的執(zhí)行結果。(實際生產(chǎn)中不可能使用這種隔離級別的)

  • 讀取提交的內(nèi)容【Read Committed】 該隔離級別是大多數(shù)數(shù)據(jù)庫的默認的隔離級別(不是 MySQL 默認的)。它滿足了隔離的簡單定義:一個事務只能看到其他的已經(jīng)提交的事務所做的改變。這種隔離級別也支持不可重復讀,即同一個 select 可能得到不同的結果

  • 可重讀【Repeatable Read】 這是 MySQL 默認的隔離級別,它確保同一個事務在并發(fā)讀取數(shù)據(jù)時,會看到同樣的數(shù)據(jù)行。不過理論上會導致另外一個問題,【幻讀】。幻讀:相同的條件查詢一些數(shù)據(jù),然后其他事務【新增】或者是【刪除】了該條件的數(shù)據(jù),然后導致讀取的結果不一樣多。InnoDB 存儲引擎通過多版本控制(MVCC)機制解決了該問題

  • 可串行化【serializable】 這是事務的最高隔離級別,它通過強制事務排序,使之不可能相互沖突,從而解決了幻讀的問題。它在每個讀的數(shù)據(jù)行上面加上共享鎖,。但是可能會導致超時和鎖競爭(這種隔離級別太極端,實際生產(chǎn)基本不使用)

  • 這四種隔離級別采用不同的鎖類型來實現(xiàn)

  • 臟讀 讀取了前一個事務未提交的或者是回滾的數(shù)據(jù)

  • 不可重復度 同樣的 select 查詢,但是結果不同,過程中有事務更新了原有的數(shù)據(jù)

  • 幻讀 兩次查詢的結果數(shù)量不一樣,過程中有事務新增或者是刪除數(shù)據(jù)

  • 下面對不同的隔離級別產(chǎn)生的不同的問題做一個匯總

    各個隔離級別的詳細測

    查看數(shù)據(jù)庫的隔離級別

    show?variables?like?'%isolation%'

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

    set?session?transaction?isolation?level?Read?Uncommitted;

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

    實驗一:Read Uncommitted

    Read Uncommitted 即:讀取未提交

    前置條件:將數(shù)據(jù)庫的隔離級別設置為read uncomitted;

    set?session?transaction?isolation?level?Read?Uncommitted;

    img

    img

    第一步:A開啟事務:start tracsaction;

    img

    第二步:A查詢數(shù)據(jù):select * from test;

    img

    第三步:B開啟事務:start transaction;

    img

    第四步:B查詢數(shù)據(jù):select * from test;

    img

    第五步:B更新數(shù)據(jù):update test set num =10 where id = 1;B沒有提交事務

    img

    第六步:A讀取數(shù)據(jù)----A讀取到了B未提交的數(shù)據(jù)(當前數(shù)據(jù)庫的隔離級別是:Read Uncommitted

    img

    第七步:B回滾數(shù)據(jù):rollback;

    img

    第八步:B查詢數(shù)據(jù):select * from test;

    img

    第九步:A查詢數(shù):select * from test;

    img

    結論:事務B更新了數(shù)據(jù),但是沒有提交,事務A讀取到的是B未提交的記錄。因為造成臟讀。Read Uncommitted是最低的隔離級別

    實驗二:讀取已提交-Read Committed

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

    set?session?transaction?isolaction?level?Read?Committed;

    img

    img

    第一步:A開始事務:start transaction;

    img

    第二步:A查詢數(shù)據(jù):select *from test;

    img

    第三步:B開啟事務:start transaction;

    img

    第四步:B查詢數(shù)據(jù):select * from test;

    img

    第五步:B更新數(shù)據(jù):update test set num =10 where id=1

    查看結果:

    img

    第六步:A查詢數(shù)據(jù):select * from test;

    img

    第七步:B提交數(shù)據(jù):commit;

    img

    第八步:A查詢數(shù)據(jù):select * from test;

    img

    結論:Read Committed 讀已提交的隔離級別解決了臟讀的問題,但是出現(xiàn)了不可重復讀的問題,即事務A在兩次查詢的結果不一致,因為在兩次查詢之間事務B更新了一條數(shù)據(jù)。

    讀已提交的只允許讀取已經(jīng)提交的記錄 ,但是不要求可重復讀

    實驗三:可重讀度-Repeatable Read

    前置條件:將數(shù)據(jù)庫的級別設置為可重復度

    set session transaction isolation level repeatable read;

    img

    第一步:A開始事務:start transaction;

    img

    第二步:A查詢數(shù)據(jù):select * from test;

    img

    第三步:B開啟事務:start transaction;

    img

    第四步:B查詢數(shù)據(jù):select * from test;

    img

    第五步:B更新數(shù)據(jù):update test set num=10 where id=1;

    img

    此時B并沒有提交事務

    第六步:B查詢數(shù)據(jù):select * from test;

    img

    第七步:A查詢數(shù)據(jù)

    img

    結果仍然是之前的結果(因為B事務還沒有提交)

    第八步:B提交事務:commit;

    img

    第九步:A查詢數(shù)據(jù):select * from test;此時A查詢的記錄仍然和之前一樣

    img

    第十步:B插入一條數(shù)據(jù)并提交事務:inset into test(num) value(4);

    img

    第十一步:A查詢數(shù)據(jù),發(fā)現(xiàn)結果還是和之前的一樣:select * from test;

    img

    第十二步:A提交事務并查詢數(shù)據(jù)

    img

    此時發(fā)現(xiàn)A查詢的數(shù)據(jù)已經(jīng)和B查詢的結果一致了;

    結論:Repeatable Read隔離級別只允許讀取已經(jīng)提交的事務的記錄,

    實驗四:串行化-Serializable

    前置條件:將數(shù)據(jù)庫的隔離級別設置為可串行化

    img

    第一步:A開始事務并查詢數(shù)據(jù)

    img

    第二步:B開啟事務并insert數(shù)據(jù),發(fā)現(xiàn)只能等待,并不能執(zhí)行下去

    img

    第三步:A提交事務

    img

    第四步:B插入數(shù)據(jù)

    img

    結論:serializable完全鎖定字段,若一個事務來操作同一份數(shù)據(jù),那么就必須等待,直到前一個事務完成并解除鎖為止。是完整的隔離級別,會鎖住對應的數(shù)據(jù)表,因為會導致效率問題。

    本文小結

    本片文章并沒有深入的去講解原理,而是讓大家能夠從更直觀的從隔離級別的表面去了解隔離級別,因為我發(fā)現(xiàn)我的很多同事對此是模模糊糊,模棱兩可的,但是這個是不可以的,因為技術本身是不允許存在這種歧義的,懂就是懂,才能合理運用,如果模棱兩可,那么在實際運用中一定也是漏洞百出,所以這也是這篇文章誕生的原因。

    我們可以先拋開原理與底層的具體實現(xiàn),先能夠清晰且明了的搞清楚各個專業(yè)術語的含義,這未嘗不是一種進步。

    最后以一句不積跬步無以至千里,不積小流無以成江河與諸君共勉!

    往期推薦

    密碼打馬賽克已經(jīng)不安全了!這款開源的去“馬賽克“工具一秒還原


    身家破億!86版西游記“紅孩兒”拒絕出道成學霸,已是中科院博士,名下52家公司


    帶爸媽去上海東方明珠旋轉(zhuǎn)餐廳體驗了一把

    ?

    直面Java第360期:如何使用樂觀鎖提升高并發(fā)的吞吐率并且不會超賣

    深入并發(fā)第015期:多線程代碼如何Debug?

    如果你喜歡本文,

    請長按二維碼,關注?Hollis.

    轉(zhuǎn)發(fā)至朋友圈,是對我最大的支持。

    點個?在看?

    喜歡是一種感覺

    在看是一種支持

    ↘↘↘

    總結

    以上是生活随笔為你收集整理的再有人问你MySql 的隔离级别是什么,就把这篇文章发给他!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。