天天看點

事務的隔離性

1、事務隔離級别

     事務有四大特性:原子性、一緻性、隔離性、持久性。其中事務的隔離比較重要,事務隔離性處理在資料并發量較大的系統顯得比較重要。

     資料庫在事務隔離這塊提供了四種事務隔離級别,分别是:讀取未送出内容(Read Uncommitted),讀取已送出内容(Read Committed),可重讀(Repeatable Read),串行化(serializable)。

  不同的資料庫關于事務隔離的預設級别不同,Oracle資料庫預設的隔離級别為Read Committed, MySql的預設隔離之别則為Repeatable Read;

2、事務隔離級别對應産生的問題

     為什麼不同的資料庫采用了不同的預設隔離級别?因為不同的隔離級别在并發操作資料庫時會産生不同的問題。 也就是由隔離級出現對應的問題:髒讀、不可重複讀及幻讀。

  先了解這幾個問題的概念及産生。引用自:MySql事務隔離詳解  

     (1) 髒讀:在事務并發處理過程中,某一事務讀取了另一個事務未送出的資料。如事務A讀取到了事務B修改過的資料,但事務B未進行送出。

時間點 事務A 事務B
1 select t.money  from t_account t where t.name='scl'
2 update t_account t set t.money = t.money+1000 where t.name = 'scl'
3 select t.money from t_account t where t.name = 'scl'
4 commit

    假如 在兩事務A、B 都未執行前,scl賬号有1000元, 在事務開始後,如果事務A第一次讀取到的資料為1000,第二次讀到的資料為2000。那麼這就出現了髒讀。因為在兩個不同僚務裡面應該是互相獨立的。不應該讀到其他事務的資料。

  (2)  不可重複讀:在事務并發處理過程中,事務A在某時間點1内讀到的資料跟時間點2讀到的資料不一緻。跟髒讀的差別是,事務A先進行查詢,然後事務B送出了某一行記錄的修改,事務A再次查詢資料發現兩次讀出來的資料不一緻。(事務A讀取了事務B送出的内容,兩次查詢某一行或幾行資料内容不一緻)

commit;
 select t.money from t_account t where t.name = 'scl'

         假如 在兩事務A、B 都未執行前,scl賬号有1000元, 在事務開始後,如果事務A第一次讀取到的資料為1000,第二次讀到的資料為2000。那麼這就出現了不可重複讀。因為在      兩個不同僚務裡面應該是互相獨立的。A讀到了B送出的事務,導緻兩次讀取結果内容不一緻。

    (3)  幻讀:某事務A進行a表資料查詢,然後事務B在a表内插入了一些新資料并且送出,事務A兩次查詢的資料條數存在差異。 與不可重複讀得差別是資料條數增加了。

select *  from t_account t  

insert into t_account values ("1000","張三",2000);

insert into t_account values ("1000","李四",3000);

insert into t_account values ("1000","王五",4000);

insert into t_account values ("1000","錢六",6000);

           假如 在兩事務A、B 都未執行前,使用sql:select * from t_account 傳回的是3條資料,在兩事務開啟後,事務A第一次讀取到3條資料,在事務B送出後,事務A讀取到了7條資料,那麼久出現了幻讀現象。

3、事務隔離級别應對事務并發産生的問題

  既然事務隔離級别不同會導緻事務并發産生問題,那麼四個事務隔離級别分别會産生什麼問題?在開發時應選擇什麼哪個隔離級别方式?

隔離級别 髒讀 不可重複讀 幻讀
讀取未送出内容(Read Uncommitted)   √        √  √
讀取已送出内容(Read Committed)   X
可重讀(Repeatable Read)        X
串行化(serializable)  X

        可重讀這個隔離級别有可能會出現幻讀,有可能不出現。取決于資料庫當時的實作。

4、事務隔離級别的查詢與修改

   Mysql事務隔離有全局事務,會話事務之分。可以通過以下指令查詢Mysql裡面事務的隔離級别:

         1.SELECT @@global.tx_isolation; 

         2.SELECT @@session.tx_isolation;

         3.SELECT @@tx_isolation;

session 指的是目前連接配接的事務級别,global則是全局的隔離級别。應該使用gobal來設定全局事務隔離級别。并進行相關的測試。
 
   修改事務隔離級别使用指令:set tx_isolation='read-committed';
   或者完整的事務隔離更改方法: set global transaction isolation level READ COMMITTED;


        
事務的隔離性
需要注意的是:即使使用了全局事務隔離級别設定,但開啟的視窗可能有session級别的緩存,把查詢視窗關閉再進行一次查詢即可确認事務級别是 否正确修改。(在64位Mysql5.5下測試過,無法在已開視窗下正确查詢事務隔離級别)
事務的隔離性
以上為本人對Mysql事務隔離級别的學習總結,如有錯誤,煩請指出糾正。      

繼續閱讀