SQL的事務( 二 )

執行完成,改動的數據的還處在內存中,并沒有刷寫到磁盤,此時稱為事務處在部分提交的狀態 。

  • 失敗的(failed):
    當事務處于活動的或者部分提交的狀態時 , 可能遇到某些錯誤(數據庫自身錯誤、操作系統錯誤、斷電等)而無法繼續執行,或人為的停止事務的執行,稱為事務處于失敗的狀態 。
  • 中止的(aborted):
    如果事務執行了一部分而變為失敗的狀態,那么就需要將修改過的事務的操作還原(就是回滾操作),還原完成后,事務就出在了中止的狀態 。
  • 提交的(committed):
    處于部分提交的狀態的事務將修改過的數據刷寫到磁盤后 , 稱為事務處在提交的狀態 。五、事務的隔離級別
  • 事務的隔離級別的出現 , 就是為了解決ACID中的 I(isolation 隔離性)在并發環境下,同時被操作的數據的隔離問題,同前面所述例子:
    比如事務A把余額從0改成100了,此時事務A還沒有commit,而事務B進來讀取余額了,此時結果是0還是100?
    以MySQL為例,MySQL是一個客戶端/服務端架構的軟件,對于同一個服務器來說,可以由若干個客戶端與之連接,每個客戶端與服務端連接上之后,稱為一個會話(Session) 。每個客戶端都可以在自己的會話中向服務器發出請求語句,而請求語句可以是某個事務的一部分 。對于服務器來說可以同時處理多個事務,但又要滿足隔離性的特性 , 理論上在某個事務對某個數據進行訪問時 , 其它事務應該進行排隊 , 直到該事務提交之后 , 其它事務才能繼續訪問這個數據(類比Java多線程鎖機制) , 但這樣性能影響太大 。如果既要保持事務的隔離性,又想讓服務器在處理訪問同一數據的多個事務的性能盡可能高,這時候就看二者如何權衡取舍了 。
    5.1 準備數據創建一張表及數據
    CREATE TABLE student (    no INT,    name VARCHAR(20),    age INT,    PRIMARY KEY (no)) Engine=InnoDB;INSERT INTO student VALUES(1, '小明', 18);確認數據正常:
    mysql> SELECT * FROM student;+----+--------+------+| no | name   | age  |+----+--------+------+|  1 | 小明   |   18 |+----+--------+------+1 row in set (0.00 sec)5.2 數據并發問題在并發情況下,如果不保證串行執行(就是一個接一個執行),那么會出現以下幾種問題:
    1. 臟寫(Dirty Write)對于兩個事務 Session A、Session B,如果 Session A修改了 Session B 修改過還未提交的數據,就意味著發生了臟寫 。
    臟寫示意圖
    發生時間編號Session ASession B①BEGIN;

    BEGIN;③
    UPDATE student SET name = '李四'  WHERE no = 1;④UPDATE student SET name = '張三'  WHERE no = 1;
    ⑤COMMIT;

    ROLLBACK;已知表中僅有一條no為1、name為小明的記錄 。
    Session A 與 Session B 各自開啟自己的事務,Session B 的事務先將no為1的記錄修改name列的值為李四,然后這條記錄緊接著又 Session A 給改成了張三,并且Session A 還 COMMIT 了,按理來說此時張三就應該永久刷寫到磁盤了 , 但接著Session B 將它的事務回滾了 , 對于這記錄的修改全部撤回,即no為1的記錄的name列的值為小明 。那對于 Session A 來說就有問題了,明明update且commit了,最后一看什么變化都沒有,這是無法被容忍的問題,所以在標準SQL中的四種隔離級別中都解決了臟寫的問題(就是沒法復現了) 。
    2. 臟讀(Dirty Read)對于兩個事務 Session A、Session B,如果 Session A讀取了 Session B 修改過還未提交的數據 , 之后 Session B 回滾,則 Session A 讀到的數據就是臨時且無效的 。
    臟讀示意圖
    發生時間編號Session ASession B①BEGIN;

    BEGIN;③
    UPDATE student SET name = '李四'  WHERE no = 1;④SELECR * FROM student  WHERE no = 1; (如果此時讀出來是李四,而不是小明

    推薦閱讀