MySQL(十三)之MySQL事務

來源:互聯網
上載者:User

標籤:不一致   服務   start   delete   禁用   情況   執行個體   1.2   multi   

前言

  這段時間自己會把之前學的東西都總結一遍,希望對自己以後的工作中有協助。其實現在每天的狀態都是很累的,但是我要堅持!

  進入我們今天的正題:

  為什麼MySQL要 有事務呢?事務到底是用來幹什麼的?我們通過一個例子來說明:

  事務廣泛的運用於訂單系統、銀行系統等多種情境。如果有以下一個情境:A使用者和B使用者是銀行的儲戶。現在A要給B轉賬500元。那麼需要做以下幾件事:

    1)檢查A的賬戶餘額>500元;
    2)A賬戶扣除500元;
    3)賬戶增加500元;

  正常的流程走下來,A賬戶扣了500,B賬戶加了500,皆大歡喜。那如果A賬戶扣了錢之後,系統出故障了呢?A白白損失了500,而B也沒有收到本該屬於他的500。

  以上的案例中,隱藏著一個前提條件:A扣錢和B加錢,要麼同時成功,要麼同時失敗。事務的需求就在於此!

一、MySQL事務概述1.1、MySQL事務簡介

  MySQL事務是訪問並更新資料庫中各種資料項目的一個程式執行單元。在事務中的操作,要麼都執行修改,要麼都不執行,這就是事務的目的,也是事務模型區別於檔案系統的重要特徵之一。

  MySQL事務主要用於處理操作量大,複雜度高的資料。比如說,在員工管理系統中,刪除一個員工,既需要刪除員工的基本資料,也要刪除和該員工相關的其他資訊。這些資料庫動作陳述式就構成一個事務。

  在MySQL中只有使用了InnoDB資料庫引擎的資料庫或者表才支援事務。

  交易處理可以用來維護資料庫的完整性,保證成批的 SQL 陳述式要麼全部執行,要麼全部不執行。

  事務用來管理 insert,update,delete 語句

1.2、事務的四大特性(ACID特性)

  嚴格上來說,事務必須同時滿足4個特性,即通常所說事務的ACID特性。雖然理論上定義了嚴格的事務要求,但是資料庫廠商出於各種目的並沒有嚴格滿足事務的ACID標準。

  例如,對於MYSQL的NDB Cluster引擎,雖然支援事務,但是不滿足D的要求,即持久性的要求。對於Oracle資料庫來說,其預設的交易隔離等級為READ COMMITTED,不滿足I的要求,即隔離性的要求。

  對於InnoDB儲存引擎而言,預設的交易隔離等級是READ REPRATABLE,完全遵循和滿足事務的ACID特性。

  1)原子性(Atomicity):指事務包含的所有操作要麼全部成功,要麼全部失敗復原,因此事務的操作如果成功就必須要完全應用到資料庫,如果操作失敗則不能對資料庫有任何影響。

  2)一致性(Consistency):指事務必須使資料庫從一個一致性狀態變換到另一個一致性狀態,也就是說一個事務執行之前和執行之後都必須處於一致性狀態。

    (例如:拿轉賬來說,假設使用者A和使用者B兩者的錢加起來一共是5000,那麼不管A和B之間如何轉賬,轉幾次賬,事務結束後兩個使用者的錢相加起來應該還得是5000,這就是事務的一致性。)

  3)隔離性(Isolation):指當多個使用者並發訪問資料庫操作同一張表時,資料庫為每一個使用者開啟的事務,不能被其他事務的操作所幹擾,多個並發事務之間要相互隔離。

  4)持久性(Durability):指一個事務一旦被提交了,那麼對資料庫中的資料的改變就是永久性的,即便是在資料庫系統遇到故障的情況下也不會丟失提交事務的操作。

  注意:事務的(ACID)特性是由關聯式資料庫管理系統(RDBMS,資料庫系統)來實現的。資料庫管理系統採用日誌來保證事務的原子性、一致性和持久性。日誌記錄了事務對資料庫所做的更新,

     如果某個事務在執行過程中發生錯誤,就可以根據日誌,撤銷事務對資料庫已做的更新,使資料庫退回到執行事務前的初始狀態。資料庫管理系統採用鎖機制來實現事務的隔離性。

     當多個事務同時更新資料庫中相同的資料時,只允許持有鎖的事務能更新該資料,其他事務必須等待,直到前一個事務釋放了鎖,其他事務才有機會更新該資料。

