<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 一、事務的具體定義 事務提供一種機制將一個活動涉及的所有操作納入到一個不可分割的執行單元,組成事務的所有操作只有在所有操作均能正常執行的情況下方能提交,只要其中任一操作執行失敗,都將導致整個事務的回滾。 簡單地說,事務提供一種“要么什么都不做,要么做全套(All or Nothing)”機制。ACID就不說了,ACID就是對這句話的一個解釋。 ## 二、并發環境下的數據庫事務 ## 2.1 事務并發執行會出現的問題 我們先來看一下事務并發,數據庫可能會出現的問題: * 更新丟失(問題嚴重) 當有兩個并發執行的事務,更新同一行數據,那么有可能一個操作會把另一個操作的更新覆蓋掉。 * 臟讀 (問題嚴重) 一個事務讀到另一個尚未提交的事務中的數據,即讀到了事務的處理過程中的數據,而不是結果數據。 該數據可能會被回滾從而失效。 如果第一個事務拿著失效的數據去處理那就發生錯誤了。 * 不可重復讀 (一般來說可以接受) 不可重復讀的含義:一個事務對同一行數據讀了兩次,卻得到了不同的結果。它具體分為如下兩種情況: 虛讀:在事務1兩次讀取同一記錄的過程中,事務2對該記錄進行了修改,從而事務1第二次讀到了不一樣的記錄。 幻讀:事務1在兩次查詢的過程中,事務2對該表進行了插入、刪除操作,從而事務1第二次查詢的結果數量發生了變化。 > 不可重復讀 與 臟讀 的區別? > 臟讀讀到的是尚未提交的數據,而不可重復讀讀到的是已經提交的數據,只不過在兩次讀的過程中數據被另一個事務改過了。 ## 2.3 如何解決并發過程中事務問題(事務隔離) 數據庫一共有如下四種隔離級別: * Read uncommitted 讀未提交 在該級別下,一個事務對一行數據修改的過程中,不允許另一個事務對該行數據進行修改,但允許另一個事務對該行數據讀。 因此本級別下,不會出現更新丟失,但會出現臟讀、不可重復讀。 * Read committed 讀提交 (oracle、sqlserver默認的隔離級別) 在該級別下,未提交的寫事務不允許其他事務訪問該行,因此**不會出現臟讀**;但是讀取數據的事務允許其他事務的訪問該行數據,因此會出現不可重復讀的情況。 * Repeatable read 重復讀 (mysql的默認隔離級別) 簡單說就是:一個事務開始讀或寫數據時,不允許其他事務對該數據進行修改。在該級別下,讀事務禁止寫事務,但允許讀事務,因此不會出現同一事務兩次讀到不同的數據的情況(不可重復讀),且寫事務禁止其他一切事務。**這個級別無法解決幻讀問題**。 * Serializable 序列化 該級別要求所有事務都必須串行執行,因此能避免一切因并發引起的問題,但效率很低。 ![](https://box.kancloud.cn/d1f1334fce5a9b832eafb79085333c26_844x334.png) 隔離級別越高,越能保證數據的完整性和一致性,但是對并發性能的影響也越大。對于多數應用程序,可以優先考慮把數據庫系統的隔離級別設為Read Committed。它能夠避免臟讀取,而且具有較好的并發性能。盡管它會導致不可重復讀、幻讀這些并發問題,應該由應用程序員采用悲觀鎖或樂觀鎖來控制。 ## 三、事務傳播行為 ### 舉例說明 事務傳播行為用來描述由某一個事務傳播行為修飾的方法被嵌套進另一個方法的時事務如何傳播。 用偽代碼說明: ~~~ ServiceA { void methodA() { ServiceB.methodB(); } } ServiceB { void methodB() { } } ~~~ 代碼中`methodA()`方法嵌套調用了`methodB()`方法,`methodB()`的事務傳播行為由`@Transaction(Propagation=XXX)`設置決定。 ### Spring中七種事務傳播行為 | 事務傳播行為類型 | 說明 | | --- | --- | | PROPAGATION\_REQUIRED | 如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。這是最常見的選擇。 | | PROPAGATION\_SUPPORTS | 支持當前事務,如果當前沒有事務,就以非事務方式執行。 | | PROPAGATION\_MANDATORY | 使用當前的事務,如果當前沒有事務,就拋出異常。 | | PROPAGATION\_REQUIRES\_NEW | 新建事務,如果當前存在事務,把當前事務掛起。 | | PROPAGATION\_NOT\_SUPPORTED | 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。 | | PROPAGATION\_NEVER | 以非事務方式執行,如果當前存在事務,則拋出異常。 | | PROPAGATION\_NESTED | 如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與PROPAGATION\_REQUIRED類似的操作。 | 定義非常簡單,也很好理解,下面我們就進入代碼測試部分,驗證我們的理解是否正確。 ## 四、@Transactional 注解 | 屬性名 | 說明 | | --- | --- | | value | 當在配置文件中有多個 TransactionManager , 可以用該屬性指定選擇哪個事務管理器。 | | propagation | 事務的傳播行為,默認值為 REQUIRED。 | | isolation | 事務的隔離度,默認值采用 DEFAULT。 | | timeout | 事務的超時時間,默認值為-1。如果超過該時間限制但事務還沒有完成,則自動回滾事務。 | | read-only | 指定事務是否為只讀事務,默認值為 false;為了忽略那些不需要事務的方法,比如讀取數據,可以設置 read-only 為 true。 | | rollback-for | 用于指定能夠觸發事務回滾的異常類型,如果有多個異常類型需要指定,各類型之間可以通過逗號分隔。 | | no-rollback- for | 拋出 no-rollback-for 指定的異常類型,不回滾事務。 | ## 五、spring事務的實現 spring事務本質上是依賴于數據庫事務 ![](https://box.kancloud.cn/83b7902520146de4b8468a6c12210d56_955x538.png) Spring事務本質上是依賴于第三方的實現 ![](https://box.kancloud.cn/312679a3bf90c280b9f4fed1f77a8e37_640x369.png) ## 六、分布式事務 筆者自己將分布式事務分為兩種:跨服務的分布式事務,跨庫的分布式事務。 1. 跨庫的分布式事務:我在做一個服務A的時候,需要同時操作兩個數據庫。我們之前給大家講的例子都是這一種,實際上總的思路就是有一個對象統一管理多個事務的提交與回滾。這種分布式事務還是在數據庫層面去解決的。 > 為了大家方便理解:我以小故事給大家簡單講一下兩段式提交:假如我在外地出差到了婦女節分別用給老婆和媽郵寄了禮物,我希望他們兩個都收到禮物并擁有禮物。首先我用快遞把禮物郵到家里,這是一段提交。老婆和媽告訴我:收到了收到了,謝謝!才發現包裝盒帶密碼,她們沒法看禮物。然后我給老婆和媽打電話,告訴他們密碼,他們就可以看了。大家有問題:1.一階段沒問題有響應才到第二階段,二階段禮物到家之后,老婆電話停機怎么辦?只給媽媽打了電話,沒給老婆打。筆者說:這種問題是所有分布式事務解決方案都要面對的問題(面對網絡與宕機問題任何分布式事務都會失效),這個不是兩段式提交自己的問題。那么就沒辦法了么?有,網絡超時就有異常,有異常就回滾,告訴媽媽這個禮物有問題要退回。2.給媽打完電話之后我的電話停機了怎么辦?就是補償方案,我記得這個電話沒打給老婆,等電話充費后再打,進而達到最終一致性,重點是我要記得。在這個例子中,我就是一個事務管理器,而老婆和媽就是資源管理器,資源管理器是在數據庫的組件,而事務管理器通常是應用組件。而不同的數據庫對兩段式提交的支持是不同的,也就是資源管理器不同。參考:[分布式事務之——MySQL對XA事務的支持](https://blog.csdn.net/l1028386804/article/details/79769043) ![](https://box.kancloud.cn/6658fe83ef6c710cfe52f0d43c6b408e_1009x561.png) 2. 跨服務分布式事務: 也就是說我在做一個服務A的時候,需要通過網絡調用多個其他服務,有可能第一個服務B成功了,第二個服務C執行失敗了。這種分布式單純的依靠數據庫層面就很難解決了,一般都是通過最終一致性的方式解決。比如:通過MQ,給服務B發消息,服務B執行,然后真的做持久化操作數據入庫了。給服務C發消息,服務C執行失敗,這個消息就會存在MQ里面,依照一定的策略還會發給服務C,直到服務C成功為止。這樣保障最終一致。
                  <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>

                              哎呀哎呀视频在线观看