1. 程式人生 > >mysql事務回滾機制概述

mysql事務回滾機制概述

應用場景:
   銀行取錢,從ATM機取錢,分為以下幾個步驟
       1 登陸ATM機,輸入密碼;
    2 連線資料庫,驗證密碼;
    3 驗證成功,獲得使用者資訊,比如存款餘額等;
    4 使用者輸入需要取款的金額,按下確認鍵;
    5 從後臺資料庫中減掉使用者賬戶上的對應金額;
    6 ATM吐出錢;
    7 使用者把錢拿走。
    對於上面的取錢這個事情,如果有一步出現錯誤的話,那麼就會取消整個取錢的動作,但是如果在第5步,系統後臺已經把錢減了,但是ATM機沒有取出來,那麼就應用到mysql中的事務。簡單地
來說,就是取錢這7步要麼都完成,要麼就啥也不做,在資料庫中就是這個道理。


    事務是使用者定義的一個數據庫操作序列,這些操作要麼全做要麼全不做,是一個不可分割的工作單位,事務回滾是指將該事務已經完成的對資料庫的更新操作撤銷,在事務中,每個正確的原子
操作都會被順序執行,直到遇到錯誤的原子操作。回滾的意思其實即使如果之前是插入操作的話,那麼會執行刪除之前插入的記錄,如果是修改操作的話,那麼會執行將update之前的記錄還原。
因此,正確的原子操作是真正被執行過的,是物理執行。

    事務是由一條或者多條sql語句組成,在事務的操作中,要麼這些sql語句都執行,要麼都不執行。

    事務的ACID特性:原子性,一致性,隔離性,永續性。
   
   在當前事務中確實能看到插入的記錄,最後只不過被刪除了,但是auto_increament不會刪除而是改變值


   為什麼auto_increament沒有回滾:因為innodb儲存引擎中的auto_increment就是主鍵的計數記錄的當前值是儲存在記憶體中,並不是存在磁碟中的,當mysql server處於執行的時候,這個計數值只會隨著
insert增長,不會隨著delete減少。而當mysql server啟動的時候,當我們需要查詢auto_increment計數值時,mysql便會自動執行:SELECT MIX(ID) FROM 表名 FOR UPDATE;這條語句來獲得auto_increment
列的最大值,然後將這個值放到auto_increment計數器中,所以ROLLBACK MYSQL的auto_increment計數器也不會做負運算


    事務分為哪些種:扁平事務,帶有儲存點扁平事務,鏈事務,巢狀事務,分散式事務。


    MYSQL中使用事務:
  在MYSQL命令列命令下事務都是自動提交的,即執行Sql語句就會馬上執行COMMIT操作。因此要顯示一個事務的開啟必須使用命令BEGIN或者START TRANSACTION,或者執行命令SET AUTOCOMMIT=0來
禁止當前回話的自動提交


   事務控制語句:
BEGIN/START TRANSACTION:顯示地開啟一個事務
COMMIT:也可以使用COMMIT WORK 兩者是等價的。COMMIT會提交事務,並是已對資料庫進行的所有的修改是永久性的。
ROLLBACK:也可以使用ROLLBACK WORK,兩者也是等價的,回滾會結束使用者的事務,並且會撤銷正在進行的所有未提交的修改。
SAVEPOINT identifier:允許在事務中建立一個儲存點,一個事務中可以有多個SAVEPOINT
release SAVEPOINT identifier:刪除一個事務的儲存點,當沒有制定的儲存點,會丟擲一個異常。 
SET TRANSACTION:用來設定事務的隔離級別。Innodb儲存引擎提供的事務隔離級別有READ UNCOMMITED,READ COMMITED,REPEATABLE READ和SERIALIZABLE.
   
    事務的隔離級別:在資料庫操作中,為了保證併發讀取資料的正確性,提出了隔離級別,如上
  區別如下:
  隔離級別 髒讀(Dirty Read)不可重複讀(NonRepeatable Read)幻讀(Phantom Read)
  未提交讀 read uncommited可能可能 可能
  已提交讀 read commited不可能可能 可能
  可重複讀 repeatable read不可能不可能可能
  可序列化 serializable不可能不可能不可能


   髒讀:一個事務讀取到了另一個事務沒有提交的資料
例如:事務T1更新了一行記錄的內容,但是並沒有提交所做的修改。事務T2讀取到了T1更新後的行,然後T1執行回滾操作,取消了剛才所做的修改。現在T2所讀取的行就無效了


   不可重複讀:在同一事務中,兩次讀取同一資料,得到的內容不同
例如:事務T1讀取一行記錄,緊接著事務T2修改了T1剛才讀取的那一行記錄。然後T1又再次讀取這行記錄,發現與剛才讀取的結果不同。這就稱為“不可重複”讀,因為T1原來讀取的那行記錄已經發生了變化


   幻讀:在同一事務中,用同樣的操作讀取兩次,得到的記錄數不同
例如:事務T1讀取一條指定的WHERE子句所返回的結果集。然後事務T2新插入 一行記錄,這行記錄恰好可以滿足T1所使用的查詢條件中的WHERE子句的條件。然後T1又使用相同的查詢再次對錶進行檢索,
     但是此時卻看到了事務T2剛才插入的新行。這個新行就稱為“幻像”,因為對T1來說這一行就像突然出現的一樣
   
   隔離級別越低,事務請求的瑣越少或者說是保持瑣的時間越短,Innodb儲存引擎預設支援的隔離界別是REPEATALE READ;在這種預設的事務隔離級別下已經能完全保證事務的隔離性。  


   mysql事務回滾怎樣實現的程式碼可以參考此bolg:http://bbs.csdn.net/topics/390876901 

   要同時修改資料庫中兩個不同表時,如果它們不是一個事務的話,當第一個表修改完,可能第二個表修改過程中出現了異常而沒能修改,此時就只有第二個表依舊是未修改之前的狀態,
   而第一個表已經被修改完畢。而當你把它們設定為一個事務的時候,當第一個表修改完,第二表修改出現異常而沒能修改,第一個表和第二個表都要回到未修改的狀態,這就是所謂的事務回滾。