1.3、事務分類

  扁平事務:最簡單,使用最頻繁的事務。在扁平事務中,所有的操作都處於一個層次,其有BEGIN WORK開始,有COMMIT WORK或ROLLBACK WORK結束。處於之間的操作是原子的,要麼全部執行,要麼全部復原。

  帶有儲存點的扁平事務:除了扁平事務支援的操作外,允許在事務執行過程中復原到同一事務中較早的一個狀態,這是因為可能有些事務在執行過程中出現的錯誤並不會對有的操作都無效,

            放棄整個事務不合乎要求,開銷也太大。儲存點用來通知系統應該記住事務當前的狀態,以便以後發生錯誤時,事務能回到該狀態。

  鏈事務:可視為儲存點模式的一個變種。

  嵌套事務:一個階層架構。

  分散式交易

二、事務控制語句

  在MYSQL命令列的預設設定下,事務都是自動認可的,即執行SQL語句後就會馬上執行COMMIT操作。

  因此要顯示的開啟一個事務必須使用命令BEGIN和START TRANSACTION,或者執行命令SET AUTOCOMMIT = 0,以禁用當前會話的自動認可。

  1)START TRANSACTION | BEGIN

    顯示的開啟一個事務。在預存程序中,MYSQL資料庫的分析器會自動將BEGIN識別為BEGIN...END,因此在預存程序中只能使用START TRANSACTION語句來開啟一個事務。

  2)COMMIT

    要想使用這個語句的最簡形式,只需發出COMMIT。COMMIT會提交事務,並使已對資料庫進行的所有修改成為永久性的。COMMIT和COMMIT WORK語句基本上是一致的,都是用來提交事務。

    不同的是COMMIT WORK用來控制事務結束後的行為是CHAIN還是RELEASE的。如果是CHAIN方式,那麼事務就變成了鏈事務。使用者可以通過參數completion_type來進行控制,預設該參數是0,表示沒有任何操作。

    在這種設定下,COMMIT和COMMIT WORK是完全等價的。當參數值為1時,COMMIT WORK等價於COMMIT AND CHAIN,表示馬上自動開啟一個相同隔離等級的事務。

    當參數值為1時,COMMIT WORK等價於COMMIT AND RELEASE。當提交事務後會自動斷開與伺服器串連。

  3)ROLLBACK

    復原會結束使用者的事務,並撤銷進行中的所有未提交的修改。

  4)SAVEPOINT identifiter

    SAVEPOINT允許使用者在事務中建立一個儲存點,一個事務可以有很多個儲存點。

  5)RELEASE SAVEPOINT identifier

    刪除一個事務的儲存點,當沒有一個儲存點執行這語句時,會拋出一個異常。

  6)ROLLBACK to [SAVEPOINT] identifier

    這個語句與SAVEPOINT命令一起使用。可以把交易回復到標記點,而不復原到此標記點之前的任何工作。

    注意:雖然有ROLLBACK,但是它並沒有真正的結束一個事務,因此即使執行了ROLLBACK TO SAVEPOINT,之後也需要顯示的運行COMMIT或ROLLBACK命令。

  7)SET TRANSACTION

    這個語句用來設定事務的隔離等級。InnoDB儲存引擎提供的交易隔離等級有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。

三、MySQL交易處理的兩種方法

1)用 BEGIN,ROLLBACK,COMMIT來實現

  BEGIN 開始一個事務

  ROLLBACK 交易回復

  COMMIT 事務確認

2)直接用SET來改變MySQL的自動認可模式

  SET AUTOCOMMIT=0 禁止自動認可

  SET AUTOCOMMIT=1 開啟自動認可

