mininet编程实现交换机规则的插入、删除与修改。_Mysql事务隔离以及MVCC实现原理...
????????上一篇我們了解了mysql的幾種日志,大致知道這些日志的作用,今天我們配合Mysql的事務以及事務的隔離級別進一步理解mysql如何實現事務相關的特性。其中重點理解mysql innodb的多版本控制和樂觀鎖,這篇大部分是文字描述,也是理解mysql-innodb事務的基礎內容,也是面試會問到的內容。
事務的特征ACID
原子性:事務是一個原子操作單元,其對數據的修改,要么全都執行,要么全都不執行。上一篇我們知道 redo log 用于保證事務持久性,是因為每次數據變更,mysql都會先記錄redo log,然后更新到數據頁的緩存,然后在刷到磁盤中;那mysql是如何實現原子性的呢,首先理解原子性,就是一組操作單元,要么全部執行成功,要么不執行,我們在做分布式的系統的時候,就會涉及到分布式的事務,兩個分布式操作,要么都成功,要么都失敗,所有的操作都需要回滾到最初的狀態,我們所了解有XA協議規則,XA是比較老的分布式事務基礎,它的核心思路是基于兩階段提交的方式,第一階段,數據準備,然后鎖住資源,第二步才會提交。今天我們不討論分布式事務的方案,這里不做深入研究,大家可以了解一下兩階段和TCC三階段,以及Base定理和CAP定理。好了,言歸正傳,我們從工作中的場景,來反向思考,mysql的事務是如何實現的呢?對于一個事務如何保證這些語句最終能保證原子性呢?上一篇講到了redolog 和binlog的一致性方案,就涉及到兩階段提交的方式來保證一致性。這里要講的是Mysql的undo log,它是保證事務的原子性和隔離性的基礎。
我們知道mysql事務中只要對數據修改的,都會生成相應的undo日志,1.對于每個 insert,這會往undo日志插入一條對應的刪除語句,回滾時會執行 delete2.對于每個 delete,回滾時會執行 insert。3.對于每個 update,回滾時會執行一個相反的 update,把數據改回去。以 update 操作為例:當事務執行 update 時,其生成的 undo log 中會包含被修改行的主鍵(以便知道修改了哪些行)、修改了哪些列、這些列在修改前后的值等信息,回滾時便可以使用這些信息將數據還原到 update 之前的狀態。
一致性:在事務開始和完成時,數據都必須保持一致狀態,保持數據的完整性。其實這里說的一致性,如果原子性保證了,mysql的數據庫的數據就會更新成功,失敗則回滾到原來的狀態,所以一致性其實是基于事務的原子性和持久性下,一致性就自然而然就得到了保證。
1.事務執行成功,redo日志和binlog日志就是持久性保障2.事務執行失敗則, undo log則是事務原子性的保障,他擔負這回滾的任務。
隔離性:數據庫系統提供一定的隔離機制,保證事務在不受外部并發操作影響的“獨立”環境執行。隔離性則是多事務并行操作下,保證各個事務之間獨立運行相互隔離的,不受其他事務影響的特性。持久性:事務完成之后,它對于數據的修改是永久性的,它是原子性和一致性保證的前提下。
數據庫隔離級別
????????Mysql-innodb可以通過設置mysql的事務隔離級別,全局修改,修改mysql.ini配置文件,在最后加上transaction-isolation = REPEATABLE-READ,#可選參數有:讀未提交READ-UNCOMMITTED,讀已提交:READ-COMMITTED, 可重復讀:REPEATABLE-READ, 串行化:SERIALIZABLE
1.讀未提交:就是在并發事務中,可以讀到沒有提交的事務變更數據;2.讀已提交:讀到已經提交的事務變更記錄;3.可重復讀:mysql的innodb默認的事務隔離級別,每次查詢一條記錄的時候,每個事務都會創建不同的讀視圖read-view,所以在該事務下,都會讀對應的視圖,如果有三個事務,每一個事務都有自己讀到的最新數據的視圖,所以在事務中,每次讀到的都是一開始數據的快照版本,這就是mysql的多版本并發控制,下面會詳細介紹mysql的MVCC。4.串行化:是最高的事務隔離級別,沒開啟一個事務,都是串行的,每一個事務都會對相應的數據行加鎖來保證串行,這樣一個事務結束,才能開啟下一個事務,這樣就完全保證了事務直接的隔離性。一般情況下并不會設置該隔離級別。
為什么要有可重讀的隔離級別
????????我們知道數據庫操作的時候,它是不斷更新的,如果說我一個事務,開始執行的時候,我只想用到當前已有記錄,不管是否已經更新,或者追加 或者減少,我都希望我當前操作是我事務開始的快照,不管是否發生變化,這樣,可重復讀就可以滿足我們的需求,不管我是查詢,還是更新,刪除 已提交的事務,我都不喜歡看到原來的數據有變化。這就是實際開發中,我們為了防止出現幻讀的情況。
可重復讀的實現
????????上面說了,可重復讀隔離級別下,數據庫會為我們創建相應的read-view快照,事務中的所有操作都會基于這個快照版本。還有mysql實現了MVCC的并發訪問控制的機制,那么什么是MVCC呢?首先這里我選擇直接查看官方文檔,這樣理解起來是最原始的資料,以免自己陷入不同的blog解說版本,可能不利于自己分析問題。
[Mysql5.5官方開發文檔中MVCC解釋]
1.介紹
??????? nnoDB是一個多版本存儲引擎:它保存有關已更改行的舊版本的信息,以支持并發和回滾等事務功能。此信息存儲在表空間中稱為回滾段的數據結構中(在Oracle中的類似數據結構之后)。InnoDB使用回滾段中的信息來執行事務回滾中所需的撤消操作。 它還使用該信息構建行的早期版本以進行一致讀取。
2.MVCC多版本的實現方案
??????? InnoDB為存儲在數據庫中的每一行添加三個字段。6字節的DB_TRX_ID字段指示插入或更新該行的最后一個事務的事務標識符 。此外,刪除在內部被視為更新,其中行中的特殊位被設置為將其標記為已刪除 每行還包含一個7字節的DB_ROLL_PTR字段,稱為滾動指針。 roll指針指向寫入回滾段的撤消日志記錄。如果更新了行,則撤消日志記錄包含在更新行之前重建行內容所需的信息。6字節的DB_ROW_ID字段包含在插入新行時單調增加的行ID。 如果InnoDB自動生成聚簇索引,則索引包含行ID值。否則,DB_ROW_ID列不會出現在任何索引中。
DATA_TRX_ID 標記了最新更新這條行記錄的transaction id,每處理一個事務,其值自動+1DATA_ROLL_PTR 指向當前記錄項的rollback segment的undo log記錄,找之前版本的數據就是通過這個指針DB_ROW_ID,當由innodb自動產生聚集索引時,聚集索引包括這個DB_ROW_ID的值,否則聚集索引中不包括這個值.,這個用于索引當中DELETE BIT位用于標識該記錄是否被刪除,這里的不是真正的刪除數據,而是標志出來的刪除。真正意義的刪除是在commit的時候。這個字段 在官方文檔中沒有,但是很多博客中有出現,可能是在5.5之后的版本才加上的。
3.undo日志如何產生和銷毀:
????????回滾段中的undo log分為插入和更新撤消日志。 只在事務回滾中才需要插入undo日志,并且可以在事務提交后立即丟棄。更新undo log也用于一致性讀取,但只有在InnoDB沒有分配快照的事務之后才能丟棄它們,在一致讀取中可能需要更新撤消日志中的信息來構建早期版本的 數據庫行。
4.長事務問題
????????按時提交你的事務,包括那些只發出一致讀取的事務。 否則,InnoDB無法丟棄更新撤消日志中的數據,并且回滾段可能會變得太大,從而填滿了表空間。回滾段中撤消日志記錄的物理大小通常小于相應的插入或更新行。 您可以使用此信息計算回滾段所需的空間。這個問題,也就說明了我們盡量不要使用長事務,長時間不提交,導致回滾段日志變得很大,導致mysql數據庫不可用。
5.刪除記錄時,MVCC的實現機制
????????在InnoDB多版本控制方案中,當您使用SQL語句刪除行時,不會立即從數據庫中物理刪除該行。InnoDB在丟棄為刪除寫入的更新undo log記錄時,僅物理刪除相應的行及其索引記錄。此刪除操作稱為清除,并且速度非常快,通常與執行刪除的SQL語句的時間順序相同。
高性能Mysql
????????下面是《高性能Mysql》中尋找一下MVCC的相關解釋,發現和官方版本就是并不一致,它是以更加簡化的思路來闡述MVCC的版本控制,我們也可以解讀一下。
1.mvcc是行級鎖的一個變種,它為了避免直接加鎖,性能更好,2.實現是通過保存數據某個時間點的快照3.innodb中的MVCC通過在每行的記錄后面保存兩個隱藏的列來實現的,(1).一個是保存創建行的系統創建版本號,每開啟一個事務,該版本號就會自增,這系統版本號作為事務的版本號,用來查詢和定位多事務的隔離版本(2).另一個字段就是行的過期時間或者刪除時間。備注:這里隱藏的列其實和官方開發文檔dev中的描述有相似的地方,作者這里只是簡單描述MVCC的工作原理,所以具體的我們還是以官方文檔為準。4.MVCC只會在可重復讀和讀提交的隔離級別下工作,因為讀未提交的數據就是讀的最新的數據行,串行化是通過加鎖。
樂觀鎖和MVCC 是一件事嗎?
????????通過上面的分析,我們是否有一種錯覺,MVCC不就是實現的樂觀鎖的功能嗎,我們是不是開發的時候不需要再考慮Mysql的樂觀鎖問題。一般的我們在并發中,涉及到更新操作時,都會再where條件加上對應的版本信息(比如時間戳,具體的變更字段狀態等),這里最好還是使用時間戳,比較好,因為我們系統數據設計的時候都會有modifyDate字段,狀態或者其他值,可能存在ABA問題,當然幾率很小。這就是我們樂觀鎖的實現。上面說到MVCC,每次事務都會有MVCC保證可重復讀,并且有隱藏的版本控制,我們是不是就可以不用樂觀鎖了呢?這里,我有必要說一下,雖然MVCC有樂觀并發控制的意思,它只是控制了事務中該記錄的版本,然后事務讀到始終是快照版本而已,并沒有做事務提交時版本的判斷,所以我們還是要手動的進行樂觀鎖的判斷。并且拿到更新int結果為1,或者是預期值時才認為更新成功,否則需要做回滾。
小結
????????今天學習了mysql的ACID的實現原理,和事務隔離級別中的可重復讀的實現機制MVCC,加深了事務的理解,如果上述闡述的有問題,或者不對的地方,歡迎留言指正和討論。
微信公眾號:MyClass社區
如有問題或建議,請公眾號留言。
喜歡請關注
總結
以上是生活随笔為你收集整理的mininet编程实现交换机规则的插入、删除与修改。_Mysql事务隔离以及MVCC实现原理...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: maxwell中文汉化补丁_《我的世界:
- 下一篇: linux cmake编译源码,linu