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

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 事務筆記 [TOC=3,8] ---- ### mysql鎖筆記 開兩個命令行 A:對行1更新 B:開啟事務,開啟事務后,對A的更新是看不到的 但是如果B此時查詢帶上for update變成行鎖的話,那么此時數據查出來是最新的,并且發現A再進行更新操作就會被阻塞。 要不了一會兒,A報錯: ``` ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction(超時) ``` 然后BCOMMIT 提交事務,A瞬間獲得鎖,做更新。 奇怪,不對啊, for update不是針對事務的嗎,A沒有使用事務,此時應該是“一致性非鎖定讀”才對啊,怎么也會被阻塞呢? (我有病啊,讀是沒問題的,A現在做的是更新好不好,更新還是需要得到排它鎖的,這不是“一致性非鎖定讀”,查詢時是沒有問題的,A和PHP一樣正常的) 我們用PHP再來做一下實驗: ~~~ 還是B開啟事務,鎖定,PHP來做和A同樣的事試試: PHP也還是會阻塞,A明明沒有開啟事務啊,正常的 ~~~ 上面是在Console上開多選項卡進行實驗測試的流程描述和結果。 結論: for update語句只在事務內有效,它是數據庫為了讓select查詢語句擁有加鎖的能力而添加的特性,它使select語句可以加排他鎖的,使用效果是select語句會鎖住它所涉及到的數據行,并且拿到最新的數據(因為它要鎖定的就是最新的數據啊),而不再是事務外的修改對事務內不可見(可重復讀時),請注意這點。 ======== 好這個問題分析完了,看下一個問題: 如果不開啟事物,A查詢,B高頻率的改,對A會有什么影響,A還會有“一致性非鎖定讀”的光環嗎? B高頻率的改,對A的查詢和更新不會有什么明顯的影響,至少沒出現過阻塞 * * * * * A開啟事務,修改zb_user的id為1的mobile=1 B客戶端,修改zb_user的id為2的mobile=1 結果被阻塞 直到報錯 ``` ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction ``` mobile為唯一索引,可見在事務類,鎖住了mobile=1,所以即使B沒有開啟事務,修改mobile=1的也會被阻塞。 關閉客戶端A,那么A的事務自動回滾了,此時B才能執行。 * * * * * 客戶端A、B都開啟事務, A修改修改zb_user的id為5的mobile=5 B修改修改zb_user的id為5的mobile=5 B會被阻塞; 提交A,B獲得鎖,執行成功。 * * * * * 客戶端A、B都開啟事務, A修改修改zb_user的id為7的mobile=7 B修改修改zb_user的id為6的mobile=7 B會被阻塞; 提交A, B執行完,但報錯,ERROR 1062 (23000): Duplicate entry '7' for key 'mobile' * * * * * 客戶端A事務 A修改修改zb_user的id為1的login=11 B修改修改zb_user的id為1的login=1111 B會被阻塞; 提交A, B執行完,login結果為1111 * * * * * 可見這次B被阻塞是因為,A更新id=1時鎖定了這一行,需要直到提交才會釋放鎖,而上面那個是因為mobile是唯一索引,所以鎖住了唯一索引。 得出結論,事務內更新操作會加鎖,并且直到提交才會釋放鎖。事務外修改也要獲得鎖,不過sql執行完就自動釋放鎖了,可以理解為,每一條sql執行完就立即自動提交了。 并且要注意的是,在默認的“可重復讀”隔離模式下,事務外的修改對事務內是不可見的。但是不管在哪里,事務外,還是事務內,還是有沒有開啟事務,鎖都是唯一的。不開啟事務修改數據也會先要獲得排它鎖,事務內修改也要獲得排它鎖。鎖是獨立于多版本控制MVCC之外的,不受局限,它是唯一的,對要上鎖的數據來說是唯一的,即,一個數據同一時刻只能被一個排它鎖上鎖,這與數據所處的環境,事務無關。這就是鎖的意義所在,不然鎖就沒有意義了。 補充:即使事務回滾,AUTO_INCREMENT也還是不能回滾的哦。所以可能出現ID斷層。 * * * * * A開啟事務 B 更新id為2的mobile=2 A查詢發現id為2的mobile還是原來的,因為在事務內,可重復讀,外面的修改對事務內是不可見的。 A更新id為3的mobile=2,報錯 ``` ERROR 1062 (23000): Duplicate entry '2' for key 'mobile' ``` 可見,雖然事務是可重復度,但是為了保證正確性,更新時卻不是這樣的,不然就會出現可以更新成功,但是提交時報錯,原因還是一樣的。 * * * * * [MySQL 四種事務隔離級的說明 - jyzhou - 博客園](http://www.cnblogs.com/zhoujinyi/p/3437475.html) [MySQL事務隔離級別詳解 - JAVA夜無眠 - ITeye博客](http://xm-king.iteye.com/blog/770721) > SQL標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低級別的隔離級一般支持更高的并發處理,并擁有更低的系統開銷。 [MySQL數據庫事務隔離級別(Transaction Isolation Level) - 生死看淡,不服就干! - CSDN博客](http://blog.csdn.net/jiangwei0910410003/article/details/24960785) >[danger] 要記住mysql有一個autocommit參數,默認是on,他的作用是每一條單獨的查詢都是一個事務,并且自動開始,自動提交(執行完以后就自動結束了,如果你要適用select for update,而不手動調用 start transaction,這個for update的行鎖機制等于沒用,因為行鎖在自動提交后就釋放了),所以事務隔離級別和鎖機制即使你不顯式調用start transaction,這種機制在單獨的一條查詢語句中也是適用的,分析鎖的運作的時候一定要注意這一點。 **其實我們平常的每條sql都是作為事務執行的(在事務中執行的)** <p style="color:red;">也就是說,其實我們平常的每一條普通的sql,我們覺得沒有開啟事務,但其實都開啟了事務,確實是作為事務執行的,單條sql作為一個事務自動開啟和提交了,只不過我們沒有感覺到而已。理解這點很重要。</p> 終于明白了 `select …… for update` 為什么要在事務內才有效果,原來是因為,默認是自動提交了,看似沒有使用事物,但其實每一條sql都是自動開啟并提交了事務的,所以鎖也就在sql本身執行完就釋放了啊,所以這樣加鎖當然沒意義啊,鎖一下,立馬就松開釋放了有什么意義呢。 > SERIALIZABLE事務隔離級別最嚴厲,在進行查詢時就會對表或行加上共享鎖,其他事務對該表將只能進行讀操作,而不能進行寫操作。 (可見更高級別的隔離就是要用更高級別的鎖,這樣會有更大的系統開銷,并發能力也越低,但是為了數據的完整性,業務邏輯的需要,不得不做這樣折中的選擇,以更大的開銷,犧牲性能來換我們對數據的業務要求。任何事情都是這樣的,都是多面性的。) **MYSQL事務的隔離級別** | 隔離級別 | 為了解決 | 會產生的問題| 問題描述| | --- | --- |---|---| | 未提交讀 Read Uncommitted | | 臟讀 | A事務沒有提交的數據能夠被B事務讀到 | | 已提交讀 Read Committed | 臟讀 | 不可重復度 | 事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新并提交,導致事務A多次讀取同一數據時,結果 不一致。 | | 可重復度 Repeatable Read | 不可重復度 | 幻讀 | A事務的提交對B事務是不可見的(默認),但是新增的數據對事務B是可見的,如果使用 事務B使用了 for update 則為當前讀,此時對事務B也是可見的 | | 可序列化 Serializable | 幻讀 | | 沒有問題,唯一的問題在于這種嚴格的模式性能是最低的,因為不能并發了 | **問題描述** | 問題 | 描述 | 解決方式 | | --- | --- | --- | | 更新丟失 | A、B同時編輯一篇文章,后提交的一個人會把前面一個人的提交覆蓋掉 | 程序業務邏輯層中去解決 | | 臟讀 | 在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用于實際應用,因為它的性能也不比其他級別好多少。讀取未提交的數據,也被稱之為臟讀(Dirty Read)。 | 已提交讀 | | 不可重復讀 | 由于B事務提交了對數據行的修改,那么A事務中兩次讀到的的數據可能是不一樣的 | 可重復讀 | | 幻讀 | 簡單的說,幻讀指當用戶讀取某一范圍的數據行時,另一個事務又在該范圍內插入了新行,當用戶再讀取該范圍的數據行時,會發現有新的“幻影” 行。InnoDB和Falcon存儲引擎通過多版本并發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。 | 可序列化 | > 隔離級別,其實就是 **一致性** 與 **可用性** 的 相互折衷和妥協(即 CAP 理論中的C、A)。應用需要根據實際情況進行取舍。 **MYSQL鎖** 排它鎖,共享鎖,意向排它鎖,意向共享鎖。 查詢操作默認是 【一致性非鎖定讀】。更新,插入,刪除都是需要對數據加排它鎖的。這個加鎖是自動的。如果在事務中,則需要等待事務提交后自動釋放鎖,如果不在事務中,獲得鎖執行完sql后立即釋放鎖。 [MySQL的四種事務隔離級別 - 帶著夢逃亡 - 博客園](https://www.cnblogs.com/wyaokai/p/10921323.html) [鎖住余額,為何還會更新異常?](https://mp.weixin.qq.com/s?__biz=MzIzMTgwODgyMw==&mid=2247483935&idx=1&sn=176c01be1a220071e78d60e6d295c34e&chksm=e89fc847dfe841515bf8901ec7ee7ca3102731cdb475275093f2d07ac9a6bb10d54ce37beed9&scene=178&cur_album_id=1337216649245655040#rd) >[tip] 可重復讀要注意別使用**快照讀**了,這個細節很重要,不然將會存在安全隱患。 * * * * * `FOR UPDATE` 是針對事務的,只會在事務內才有鎖效果 而更新操作不論是在事務內還是在事務外都會對所影響到的數據加排他鎖,如果在事務外,sql執行完立即釋放鎖,如果在事務內則等待事務提交后才釋放鎖。 * * * * * 參考:[MySQL學習之——鎖(行鎖、表鎖、頁鎖、樂觀鎖、悲觀鎖等) - 一個手藝人 - 博客頻道 - CSDN.NET](http://blog.csdn.net/mysteryhaohao/article/details/51669741) **?InnoDB行鎖模式兼容性列表** |請求鎖模式 是否兼容 當前鎖模式 | X | IX | S | IS | | --- | --- |---|---|---| | X | 沖突 | 沖突 | 沖突 | 沖突 | | IX | 沖突 | 兼容 | 沖突 | 兼容 | | S | 沖突 | 沖突 | 兼容 | 兼容 | | IS | 沖突 | 兼容 | 兼容 | 兼容 | 如果一個事務請求的鎖模式與當前的鎖兼容,InnoDB就將請求的鎖授予該事務;反之,如果兩者不兼容,該事務就要等待鎖釋放。 意向鎖是InnoDB自動加的,不需用戶干預。**對于UPDATE、DELETE和INSERT語句,InnoDB會自動給涉及數據集加排他鎖(X);對于普通SELECT語句,InnoDB不會加任何鎖;事務可以通過以下語句顯示給記錄集加共享鎖或排他鎖。** * 共享鎖(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。 * 排他鎖(X):SELECT * FROM table_name WHERE ... FOR UPDATE。 用SELECT ... IN SHARE MODE獲得共享鎖,主要用在需要數據依存關系時來確認某行記錄是否存在,并確保沒有人對這個記錄進行UPDATE或者DELETE操作。但是如果當前事務也需要對該記錄進行更新操作,則很有可能造成死鎖,對于鎖定行記錄后需要進行更新操作的應用,應該使用SELECT... FOR UPDATE方式獲得排他鎖。 * * * * * ### 參考 [關系型數據庫為什么能活這么久?](https://mp.weixin.qq.com/s/tvUQPSITJ7mxNuxLUbNPOw) [mysql事務處理用法與實例詳解 - 網名還沒想好 - 博客園](http://www.cnblogs.com/ymy124/p/3718439.html) [幻讀和不可重復讀的區別 - 閉關修煉 - 博客頻道 - CSDN.NET](http://blog.csdn.net/v123411739/article/details/39298127) [MySQL "replace into" 的坑 - 默念默 - 博客園](http://www.cnblogs.com/monian/archive/2014/10/09/4013784.html) [MySQL :: MySQL 5.7 Reference Manual :: 13.2.8 REPLACE Syntax](https://dev.mysql.com/doc/refman/5.7/en/replace.html) [數據庫村的旺財和小強](https://mp.weixin.qq.com/s/tSF_w9xUOj3Q2hmOxJkwLg) > 有的操作必須要串行,才能保證最終結果正確,所以數據庫的解決辦法都是用鎖。 可以再補充一個,【更新丟失】:更新丟失其實不是數據庫層要解決的問題,而是業務邏輯層要解決的問題,比如A、B同時打開同一篇文章進行編輯,A先提交保存了,B再點擊提交保存,就會覆蓋掉A之前保存的內容。解決更新丟失的問題,可以給文章加一個版本號;或者A打開時就記錄下A打開的狀態,此時就不能允許其他人打開編輯了。 * * * * * [分布式系統的事務處理](http://coolshell.cn/articles/10910.html) > 分布式事務處理,更加的困難,也就是著名的**拜占庭將軍問題 (Byzantine Generals Problem)** [解決分布式系統事務一致性的幾種方案對比,你有更好的嗎?](http://mp.weixin.qq.com/s/kzmTKKH-t6tpJ97fa6TYPg) ~~~ ……我們會盡量把可提供回滾接口的服務放在前面。 解決了通知的問題,又有新的問題了。萬一這消息有重復被消費,往用戶帳號上多加了錢,那豈不是后果很嚴重? 仔細思考,其實我們可以消息消費方,也通過一個“消費狀態表”來記錄消費狀態。在執行“加款”操作之前,檢測下該消息(提供標識)是否已經消費過,消費完成后,通過本地事務控制來更新這個“消費狀態表”。這樣子就避免重復消費的問題。 從上面分析的幾種情況來看,貌似問題都不大的。那么我們來分析下消費者端面臨的問題: 消息出列后,消費者對應的業務操作要執行成功。如果業務執行失敗,消息不能失效或者丟失。需要保證消息與業務操作一致 盡量避免消息重復消費。如果重復消費,也不能因此影響業務結果 如何保證消息與業務操作一致,不丟失? 主流的 MQ 產品都具有持久化消息的功能。如果消費者宕機或者消費失敗,都可以執行重試機制的(有些 MQ 可以自定義重試次數)。 如何避免消息被重復消費造成的問題? 保證消費者調用業務的服務接口的冪等性 通過消費日志或者類似狀態表來記錄消費狀態,便于判斷(建議在業務上自行實現,而不依賴 MQ 產品提供該特性) 其實為了交易系統更可靠,我們一般會在類似交易這種高級別的服務代碼中,加入詳細日志記錄的,一旦系統內部引發類似致命異常,會有郵件通知。同時,后臺會有定時任務掃描和分析此類日志,檢查出這種特殊的情況,會嘗試通過程序來補償并郵件通知相關人員。 在某些特殊的情況下,還會有“人工補償”的,這也是最后一道屏障。 ~~~ * * * * * [國之驕傲!他的課堂帶領中國計算機叫板美國,高考狀元們擠破頭也想進](http://www.toutiao.com/i6448402201713836557/?tt_from=weixin&app=news_article&iid=12619555732&wxshare_count=1) [Raft 為什么是更易理解的分布式一致性算法 - mindwind - 博客園](http://www.cnblogs.com/mindwind/p/5231986.html) [raft算法與paxos算法相比有什么優勢,使用場景有什么差異? - 知乎](https://www.zhihu.com/question/36648084) [春晚搶微信紅包如何實現 - 騰訊云分布式消息隊列CMQ架構](http://www.toutiao.com/a6333075051169399041/?tt_from=weixin&utm_campaign=client_share&app=news_article&utm_source=weixin&iid=12619555732&utm_medium=toutiao_android&wxshare_count=1) [分布式事務之TCC服務設計和實現](https://mp.weixin.qq.com/s/L7c1yKLZf8ZkMNiUerokyQ) * * * * * [MySQL鎖問題 - Lucky_man - 博客園](http://www.cnblogs.com/lucky-man/p/6207776.html) ~~~ 間隙鎖 當使用范圍條件檢索數據的時候,對于鍵值在條件范圍內但并不存在的記錄,InnoDB也會進行加鎖,這個鎖 就叫“間隙鎖”。InnoDB使用間隙鎖的目的,一方面是為了防止幻讀,另一方面是為了滿足恢復和復制的需要。但是 這種加鎖機制會阻塞符合條件范圍內鍵值的并發插入,造成嚴重的鎖等待,所以應該盡量避免使用范圍條件來檢索數據。 除了通過范圍條件加鎖時使用間隙鎖外,如果使用相等條件請求給一個不存在的記錄加鎖,InnoDB也會使用間隙鎖! ~~~ [MySQL中鎖詳解(行鎖、表鎖、頁鎖、悲觀鎖、樂觀鎖等) - 坦GA的博客 - CSDN博客](http://blog.csdn.net/tanga842428/article/details/52748531) * * * * * ### 注意 InnoDB引擎下由超時(往往是等待鎖)引發的異常錯誤,<span style="color:#F90B0B">**并不會自動回滾數據庫哦,而是隱式的提交了,這是很危險的!**</span>所以程序中需要注意了,一定要捕獲到這種異常,然后回滾,不然就會很危險了。 ```php try { sql執行 提交 } catch (Exception $e) { 回滾 } ``` * * * * * ### 擴展 [分布式事務XA](https://www.cnblogs.com/zengkefu/p/5742617.html) [MySQL 百萬級數據量分頁查詢方法及其優化](https://mp.weixin.qq.com/s/le6ue-8q9T20WWWFw8fvuQ) [談談中間件開發,給想從事中間件開發的同學](https://mp.weixin.qq.com/s/hXnMmXWkFHebT5GddvwVZg) [SpringBoot多數據源中的分布式事務](https://mp.weixin.qq.com/s/lO0EF7-n-mNffzrUzXYmJA) [10分鐘搞定ICO](https://zhuanlan.zhihu.com/p/32796998) [比特幣入門教程 - 阮一峰的網絡日志](http://www.ruanyifeng.com/blog/2018/01/bitcoin-tutorial.html) [區塊鏈入門教程 - 阮一峰的網絡日志](http://www.ruanyifeng.com/blog/2017/12/blockchain-tutorial.html) > 區塊鏈是什么?一句話,它是一種特殊的分布式數據庫。 [如何理解拜占庭將軍問題? - 知乎](https://www.zhihu.com/question/23167269) [超級賬本PBFT(拜占庭容錯)算法詳解 - CSDN博客](http://blog.csdn.net/fidelhl/article/details/52833118) [拜占庭將軍問題深入探討 | 巴比特](http://www.8btc.com/baizhantingjiangjun) > 拜占庭問題 和 兩軍問題 不同,不能混為一談。 [漫畫:什么是拜占庭將軍問題?](https://mp.weixin.qq.com/s/-dTBkwVaRo6WxZ8uS9DwjQ) [一文看懂區塊鏈 為何騰訊等巨頭紛紛殺入?](https://www.toutiao.com/a6508633088778568206/?tt_from=weixin&utm_campaign=client_share&article_category=stock&timestamp=1515433507&app=news_article&utm_source=weixin&iid=22069500288&utm_medium=toutiao_android&wxshare_count=1) [Spring Cloud 分布式事務終極解決方案探討](http://mp.weixin.qq.com/s/VMYsLKYV__Nf_UuVSR0HDw) [九分鐘了解區塊鏈](https://mp.weixin.qq.com/s/iHEFRZTcLDXQ5trzKbPt3g) [目前介紹比特幣和區塊鏈最好的視頻](https://www.ixigua.com/a6514121541184127501/?utm_source=toutiao&utm_medium=feed_stream#mid=60418991004) [漫談分布式系統、拜占庭將軍問題與區塊鏈](http://mp.weixin.qq.com/s/tngWdvoev8SQiyKt1gy5vw) [Java架構沉思錄](https://mp.weixin.qq.com/s/BNiNXylqPwKXMW8rkS6dbQ) [數據庫村的旺財和小強](http://mp.weixin.qq.com/s/bM_g6Z0K93DNFycvfJIbwQ) > 感覺數據庫和分布式,是世界上最復雜的軟件工程,不知道是不是,還有沒有其它的。 [為什么不建議在MySQL中使用UTF-8?](https://mp.weixin.qq.com/s/LmpFIwoNULIqFuyTJqG1Vw)(此 `UTF-8` 非真的 `UTF-8`) [MySQL事務隔離級別和MVCC](https://mp.weixin.qq.com/s/Jeg8656gGtkPteYWrG5_Nw) [一文讀懂數據庫事務](http://mp.weixin.qq.com/s/uvardpe6Qy2cMahi8gFMlA) >[tip] **串性化**(原來可序列化,不是`serialize/serialized`“序列化”的意思啊,是可串行的意思啊,**序列不就是順序串行嗎**,看來**英文在翻譯成中文時確實存在很大問題,很多本來就淺顯易見的東西翻譯過來就變得晦澀難懂了,看來學習過程嚴重依賴翻譯是有很多問題的,容易誤入歧途走很多彎路**),指的是強制事務串行執行,其可以避免“幻象讀”的問題出現,這是最嚴格的隔離級別了。因為串行化需要在發生競爭的數據上加鎖,所以并發性能不高,只有在對數據一致性要求非常高且并發度不高的情況下才會考慮使用這種隔離級別。(雖然我們不使用這種最高級別的事務隔離,但是其實重要數據操作,我們是會加鎖的,比如涉及到轉賬時,會鎖住相應的賬戶直至操作完成,其實也是一種強行變為串行的方式。) >[danger] 多個事務可以同時存在(受隔離級別的影響,會有不同的后果),但如果用了鎖,存在競爭關系(有共同的競態資源),那么事務就是串行的了。可以看到所有的并發問題最后唯一的解決辦法其實都是強制變并行為串行的來解決的,畢竟競態資源只有一個,是唯一的,要保證數據完整性,業務邏輯正確性,必須這樣。**這是沒有辦法的事,計算機不是神,不能獨立于現實生活而存在,所以也要遵守現實科學規則。** [分布式系統事務一致性](https://mp.weixin.qq.com/s/OIqRYvA3iliUG64nI48llA) [深入學習MySQL事務:ACID特性的實現原理](https://mp.weixin.qq.com/s/51vyvMdMnin6yD7MVXHG5w) [MySql 三大知識點——索引、鎖、事務](https://mp.weixin.qq.com/s/btzwjg7uMQ1_H_m2Lnt_pQ) [數據庫分庫分表如何避免“過度設計”和“過早優化”](https://mp.weixin.qq.com/s/uTRwstOABOgZf2YCbgz5TQ) [面試官:你知道哪幾種事務失效的場景?](https://mp.weixin.qq.com/s/AoifU5hk3HHcQxSF0hPIJw) [是誰拯救了數據庫?](https://mp.weixin.qq.com/s/KTNM1AHfN0Gs9cjsJsPyxQ) [上億數據怎么玩深度分頁?兼容MySQL + ES + MongoDB](https://mp.weixin.qq.com/s/vrFU0lsURV5WQOgK7w9Mtw) [select for update引發的死鎖分析,太驚險了](https://mp.weixin.qq.com/s/w6TXqllB8e1EgJqv47dnqg) * * * * * >[danger] **凡是有可能失敗的地方,就一定會發生失敗,所以檢測、容錯性要做好,不能偷懶!** * * * * * >[danger] **每條sql都有可能執行失敗,所以要嚴格判斷每一條sql的執行**,特別是在上下文中有很多sql的情況,這里首先要明確規定一下,對于sql操作失敗是怎樣定義的:更新操作受影響的條目為0,查詢操作結果集為空,刪除操作受影響的條目為0,這些都為操作成功,操作失敗是指sql操作出現異常,比如插入失敗,這個原因就有很多了,sql非法,字段格式錯誤,唯一索引導致的等等,這樣的錯誤會直接拋異常的,不會繼續往下執行的,需要我們捕獲處理。好在tp5框架是這么對待sql錯誤的,所以任何時候我們的sql操作都應該在try{}中,這樣就方便多了,不用一條一條的去判斷執行失敗了。回想起tp3真是噩夢,sql執行失敗不會拋異常,而是返回失敗,并把錯誤信息放到模型error中,讓用戶自己去判斷,真的很麻煩。 >[danger] 你并不能保證你寫的每一條語句一定會執行成功,程序絕對嚴謹嗎,如果停電呢,打雷呢,臨時工挖斷網線呢,這些你考慮了沒有,代碼即科學,**并不能想當然的認為會怎么樣**(計算機技術是經過嚴密的證明,有科學事實依據的,并不是你隨便拍腦袋想出來的)。所以既然我們無法確定未知的錯誤,只能提前做好容錯準備了,**所有SQL操作都必須放在事務內,這是沒有任何商量余地的硬性規定!!!** * * * * * 看來數據庫的 `Undo/Redo` 日志,其實就是撤銷(后退)和重做(前進) ![](http://cdn.aipin100.cn/18-4-3/17100759.jpg) * * * * * >[danger] ### 實現可靠/安全的必備保證:事務+原子性+鎖 系統不斷向下游發送sql,這也是業務邏輯的體現,但對于下游數據庫系統來說,它并不知道,**它并不關心你所謂的業務邏輯,它只知道接受sql執行**。 這些sql交錯著,最終順序被下游數據庫執行(具體跟數據庫的底層設計或存儲引擎實現細節有關)。但是 `一個業務邏輯` 包含的多條sql要保證順序執行,中間不能被其它sql插進來,不能受其它影響,才能保證業務邏輯的正確性,**否則就會有并發問題**,業務就不能按照預期執行。 要保證每個業務的sql操作為一個原子,一個獨立的整體單元,不可分割,而不是分散的單條sql,這就要引入事務和鎖了。 * * * * * [從單一架構到分布式交易架構,網易嚴選的成功實踐](https://mp.weixin.qq.com/s/nv3Ht7OqTYQw31QFDX3gNg) >[danger] **沒有完美的架構設計,世上也沒有絕對的事情,沒有誰能保證絕對可靠、安全和高可用,但我們有補償和容錯(類似還有重試,確認等機制),也是能做到萬無一失的。** [MySQL事務隔離級別和MVCC](https://mp.weixin.qq.com/s/SCW_3AypO-rSolMcjCxVtA) [不知怎么優化MySQL?先搞懂原理再說吧!](https://mp.weixin.qq.com/s/NPeJPesMb6KbFjbWji5xdw) [分布式事務:深入理解什么是2PC、3PC及TCC協議](https://mp.weixin.qq.com/s/jQrPSmPhC_yNbIRcufR8KQ) [關于MySQL,你未必知道的!](https://mp.weixin.qq.com/s/pWHCieOwAdCrz8cauduWlQ) [【技術棧之Mysql】Mysql InnoDB常見死鎖分析](https://mp.weixin.qq.com/s/LqvtEoozs4xWPNnMpLyF5w) [你真的懂Redis事務嗎?](https://mp.weixin.qq.com/s/WOcw5B038P3qLU0c_Rs-Mw) [InnoDB,select為啥會阻塞insert?](https://mp.weixin.qq.com/s/y_f2qrZvZe_F4_HPnwVjOw) [揭秘JDBC超時機制](https://mp.weixin.qq.com/s/lxAHnuRO9rB5VlUTW4AsfQ) [MySQL在并發場景下的優化手段](https://mp.weixin.qq.com/s/BNiNXylqPwKXMW8rkS6dbQ) [分庫分表的事務處理機制](https://mp.weixin.qq.com/s/Z2uqixTplk5CilQNamOR2A) [分析一個MySQL并發事務示例](https://mp.weixin.qq.com/s/hdDl95a6ayVtCoEc3RiLwQ) > 兩種開啟事務方法的區別:使用 ”start transaction with consistent snapshot;“ 語句的目的是馬上啟動事務,”begin/start transaction“命令不是一個事務的起點,而是在執行到他們之后的第一個操作 InnoDB 表的語句后事務才開始。 [找對“關系”后,辦事果然輕松了!](https://mp.weixin.qq.com/s/mpi2tfvLKXAiPK1dxWSTQQ) [RDF 和 SPARQL 初探:以維基數據為例](http://www.ruanyifeng.com/blog/2020/02/sparql.html) > 維基數據 圖數據 [隔離做得好,誰都沒煩惱!](https://mp.weixin.qq.com/s/201mUftRWEFcxx9W_zsD2w) [分布式事務及其中間件介紹 - 掘金](https://juejin.im/post/5e9709d2e51d457918095eac) > 一、原理介紹: TXC模式命名來源于淘寶,實現原理是在執行SQL之前,先查詢SQL的影響數據,然后保存執行的SQL快走信息和創建鎖。當需要回滾的時候就采用這些記錄數據回滾數據庫,目前鎖實現依賴redis分布式鎖控制。 [數據庫如何存儲時間?你真的知道嗎?](https://mp.weixin.qq.com/s/h5qysXyiOpXNvJT8pbTN3g) [死鎖案例一](https://mp.weixin.qq.com/s/1Jd-8d-hZgGlAkvjWmO5kw) [這次終于懂了,InnoDB的七種鎖(收藏)](https://mp.weixin.qq.com/s/f4_o-6-JEbIzPCH09mxHJg) * * * * * ### 嵌套事務的原理 https://github.com/top-think/framework/blob/5.1/library/think/db/Connection.php 關鍵點在: ```php protected function parseSavepointRollBack($name) { return 'ROLLBACK TO SAVEPOINT ' . $name; } ``` 嵌套事務的提交并沒有真正提交,嵌套事務的開啟也并不是真正的開啟,只是計數,嵌套事務的回滾利用了回滾計數。 擴展:[XA 分布式事務原理 - 飛鷹之歌 - 博客園](https://www.cnblogs.com/luoyunfei99/articles/6803682.html) (tp也支持xa事務了) [mysql 事務之使用savepoint部分回滾 - 簡書](https://www.jianshu.com/p/c93c1730e5dc) [PHP中實現MySQL嵌套事務的兩種解決方案_hello_katty的專欄-CSDN博客](https://blog.csdn.net/hello_katty/article/details/45220825) [MySQL 到底支不支持事務嵌套?_weixin_34200628的博客-CSDN博客_mysql事務可以嵌套嗎](https://blog.csdn.net/weixin_34200628/article/details/91725920) > **MYSQL 支持嵌套事務**,但不要直接多次執行 `START TRANSACTION` 以期望有嵌套事務的效果,這會帶來隱式提交,嵌套事務需要你在系統層面去實現(使用:`SAVEPOINT` / `ROLLBACK TO SAVEPOINT` ),再次說明 **MYSQL 是支持嵌套事務的**。 >[danger] 連接斷開后重連事務就不完整不能直接用了,而有的框架有斷線重連的機制(tp db.break_reconnect),在使用事務時,考慮到我們使用事務的目的就是希望這些 sql 都在一個完整的事務當中不可分割以確保邏輯的正確性,所以此時不能使用框架提供的重連機制,因為重連后的連接不再是之前的那個事務的連接了!這是一個很嚴重的問題,如果重連后繼續執行,后續的sql就不再是處于之前的事務之中了!!!那就與我們使用事務的目的背道而馳了!!! ~~~ // 再次開啟事務,會隱式 COMMIT 此連接上的上一個 開啟的事務 START TRANSACTION // 創建保存點 SAVEPOINT name // 回滾到保存點 ROLLBACK TO SAVEPOINT name COMMIT ROLLBACK ~~~ ~~~ // 再次開啟事務,會隱式 COMMIT 此連接上的上一個 開啟的事務 START TRANSACTION // 創建保存點 SAVEPOINT name // 回滾到保存點 ROLLBACK TO SAVEPOINT name COMMIT ROLLBACK ~~~ * * * * * ### 在事務內申請的鎖,是屬于整個事務的 ```php Db::startTrans(); if (Db::name('user')->field('balance,cumulative_earn,cumulative_team_reward')->lock(true)->find(10029)) { echo "1"; } // 鎖不會對同一個事務內鎖申請進行排斥,也就是說,在事務內申請的鎖,是屬于整個事務的 if (Db::name('user')->field('balance,cumulative_earn,cumulative_team_reward')->lock(true)->find(10029)) { echo "2"; } sleep(5); // 如果不提交,腳本執行完畢,連接關閉,事務也會結束的 Db::commit(); ``` 框架并不知道你寫了嵌套的代碼(機器沒有人類直觀可以直接看出來,而是要通過其他規則取理解事物的),只知道計數和順序,這很重要。 #### 在循環中使用事物請注意! 由于框架實現嵌套事務的原理,所以再循環中使事務要特別小心,因為很可能出現嵌套事務哦,盡管你沒有寫嵌套事務的代碼,上面我們已經知道了,“嵌套”只是我們理解的概念,實際上是事務計數。 如果,我們在 continue; 退出當前遍歷直接進入下個遍歷時,沒有提交,下個遍歷又再次開啟事務,這就成了一個嵌套事務了。 這造成的后果就是,就第二個遍歷的提交不會真的提交,原因你應該知道了,因為第二個遍歷中的提交,做的是計數-1。 ---- ### 關于連接的思考 ~~~ 1. mysql 打開連接,執行sql,然后又長時間再沒有執行sql,再執行sql時,可能執行失敗,因為長時間沒有查詢,連接已經被自動關閉了 2. mysql 打開連接未變關閉會怎樣(短連接,和長連接的情況) 3. mysql 打開事務未提交也未回滾會怎樣: a. 程序關閉了,連接未斷開,未提交 b. 斷開連接,未提交 c. 連接丟失(網絡等原因),未提交 4. mysql insert_id() 并發時的問題 5. mysql 并發能力,連接上限,web服務在請求并發量很高時,不能都打在mysql上去了,因為mysql并發能力有限 6. 連接斷開后重連事務就不完整不能直接用了,而有的框架有斷線重連的機制(tp db.break_reconnect),在使用事務時,不能使用重連機制啊,因為重連后的連接不再是之前的那個事務的連接了!這是很嚴重的問題,如果重連后繼續執行,就不再是處于之前完整的事務之中了!!! 資料: https://www.cnblogs.com/gaogao67/p/10859651.html https://www.cnblogs.com/leijiangtao/p/11882107.html https://segmentfault.com/q/1010000012903190 https://www.laruence.com/2011/04/27/1995.html https://www.laruence.com/2010/04/12/1396.html http://guitoo.cc/wordpress/2018/11/04/pdo/ https://blog.csdn.net/u014229282/article/details/81071257 https://dbaplus.cn/news-11-974-1.html https://blog.csdn.net/xc_zhou/article/details/80879863 https://blog.csdn.net/qianwenzhi/article/details/94433279 https://www.cnblogs.com/A121/p/12028972.html ~~~ ---- ### 程序終止了,未提交/未回滾,會怎樣? https://segmentfault.com/q/1010000006202863?_ea=1071166 https://tieba.baidu.com/p/4185856648?pn=0&red_tag=t3424511720&referer=tieba.baidu.com [有關mysql長連接涉及事務的問題? - 知乎](https://www.zhihu.com/question/62603122) 程序報錯,終止運行,未提交和回滾事務。 musql 那邊可能立馬不知道連接斷開了(連接沒有心跳的話就無法得知對方是否掉線了),還會保持這個會話和事務,如果有鎖,可能會一直生效。 所以這種情況還是很危險的,需要保證程序終止前能夠回滾事務。 如果會話活動超時,mysql那邊要主動關閉連接時發現有未提交的事務,可能會回滾,也可能會提交,這取決于默認配置。不過應該默認是回滾。 不要站在應用上像這個問題,站在mysql設計者的角度看這個問題就發現非常簡單。 ---- ### 可重復讀 可重復讀: 先開啟事務,再修改數據,再事務中查詢,能查到最新的修改的。—— 說明并不是開啟事務就固化了數據。 事務中查詢了一次,再修改了數據,事務中再次查詢,結果與前次查詢一致,并不是最新已修改的數據。—— 說明可重復讀 機制 是記錄當當前事務中首次查詢的數據,并在后續查詢與第一次查詢一致。 ---- ### 查詢緩存 應用程序中 重復執行 同一條 sql 這個情況很常見,往往不同的邏輯類相互使用時會有這個問題,因為它們獨立使用時確實需要執行查詢,但當組合使用時就會都執行了查詢,這在開發中很常見,數據庫早就想到了這個問題,在同一個會話連接(一個連接上只能同時開啟一個事務)短時間內執行相同的查詢sql,會有緩存,當數據沒有被修改時都會命中查詢緩存的,所以不用擔心多次將數據從磁盤的某個位置讀取出來的性能問題了。 有關mysql長連接涉及事務的問題? https://www.zhihu.com/question/62603122 http://www.nowamagic.net/librarys/veda/detail/756 https://www.cnblogs.com/coshaho/p/7192343.html https://blog.csdn.net/yongqi_wang/article/details/86674088 > 如果查詢緩存使用了很大量的內存,緩存失效操作就可能成為一個非常嚴重的問題瓶頸。如果緩存中存放了大量的查詢結果,那么緩存失效操作時整個系統可能都會僵死一會。因為這個操作時靠一個全局鎖操作保護的,所有需要做該操作的查詢都需要等待這個鎖,而且無論是檢測是否命中緩存、還是緩存失效檢測都需要等待這個全局鎖。 > 并不是什么情況下查詢緩存都會提高系統性能的。緩存和失效都會帶來額外的消耗,**所以只有當緩存帶來的資源節約大于其本身的資源消耗時才會給系統帶來性能提升。這根具體的服務器壓力模型有關。** > 不過查詢緩存命中率是一個很難判斷的數值。命中率多大才是好的命中率?**只要查詢緩存帶來的效率提升大于查詢緩存帶來的額外消耗,即使百分之三十的命中率對系統性能提升也有很大好處。** 另外,緩存了哪些查詢也很重要,例如,被緩存的查詢本身消耗非常巨大,那么即使緩存命中率非常低,也任然會對系統性能提升有好處。所以,沒有一個簡單的規則可以判斷查詢緩存是否對系統有好處。 ---- ### mysql 索引 [MySQL 索引概覽_wallace_www的博客-CSDN博客](https://blog.csdn.net/wallace_www/article/details/117264149) > 可以擴展了解一下,理論上最左匹配原則中索引對 where 中子句的順序也是敏感的,但是由于MySQL的查詢優化器會自動調整 where 子句的條件順序以使用適合的索引,所以實際上 where 子句順序不影響索引的效果。 [MySQL 索引結構_wallace_www的博客-CSDN博客_mysql 默認索引結構](https://blog.csdn.net/wallace_www/article/details/117304921?spm=1001.2014.3001.5501) [mysql協議詳解_耿小渣的進階之路-CSDN博客_mysql protocol](https://blog.csdn.net/u014608280/article/details/80484861) ---- ### 隔離級別 1. READ-UNCOMMITTED 未提交讀 臟讀問題(讀到了未提交的數據) 2. READ-COMMITTED 已提交讀,解決臟讀問題,新問題:不可重復讀(事務內,兩次相同的查詢可能結果不一致) 3. REPEATABLE-READ 可重復讀,解決不可重復讀問題,新問題:幻讀(事務內,兩次查詢可能出現查詢出前一次未查出的新行) 4. SERIALIZABLE 串行化,解決幻讀問題,但是事務變串行了,吞吐降低了 select @@transaction_isolation; READ-COMMITTED 阿里云 rds 默認 已提交讀 通常 RC 已提交讀 已經夠了,大部分應用 能夠接受 不可重復讀 的問題,RC 在提供了較好的性能的同時也能滿足應用需求,是一個不錯的選擇。只有情況特殊時,才需要 RR 、SR 級別。 ---- last update:2018-9-23 17:03:51
                  <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>

                              哎呀哎呀视频在线观看