四、MySQL中事務的隔離等級4.1、在MySQL中如果不考慮事務的隔離性,會發生的幾個問題

  1)髒讀

  指在一個交易處理過程裡讀取了另一個未提交的事務中的資料。

  當一個事務正在多次修改某個資料,而在這個事務中這多次的修改都還未提交,這時一個並發的事務來訪問該資料,就會造成兩個事務得到的資料不一致。

  舉例:

    使用者A向使用者B轉賬100元,對應SQL命令如下:

    update account set money=money+100 where name=’B’;(此時A通知B)

    update account set money=money-100 where name=’A’;

    當只執行第一條SQL時,A通知B查看賬戶,B發現確實錢已到賬(此時即發生了髒讀),而之後無論第二條SQL是否執行,只要該事務不提交,則所有操作都將復原,那麼當B以後再次查看賬戶時就會發現錢其實並沒有轉。 

  2)不可重複讀取

  指在對於資料庫中的某個資料,一個事務範圍內多次查詢卻返回了不同的資料值,這是由於在查詢的時候,被另一個事務修改並提交了。

  舉例:

    事務T1在讀取某一資料,而事務T2立馬修改了這個資料並且提交事務給資料庫,事務T1再次讀取該資料就得到了不同的結果,發送了不可重複讀取。

  不可重複讀取和髒讀的區別是,髒讀是某一事務讀取了另一個事務未提交的髒資料,而不可重複讀取則是讀取了前一事務提交的資料。

  在某些情況下,不可重複讀取並不是問題,比如我們多次查詢某個資料當然以最後查詢得到的結果為主。但在另一些情況下就有可能發生問題,例如對於同一個資料A和B依次查詢就可能不同,A和B就可能打起來了。 

  3)虛讀(幻讀)

  幻讀是事務非獨立執行時發生的一種現象。

  舉例:

    事務T1對一個表中所有的行的某個資料項目做了從“1”修改為“2”的操作,這時事務T2又對這個表中插入了一行資料項目,而這個資料項目的數值還是為“1”並且提交給資料庫。

    而操作事務T1的使用者如果再查看剛剛修改的資料,會發現還有一行沒有修改,其實這行是從事務T2中添加的,就好像產生幻覺一樣,這就是發生了幻讀。

  幻讀和不可重複讀取都是讀取了另一條已經提交的事務(這點就髒讀不同),所不同的是不可重複讀取查詢的都是同一個資料項目,而幻讀針對的是一批資料整體(比如資料的個數)。

4.2、MySQL資料庫的四種隔離界別

   InnoDB儲存引擎提供事務的隔離等級有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。       

  1)Serializable (序列化):可避免髒讀、不可重複讀取、幻讀的發生。

    它通過強制事務串列執行,避免了前面說的幻讀的問題。
  2)Repeatable read (可重複讀):可避免髒讀、不可重複讀取的發生。

    解決了髒讀,也保證了在同一個事務中多次讀取同樣記錄的結果是一致的。但是理論上,可重讀讀隔離等級還是無法解決另外一個幻讀的問題,

    指的是當某個事務在讀取某個範圍內的記錄時,另外一個事務也在該範圍插入入了新的記錄,當之前的事務再次讀取該範圍內的記錄時,會產生幻行。
  3)Read committed (讀已提交):可避免髒讀的發生。

    一個事務從開始直到提交之前,所做的任何修改對其他事務都是不可見的。

    這個層級有時候也叫做不可重複讀取,因為兩次執行相同的查詢,可能會得到不一樣的結果。因為在這2次讀之間可能有其他事務更改這個資料,每次讀到的資料都是已經提交的。
  4)Read uncommitted (讀未提交):最低層級,任何情況都無法保證

    事務中的修改,即使沒有提交,在其他事務也都是可見的。事務可以讀取未提交的資料,這也被稱為髒讀。

  分析:

    1)以上四種隔離等級最高的是Serializable層級,最低的是Read uncommitted層級,當然層級越高,執行效率就越低。像Serializable這樣的層級,

     就是以鎖表的方式(類似於Java多線程中的鎖)使得其他的線程只能在鎖外等待,所以平時選用何種隔離等級應該根據實際情況。在MySQL資料庫中預設的隔離等級為Repeatable read (可重複讀)。

    2)在MySQL資料庫中,支援上面四種隔離等級,預設的為Repeatable read (可重複讀)。

     而在Oracle資料庫中,只支援Serializable (序列化)層級和Read committed (讀已提交)這兩種層級,其中預設的為Read committed層級。

    3)Repeatable read是MySQL的預設交易隔離等級,它確保同一事務的多個執行個體在並發讀取資料時,會看到同樣的資料行。

     不過理論上,這會導致另一個棘手的問題:幻讀 (Phantom Read)。簡單的說,幻讀指當使用者讀取某一範圍的資料行時,另一個事務又在該範圍插入入了新行,

     當使用者再讀取該範圍的資料行時,會發現有新的“幻影” 行。InnoDB和Falcon儲存引擎通過多版本並發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。

    4)在MySQL資料庫中查看當前事務的隔離等級:select @@tx_isolation;

    5)在MySQL資料庫中設定事務的隔離等級:

      set [glogal|session] transaction isolation level 隔離等級名稱;
        set tx_isolation=’隔離等級名稱’;

     如果想啟動時就設定事務的預設隔離等級,修改MYSQL的設定檔,在[mysqld]中添加如下行:

      [mysqld]

        transaction-isolation = READ-COMMITTED

     注意:設定資料庫的隔離等級一定要是在開啟事務之前!  

   

MySQL(十三)之MySQL事務

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.