?關系型數據庫都具有一套事務級別,以前的開發和學習過程我很少關注過這個概念,今天搜集了一些資料,在
結合spring聲明式事務學習的同時,總結一下數據庫的事務級別與操作。
READ-UNCOMMITTED: 未提交讀 會出現臟讀、不可重復讀、幻讀 ( 隔離級別最低,并發性能高 )
READ-COMMITTED: 提交讀 會出現不可重復讀、幻讀問題(鎖定正在讀取的行)
REPEATABLE-READ: 可重復讀 會出幻讀(鎖定所讀取的所有行)
SERIALIZABLE: 序列化 保證所有的情況不會發生(鎖表)
詳細說明:
未提交讀——這通常稱為 'dirty read':non-locking SELECT 的執行使我們不會看到一個記錄的可能更早的版本;
因而在這個隔離級別下是非 'consistent' reads;這級隔離級別的運作如同 READ COMMITTED。處于這個隔離級的
事務可以讀到其他事務還沒有提交的數據。如果這個事務使用其他事務未提交的變化作為計算的基礎,然后那些未
提交的變化被他們的父事務撤銷,則會導致誤差。
提交讀——在一個事務中已經COMMIT的數據可以在其他事務中看到。如果這個事務頻繁提交的話,其他的大的查詢
事務中可能會得到多個不同的結果。
可重復讀——這是 InnoDB 默認的事務隔離級。在一個事務中所有讀都是連續的。
序列化——提供最大程度的隔離,如果每個事務都以這種隔離級運行就會影響Mysql的性能,因為需要大量的資源來
使大量事務在任一時刻不被看到。如果一個事務在執行一個SELECT操作,另外的事務不允許執行UPDATE操作,這個
隔離級別下的SELECT操作被陰式地轉換為 SELECT ... LOCK IN SHARE MODE。
不可重復讀的重點是修改 :?
同樣的條件 ,?? 你讀取過的數據 ,?? 再次讀取出來發現值不一樣了?
幻讀的重點在于新增或者刪除?
同樣的條件 ,?? 第 1 次和第 2 次讀出來的記錄數不一樣
MySQL InnoDB存儲引擎的事務隔離級別
查看InnoDB系統級別的事務隔離級別:
以下為引用的內容:?
mysql> SELECT @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set (0.00 sec)
?
查看InnoDB會話級別的事務隔離級別:
以下為引用的內容:?
mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
?
修改事務隔離級別:
以下為引用的內容:?
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
?
InnoDB的可重復讀隔離級別和其他數據庫的可重復讀是有區別的,不會造成幻象讀(phantom read),所謂幻象讀,
就是同一個事務內,多次select,可以讀取到其他session insert并已經commit的數據。下面是一個小的測試,證明
InnoDB的可重復讀隔離級別不會造成幻象讀。測試涉及兩個session,分別為session 1和session 2,隔離級別都是
repeateable read,關閉autocommit
以下為引用的內容:
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> set autocommit=off;
Query OK, 0 rows affected (0.00 sec)
session 1 創建表并插入測試數據
mysql> create table test(i int) engine=innodb;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test values(1);
Query OK, 1 row affected (0.00 sec)
session 2 查詢,沒有數據,正常,session1沒有提交,不允許臟讀
mysql> select * from test;
Empty set (0.00 sec)
session 1 提交事務
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
session 2 查詢,還是沒有數據,沒有產生幻象讀
mysql> select * from test;
Empty set (0.00 sec)
以上試驗版本:
mysql> select version();
+-------------------------+c
| version() |
+-------------------------+
| 5.0.37-community-nt-log |
+-------------------------+
1 row in set (0.00 sec)
?
spring的聲明式事務的隔離級別與數據庫的如出一轍,共5種級別:
1.?ISOLATION_DEFAULT: 這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別.
????? 另外四個與JDBC的隔離級別相對應
?2.?ISOLATION_READ_UNCOMMITTED: 這是事務最低的隔離級別,它充許令外一個事務可以看到這個事務未提交的數據。
????? 這種隔離級別會產生臟讀,不可重復讀和幻像讀。
?3.?ISOLATION_READ_COMMITTED: 保證一個事務修改的數據提交后才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的數據
?4.?ISOLATION_REPEATABLE_READ: 這種事務隔離級別可以防止臟讀,不可重復讀。但是可能出現幻像讀。
????? 它除了保證一個事務不能讀取另一個事務未提交的數據外,還保證了避免下面的情況產生(不可重復讀)。
?5.?ISOLATION_SERIALIZABLE?這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。
????? 除了防止臟讀,不可重復讀外,還避免了幻像讀。 ?
本文轉自施楊博客園博客,原文鏈接:http://www.cnblogs.com/shiyangxt/archive/2009/02/11/1388519.html,如需轉載請自行聯系原作者???