MySQL事務(transaction)的四大特性ACID、隔離性問題及隔離級別

1.事務的四大特性(ACID)

原子性(atomicity):一個事務是不可分割的工作單位,事務中的操作要麼一起發生,要麼一起不發生

一致性(consistency):事務前後的數據必須保持一致

隔離性(isolation):多個事務之間數據要相互隔離

持久性(durability):事務一旦被提交,改變是永久性的

2.隔離性問題

2.1隔離性分析

  • 隔離性問題本質上就是多線程的併發安全問題
  • 如果兩個線程併發修改,必然會產生多線程安全問題,必須隔離
  • 如果兩個線程併發查詢,必然沒有問題,不需要隔離
  • 如果一個線程修改,一個線程查詢,在不同的應用場景下可能有問題,也可能沒問題

2.2隔離性可能造成的問題

髒讀(dirty reads):一個事務讀取到另一個事務未提交的數據

實現髒讀過程:

1.打開兩個窗口,因爲SESSION表示的是當前窗口有效,所以窗口1和窗口2都要先執行下面語句,將隔離級別設置爲最低

set session transaction isolation level read uncommitted;

2. 執行窗口1中圈住的語句

3.執行完窗口1中的語句後回到窗口2中開啓事務並執行查詢,此時窗口2中的數據查詢a用戶已經被扣款100,b用戶賬戶已經被增加100(因爲窗口1還未完成提交,但是允許查詢,故出現了髒讀)

 

4.執行窗口1的回滾操作

5.回到窗口2中繼續查詢數據,此時展示的值就是窗口一回滾後的值

2.不可重複度(non-repeatable reads) :一個事務多次讀取同一條數據,多次查詢結果不同

測試方法類似於髒讀(此處不再贅述)

窗口1:

start transaction;

select * from user where name='a';

窗口2:

start transaction;

update user set money=money-100 where name='a';

commit;

窗口1:

/#兩次查詢結果不同

select * from user where name='a';

commit;

3.虛讀/幻讀(phantom reads ):出現概率很低,一個事務多次查詢整表數據,查詢到的結果不同

測試方法類似於髒讀(此處不再贅述)

窗口1:

start transaction;

select sum(money) from user;

窗口2:

start transaction;

insert into user values(3,'c',5000);

commit;

窗口1:
#兩次查詢結果不同

select sum(money) from user; 

commit;

3.隔離級別

數據庫針對不同場景需求設計了不同的隔離級別

  • read uncommitted:不做任何隔離,可能造成髒讀、不可重複讀、虛讀(幻讀)問題
  • read committed:可以防止髒讀,但是不能防止不可重複讀、虛讀(幻讀)問題
  • repeatable read:可以防止髒讀、不可重複讀,但是不能防止虛讀(幻讀)問題
  • serializable:可以防止所有隔離性問題,但是數據庫被設計爲串行化的數據庫,性能很低

安全性:serializable>repeatable read>read committed>read uncommitted

效率:read uncommitted>read committed>repeatable read>serializable

MySQL默認隔離級別:repeatable read

Oracle默認隔離級別:read committed

操作隔離級別

查詢數據庫的隔離級別

select @@tx_isolation;

修改隔離級別

set [session/global] transaction isolation level xxx;

不寫默認爲session,表示只修改當前客戶端的隔離級別,不影響其他客戶端

如果設置爲global,表示修改數據庫默認的隔離級別,但是當前窗口無效

例如:set session transaction isolation level serializable;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章