<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 并發問題帶來的后果 ![](http://cdn.aipin100.cn/18-5-5/47888058.jpg) > 任何程序,哪怕再短小的程序,運行過程都是一個運行時間段,稱為運行段,絕不是只運行一下的。 >[danger] 注意到A、B程序運行段有重合部分,在時間上重合就說明有并發爭奪資源的可能,即有可能出現并發問題(我們把因并發情況導致的程序未能按照預期運行或未得到預期結果的情況,稱為并發問題)。 **兩個進程同時請求一個資源、修改,總會有一個持有舊的數據,這是必然的**,遇到這樣的實際問題,就要用“解決實際問題的解決辦法”來解決?(這句話不是廢話嗎?) A、B同時讀取數據,并修改 在B修改時,A已經提前修改了,所以B修改數據時,持有的數據就變成舊的了,但是B并不知道,在他之前發生了什么,這帶來的后果根據不同的應用場景不同,比如: 我們購物時,下單的那一刻查詢到的價格為3元,那么訂單的應付的錢也就是3,但就是在那一刻,商家把價格上調了,變為4,于是就出現這樣的問題了,商家看到明明在第四秒鐘時價格被變為4了,而訂單創建時間也是第四秒鐘,為什么訂單的價格是3呢? 問題就出在,下單時,查到的價格的確為3,但是就在準備寫入訂單時價格變為4了,這一切下單的程序并不知道,也就是下單的進程持有的是舊數據,用舊數據下了訂單。 實際上,我們永遠不知道下一刻會發生什么,不可能保證此刻持有的數據是最新的,除非用鎖,我們獲取這個數據時就加上排它鎖,這樣才能保證我們此刻持有的數據是最新的,因為別人不能修改了。 這個價格問題其實不算問題,更嚴重的問題是涉及到金錢的問題: 比如一個賬戶兩個地點登錄,取錢,收錢查詢余額滿不滿足取錢,然后完成取錢,扣錢。 如果A、B同時操作,會出現都滿足取錢條件,然后都扣錢,這樣余額就會變成負數了。 所以這個問題才是真正嚴重的問題,不能允許這種情況出現,所以這個過程很重要,持有舊數據進行操作造成的后果很嚴重,所以只能使用鎖,查詢的時候就阻塞其他進程在進行查詢,這樣就不會出現兩個進程同時滿足取錢條件了。 > 并發問題其實就是一種“[線程安全](http://mp.weixin.qq.com/s/zDbcV_vJeBOnAYxK0WEJQQ)”問題。 * * * * * ### 競態資源與鎖 并發問題有很多情況,有時候防止多進程對競態資源的獲取出現問題,比如下單減庫存問題,這是由于舊數據造成的后果問題,可以使用樂觀鎖和悲觀群來解決,鎖可以利用數據庫或者文件實現,但是要區分競態資源和鎖是誰,比如,這個例子,大批量生成二維碼,為了保證二維碼是連續的,必須對生成過程加鎖,但是過程怎么鎖呢,那么我們根據一個key來鎖文件,以鎖文件來約定表示鎖過程,這樣就安全了。但要注意,如果其它程序,其它文件控制器中,不遵守這個約定(要走過程必須先獲得鎖,而同時只能有一個進程獲得鎖,其它進程再獲取鎖都會被阻塞。),不用鎖,直接走過程那就沒用了,所以處理競態資源一定要遵守約定,比如其它和庫存有關的并發業務,不管是在哪里的代碼,哪里的業務,也要使用事物鎖,必須遵守這個相同的約定,只要有一個沒有遵守,那么還是會出現并發問題。 重要的是要理解清楚哪部分是競態資源,另外怎么安全高效的實現鎖,確保競態資源面對并發時是安全的。 所說的安全是指,業務是安全的,業務邏輯是正常的,是預期的。 競態資源和鎖可以是同一個對象,比如減庫存問題可以直接鎖商品行,用數據庫的行鎖,但也不全是這樣,比如批量生成二維碼的例子。生成二維碼的過程是競態資源,過程是個抽象的。要保證的是同一時刻最多只能有一個這個過程存在,這樣才能保證業務邏輯正確。而鎖是利用文件鎖(當然還有很多方式實現鎖)。 **競態資源:被多個使用者競爭(搶奪)使用的資源。** >[danger] 有時候要保證并發安全,就需要考慮對競態資源加鎖。 **上面所說的約定即相同的數據訪問規則** > <span style="color:red;">只有將所有線程都設計成遵守相同的數據訪問規則,互斥機制才能正常工作。</span> **操作系統并不會為我們做數據訪問的串行化。** 如果允許其中的某個線程在沒有得到鎖的情況下也可以訪問共享資源,那么即使其他的線程在使用共享資源前都申請鎖,也還是會出現數據不一致的問題。(UNIX環境高級編程第三版 P-380) * * * * * **告訴我你能承受的,最壞的后果是什么?** >[danger] **只要持有舊數據進行操作的過程都是不符合預期的,都是不合法的,必然也一定會帶來問題的,只是根據帶來問題的不同,我們選擇處理方式也不同**,比如取錢,減余額操作就是很重要的,所以不能讓這種問題在這里發生,而對于如果狀態怎么怎么樣,就可以怎么怎么樣,這樣的操作要視情況和出問題所帶來的的后果而定,如果不是特別重要的業務,就不需要加鎖,如果比較重要的也還是需要加鎖,這樣邏輯才嚴謹。總之像減余額這種是級別最高的,必須加鎖,不然連錢都守不住,還能干別的? **“這樣的操作要視情況和出問題所帶來的的后果而定”,這句話什么意思呢?** 比如:如果狀態允許下載就能下載,當下載的那一刻,管理員同時更新為不可下載,由于下載操作檢測狀態使用的是“一致性非鎖定讀”那么并發時就會出現理論上的問題:檢測時是允許的,可是下一刻變成不允許的,但是檢測已經過了,這時下載程序繼續向下執行持有的就是舊數據了,那么此時就會出現還能下載的BUG,這就是后果,如果你能允許這個后果,你默許的是檢測那一刻是允許就表示是允許的,那么就可以不加鎖,如果你非要執拗與下載的那一刻是什么樣的狀態,不能容忍這樣的情況出現就需要加鎖了。 >[danger] 這要看你對那個點的理解要求是什么,不同情況對那個點的要求是不同的,下單肯定要求是下單的那一刻的,下載這個就以檢測的那一刻為準就好了,后面發生的舊數據,就不管了,我只認可檢測那一刻的數據,以它為準就好了。 減余額問題,出現的后果就不用說了,錢都保護不了,還能干什么。 可見舊數據無處不在,只要不加鎖,可以說每一步操作都會持有舊數據。具體怎么做,加不加鎖,這取決于你的程序能不能容忍出現舊數據后所帶來的后果,這樣后果你必須要預料到(提前考慮到了,并且有應對的措施,心中有數)。 所以減余額這種操作,如果你可以選擇不加鎖,能接受它所帶來的的后果的話,那我就不說什么了,土豪,我們做朋友吧。 > 還有一種問題是“更新丟失”,但是這個嚴格來說不是并發問題,不可能把用戶編輯文檔的整個時間/過程都鎖上吧,但其實有時候,還真是這樣做的。一個資源只允許一個客戶端打開,比如看云就是的,一個文檔打開編輯頁面,另一個窗口再打開編輯,就會提示“賬號已在其它地方登陸”,這樣就保證了同時只能讓一個客戶端進入編輯頁面,這樣就不會出現更新丟失的問題了。 * * * * * **持有舊數據的情況隨處隨時都在發生**,根據持有舊數據后要做的操作是否有危險就可以確定 持有舊數據進行操作所帶來后果是不是會讓程序變得和預期的執行不一樣,也就是產生BUG,**其實很多時候的持有就數據操作并不危險,所帶來后果并沒有任何問題,并不會讓影響程序邏輯**,比如:為文章添加一個標簽,先要判斷標簽是否存在,我沒有用鎖,但是如果你突然刪除了標簽,這就造成我提交后,文章有一個空的標簽,這就是后果,可是這個后果不會帶來什么影響啊,文章標簽顯示時會做處理的。而如果我們強行的使用鎖,那可想而知,這樣的地方很多,幾乎每一個這樣的地方都用鎖,可以想象這樣會犧牲掉很多性能的,所以需要在數據強一致性和性能之間找一個平衡點,但是不管怎么樣,安全是第一的,而這個問題中顯然不會出現安全問題,不是轉賬的操作,也不是很重要的操作,我們能接受這個后果,不認為它會對我們的程序基本結構和邏輯產生影響,所以我們當然更加傾向于性能了。總之安全第一,不管什么時候,分析完各種情況下所出現的后果,你就知道該怎么做了。 * * * * * **什么是舊數據** ~~~ 例子1: A … B A對B所說數據是1 B好的 ####### 例子2: A 數據是1哦 …c 小c來了,嘿嘿,沒人發現我來了吧,我現在把數據改為2了 B(嗯,A跟我說的數據是1) 結果:臥槽,這不對啊 A:我沒錯啊 B:我也沒錯啊 那么請問誰錯了? 答:例子1沒問題,例子2問題出在B持有了舊數據后還進行了操作。小c在中間把數據改為了2,而B還拿著A給它的數據1,B根本不知道最新的數據已經是2了,他還拿著1,就是舊數據。 ~~~ >[danger] mysql查詢操作默認不加排他鎖(加共享鎖,并行非阻塞),更新操作默認會加排他鎖(串行阻塞的),這就是在操作產生“縫隙”的原因,而樂觀鎖查詢時雖然沒加排他鎖,但是它更新時利用更新操作排他鎖的特性,把where查詢操作和update更新操作合在一條語句里面了,所以就不會出現“縫隙”了。 (如果更新影響的條目為0,也就是說發現舊數據了。樂觀鎖會帶來“重試”——即用戶下單時會提示沒有庫存了(特點:返回時間短,不阻塞,可以讓用戶重新試著再次提交,重試因此得名);而悲觀鎖,針對同一商品的搶購秒殺時,用戶會明顯的感覺到提交訂單時有點慢,因為加的是悲觀鎖。特點:阻塞,耗時,返回結果靠譜,不重試; 兩種鎖的相同點,并發的量越大,重試的幾率越大,阻塞的時間也越長。) 補充:樂觀鎖的where根據實際情況會有很多種查詢方式,這個看你對數據要求的嚴格級別了。比如下單時,針對庫存`where inventory > $num` 這樣就可以了,而不需要這樣 `where inventory = $inventory_old`,有的要求嚴格甚至的這樣 `where version = $version_old` ,當然具體怎么用還需要根據實際實際情況去考量的。 **其實就是這個控制了樂觀鎖的“鎖粒度”了,where越寬松,鎖粒度越大,重試的幾率越小,where越嚴格,鎖的粒度越小,重試的幾率越大,即鎖粒度和重試幾率成反比。**(終于明白了我以前不理解的概念) **鎖粒度與重試記錄(幾率)成反比,與并發能力成正比。(僅限于樂觀鎖)** 所以在使用樂觀鎖的時候要盡可能的使用更加寬松的where,使所粒度更大,這樣重試的幾率就會小些,從而提高程序的并發性。(不然你老讓用戶重試好啊) **悲觀鎖,鎖粒度越小,并非能力越大。鎖粒度和并發成反比。(僅限悲觀鎖)** [Mysql樂觀鎖悲觀鎖行鎖表鎖是從哪幾個方面來分類的?比如說表鎖也可是樂觀鎖,也可以是悲觀鎖嗎?](https://segmentfault.com/q/1010000003917591) * * * * * **思考:** 看到了樂觀鎖實現的原理,發現樂觀鎖的本質其實不是鎖。哈哈,可以叫樂觀鎖為假鎖,悲觀鎖為真鎖。 其實悲觀鎖的內部實現我們真的了解嗎? 樂觀鎖,悲觀鎖,文件鎖。進程鎖,內存鎖,自旋鎖,軟鎖,硬鎖,cas,互斥量,讀寫鎖,……,本質是什么,具體內部究竟是怎么實現的呢?或許其實根本就是樂觀鎖吧,我們的程序是運行在操作系統上的,內部實現應該是操作系統提供的實現。 參考:[內存鎖與內存事務 - 劉小兵2014](https://my.oschina.net/digerl/blog/34001#tt_daymode=1) > 鎖有更復雜的實現如更新鎖,意向鎖,樂觀鎖,悲觀鎖,輕量級鎖,偏向鎖,自旋鎖等等,都是針對不同的需求特征或事務等級定制的鎖。事實上,這里面的很多只是使用了鎖的名字,所以其實并不是鎖,因為它們沒有起到排它的作用如自旋鎖,輕量級鎖,偏向鎖等等其實都不是鎖。特別是樂觀鎖,卻是通過不鎖來達到鎖的效果。 不管是鎖還是什么,我們應用它的目的都是為了,讓我們的程序在任何時候,業務邏輯不會出錯,跟預期一致,安全、穩定、可靠。這三點是對一個合格軟件的基本要求。 * * * * * **你當前所查看的數據永遠都不可能一定是最新的,除非你在查看的同時就把它鎖住。** * * * * * **樂觀與悲觀** >[info] 不行那就再試一次哈,樂觀點嘛^_^ >[danger] :( 好慢啊,我被人阻塞者,一直在等待,郁悶中……,悲哀啊! * * * * * **舊數據怎么來的?** 持有舊數據進行操作會帶來后果的根本原因就是因為,我們每一種完整的操作(添加文章,為文章添加標簽等等)都是有一些單個操作組成的,而這些操作執行是是單獨的,比如一條一條的sql語句,這中間的過程是有縫隙的,那么問題就出在這縫隙里面,處于縫隙的過程中其他的操作就可能會隨時插進來(我們永遠不能預測誰會什么時候突然插進來),就出現舊數據了,而出現舊數據之后會帶來問題,是因為,我們后面的操作可能依賴于前面的操作的反饋結果和數據,本來沒人插進縫隙產生舊數據,那么程序的執行就是我們預期的那樣,現在縫隙被人插入了,有舊數據了,而我們后面的操作卻對此渾然不覺,悶頭的繼續操作,那么顯然就會出現和我們預期不一樣的結果,也就是BUG了,這個后果是可以提前考慮分析出來的,具體應該做上面已經說清楚了。 * * * * * **前臺:我們永遠不敢說我此刻所查看的數據是最新的** 只要是對數據有更改的操作都需要考慮并發問題,一般是`POST`類的請求,簡單的`GET`通常不會對數據進行更新的操作,所以一般沒有并發的問題,只是簡單的取出數據而已,用的是**一致性非鎖定讀**,只是查看數據而已,不會對數據有確切的實時性要求,因為理論上前臺查看數據永遠不可能確保你此刻所查看的是最新的數據,**也就是前臺對舊數據并不那么在意**,它只是顯示而已,并不會造成什么安全性的問題,但是更新的操作就不同了,所以請注意這點,**注意所有的`POST`操作,所有的可能對數據進行更改的操作,謹慎對待一切會對數據進行更改的操作。** * * * * * ### 薛定諤的貓 **實際上,這個問題就是[薛定諤的貓](https://www.zhihu.com/question/57096040/answer/153384751)** > ……你個東西你不去管它,它就在那里,若你研究它,研究結果就會受到你自身的影響。…… > <span style="color:red;">數據就在那里,它的存在與你無關,不論你是否去觀察它,但是當你一旦去觀察它的時候,結果又會受你自身的影響了,所以理論上,你永遠無法得到它真實的樣子,除非你不去觀察它,但你不觀察它你就不知道它此時處于什么狀態。</span> 對于萬物論來說,每時每刻都有事件發生,你覺得什么時候發生,那是相對觀察著的,即使沒有觀察者,事件也在發生,但是這樣我們就不知道了,所以通常我們所說的發生,其實都是站在觀察者的角度的。 * * * * * **思考:** >[danger] 實際上時間是一個相對概念,秒、微妙,還可以再進行細化,理論上存在同一時刻,但是實際上卻不能夠證明這一點,因為理論上你知道無限細分最終也是會在一個點上的,而實際上你又無法去實際的證明它。這是一個無法被證明的理論。 [怎么去證明兩個是事件是在同一時刻發生的?](https://segmentfault.com/q/1010000009908203) * * * * * [我是一個線程(修訂版)](http://mp.weixin.qq.com/s/-BMCUuIWYE3O_oC3ZNNJRg) [我是目錄 - 2017-07-11 劉欣 碼農翻身](https://mp.weixin.qq.com/s/nCx7Jb5WRXGzkpsuth6LAw) * * * * * ### 相關閱讀 [為什么說樂觀鎖是安全的的](http://www.hmoore.net/xiak/php-node/348580) * * * * * **其他** 這是微信支付文檔 支付結果通知 中的一段摘抄 ![](https://box.kancloud.cn/ff2784fba7f646bbf8f7a3085032c019_964x317.png) 參考:[函數重入問題 - CSDN博客](https://blog.csdn.net/gj19890923/article/details/9017809) * * * * * ### 如果不能完全避免錯誤,那就努力把出錯的概率降到最低。 ~~~ `switch` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT '應用開關:1-開,0-關。應用升級、安裝、維護時需要暫時關閉,使其不能訪問,否則會出現意外(即使這樣也還是不能完全避免極端時候的并發問題,不過還是將故障降到最低概率了)', 來自家校 s_app表 ~~~ * * * * * ### 安全:陷阱和意外無處不在 >[danger] 系統不斷向下游發送sql,這就是也業務邏輯的體現,但對于下游數據庫系統來說,它并不知道,它并不關心你所謂的業務邏輯,它只知道接受sql執行。**這些sql交錯著**,最終順序被下游數據庫執行。但是 `一個業務邏輯` ,**包含的多條sql要保證順序執行,中間不能被其它sql插進來,否則就會有并發問題,因為它們是一組的**,業務就不能按照預期執行,要保證每個業務的sql為一個原子,獨立的整體單元,而不是分散的單條sql,這就要引入事物和鎖了。 >[danger] 業務邏輯要正確,要穩定可靠,就必須保證它是嚴格按照我們預期的執行的,不會出現差錯,不能夠出現意外,所以你要謹慎小心的對待,你的每一步都有可能踩到陷阱里面去。所以每一步你都要認真的思考。 **為了安全,任何時候都得考慮并發問題,都要考慮并發問題帶來的每一種后果,并做好容錯。** 任何時候,只要是大于一條sql的操作,都必須使用事務控制,因為你不可能保證第二條語句一定會成功,使用事務控制,保證數據的一致性/完整性,直接回滾是最簡單的。 > 想想沒有事務的年代(MYISAM),如果第二條出錯,我們還得判斷,手動處理失敗留下的后遺癥問題,比如onethink里面,文章新增sql失敗的話要手動刪除上面一條sql的插入,但是誰又能保證修復語句又一定能成功呢,如果也失敗了呢,這陷入了一個無限循環去補救,用一個錯誤去彌補上一個錯誤的泥潭(深淵)里去了,所以事務是你唯一的選擇。 >[danger] 根據“墨菲定律”——“凡事只要有可能出錯,那就一定會出錯。所以凡是有可能失敗的,就一定會出現失敗的情況,凡是可能出現并發問題的,就一定會出現并發問題,所以每一行代碼都要嚴謹,并為可能出現問題的部分做好異常處理,以保證代碼在每個地方都周到嚴密,不會在未來出現什么亂子。 ![](http://cdn.aipin100.cn/18-4-2/77693588.jpg) https://github.com/top-think/framework/blob/5.1/library/think/cache/driver/File.php 所有的 文件/目錄操作 都可能出現并發問題而操作失敗,比如文件或目錄有可能被殺毒軟件鎖住掃描呢,所以都需要考慮失敗到失敗的情況。 * * * * * [當多線程并發遇到Actor](https://mp.weixin.qq.com/s/mzZatZ10Rh19IEgQvbhGUg) [改進日志寫入并發問題 · top-think/framework@618fb51](https://github.com/top-think/framework/commit/618fb517888ad6baf03915316f1786fc52ffc6b9) [php高并發狀態下文件的讀寫 - 踏雪無痕SS - 博客園](https://www.cnblogs.com/chenpingzhao/p/4796265.html) > 如果并發高,在我們對文件進行讀寫操作時,**很有可能多個進程對進一文件進行操作,如果這時不對文件的訪問進行相應的獨占,就容易造成數據丟失** (編程語言是在操作系統之上的,系統調用層面已經考慮了并發下沖突問題,所以我們程序層面應該是不會造成數據錯亂和亂碼的情況,但是會造成“更新丟失”的問題。) [數據庫的最簡單實現 - 阮一峰的網絡日志](http://www.ruanyifeng.com/blog/2014/07/database_implementation.html) > 所有應用軟件之中,數據庫可能是最復雜的。 [【系統架構】大白話聊聊分布式事務](https://mp.weixin.qq.com/s/yBquVKyKnhpy2yPxY-0eqA) [同步鎖的三種實現與案例解析 - CSDN博客](http://blog.csdn.net/u013630349/article/details/78826305) [Doug Lea并發編程文章全部譯文 | 并發編程網 – ifeve.com](http://ifeve.com/doug-lea/) [談談高并發下的冪等性處理](https://mp.weixin.qq.com/s/iQOXjCZJK_o1tLnKNQcp8w) * * * * * #### 并發問題帶來的后果:到底挨不挨打? ~~~ 老婆: 可不可以打你一巴掌,當前狀態是可以,于是,老婆的手舉起來開始揮過來了,這時,突然喊不能打,狀態改為不能打,但是已經晚了,老婆的手已經停不了了,于是啪,一巴掌。老婆: 你不早說,反正我問你的時候你是說可以打的。 這就是并發沒加鎖的例子。 加鎖是這樣的,老婆: 可以打嗎,我: 可以,老婆: 那我開打的過程中就不許在變了哦。 于是,再老婆: 打完之前,都不能再改狀態了,所有要改狀態和問狀態的請求,都會被阻塞,只有打完啪之后才會釋放鎖,這樣就沒有任何異議了。 沒有獨占鎖的問題,為文章添加標簽,標簽狀態必須是可用的。更改標簽狀態和為文章添加可用標簽兩個請求的并發問題。1. 查詢標簽是否存在和狀態,更改狀態。2. 查詢文章是否存在,查詢標簽是否存在,以及狀態是否可用。是則更新文章標簽。 并發問題。當2條件檢查為是時,準備更新文章標簽時,1把標簽更改為不可用,那么就為文章添加了一個不可用的標簽。這就出現了并發問題!!!并發問題往往是達不到預期的業務邏輯。要避免這個問題,1和2對標簽的查詢只能夠使用獨占鎖才可以。 ~~~ * * * * * > 一般,數據展示時,都不會用鎖,都是快照讀,即無鎖定讀,只有當對數據進行變更時才會出現危險,所以任何對數據變更的地方都需要特別注意。 >[danger] **凡是有可能失敗的地方,就一定會發生失敗,所以檢測、容錯性要做好,不能偷懶!** >[danger] **更改數據那個地方,第一條sql就是查詢,這個查詢要上獨占鎖,只有這樣下面更改才是安全的。** >[danger] 并不是說寫代碼是悲觀主義,而是要嚴謹。 >[danger] 任何時候都要考慮并發,沒有考慮并發問題的程序是不完整的,是不要嚴謹,不正確的,不合格的程序。 >[tip] 涉及到錢的一定要用鎖! * * * * * ### 形象展示為什么會有并發問題 ![](http://cdn.aipin100.cn/18-7-6/49426434.jpg) 這就是并發問題,3操作對于進程2是不可見的,所以4這一刻還以為狀態還是2時的,但其實不是的,也就是持有了舊數據,既然持有舊數據,那么程序可能就會和預期不一致,這就是并發問題。 小明 可用 小紅 可用 小明 改為不可用 小紅 剛看了是可用的 用鎖的話 小明 只能我一個人看,可用 小紅 有人再看,等一會吧 小明 改為不可用,走了 小紅 輪到我看了,也只準我一個人看,不可用 小紅 哦,不可用啊,我走了 數據不會被兩個人同時共享,每個人,每一刻持有的都是最新數據,不可能持有到舊數據。 將并行問題變成串行來解決,這也體現了鎖其實就是一種排隊,或者說是控制并發程序訪問共享資源的順序和規則。 * * * * * [MySQL 返回更新值(RETURNING)_四爺-CSDN博客_mysql returning](https://blog.csdn.net/yueliangdao0608/article/details/41643897) > update ... returning 特性可以用來在業務代碼中非常方便的實現某些防止并發問題的功能,可惜 mysql 不支持 ---- last update:2018-4-10 17:54:21
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看