數據庫事務的四大特性

     事務四大特性(簡稱ACID

一、原子性(Atomicity):事務中的所有操做在數據庫中是不可分割的,要麼所有完成,要麼均不執行。mysql

二、一致性(Consistency):幾個並行執行的事務,其執行結果必須與按某一順序串行執行的結果相一致。sql

三、隔離性(Isolation):事務的執行不受其餘事務的干擾,事務執行的中間結果對其餘事務必須是透明的。數據庫

四、持久性(Durability):對於任意已提交事務,系統必須保證該事務對數據庫的改變不被丟失,即便數據庫出現故障。   安全

        數據庫能夠保證原子性,一致性,持久性。可是隔離級別須要根據併發狀況進行設置,將數據庫設計成單線程,能夠防止全部的線程安全問題,天然也就保證了隔離型的問題,可是若是這樣,那麼效率就會極其低下。若是兩個線程併發修改,必定會相互搗亂,這時必須利用鎖機制防止多個線程的併發修改。若是兩個線程併發查詢,沒有線程安全問題。併發


  四大隔離級別oracle

  Read uncommitted:---不防止任何隔離型問題,不能防止髒讀/不可重複讀/幻讀問題。數據庫設計

  Read commit:---能夠防止髒讀問題,可是不能防止 不可重複讀/幻讀問題。(oracle默認隔離級別)spa

  Repeatable read:---能夠防止髒讀/不可重複讀,不能防止幻讀。(mysql默認隔離級別).net

  Serializable:--數據庫被設計爲單線程,能夠防止上述全部問題線程

  髒讀:一個事務讀取到另外一個事務未提交的數據。

  場景:a帳戶1000,b帳戶1000,a到b的網店裏買一百塊錢的鞋子。。。。

  a:start transaction

  update table set money=money-100 where name='a';//a帳戶扣除100

  update table set money=money+100 where name='b';//b帳戶增長100

  此時a尚未提交事務,對b說付款成功

  b:start transaction;//b開始查詢本身的帳戶餘額

  select money form table where name='b';

  b:commit;

  若是讀取到了a沒有提交的數據,那麼b查出來的就會是1100,此時b開始發貨

  此時a執行回滾

  a:rollback;

  那麼b再去查詢帳戶餘額會發現本身的帳戶仍是原先的100塊

 

  不可重複讀:在當前事務中,讀取到了另外一事務提交的更新和刪除的數據。

  場景:若是a有活期資金1000,按期1000,固定資產1000

  a: 1000 1000 1000
  b: 銀行職員,銀行讓職員b算出a客戶的總共資產
  ---------
  b:start transaction;
  select 活期存款 from account where name='a'; ---- 活期存款:1000
  select 按期存款 from account where name='a'; ---- 按期存款:1000
  select 固定資產 from account where name='a'; ---- 固定資產:1000 
    -------此時a客戶取走了本身活期的1000元
    a:
    start transaction;
    update accounset set 活期=活期-1000 where name='a';
    commit;
  -------
  select 活期+按期+固定 from account where name='a'; --- 總資產:2000,按照以前查出來的應該是3000元,可是如今是2000元
  commit;
  ----------

  可是雖然在這種場景下,出現了不可重複讀,可是若是在另外一場景下,若是你和你的夥伴共用一個銀行帳戶共100萬,你的夥伴若是中途取走了50萬,而你此時讀取到剩下的50萬,就符合該場景。

  幻讀:在當前事務中,讀取到了另外一事務提交的插入的數據

  場景:若是銀行如今有a、b兩位客戶存款各1000,銀行老闆讓職員b去算平均每一個客戶的平均存款,而又有新增客戶c存入了4000元。

  a: 1000   b: 1000   d: 銀行業務人員   -----------   d:   start transaction;   select sum(money) from account; --- 2000 元   select count(name) from account; --- 2 個   ------   c: start transaction; insert into account values(c,4000); commit; ------ select sum(money)/count(name) from account; --- 平均:2000元/個,結果應該是平均存款1000,而實際結果確實2000 commit; ------------