前幾天同事講了transaction isolation level,並且大家一起在sqlserver,oracle跟mysql資料庫上實驗了一下,發覺這些知識還是挺重要的。
假如有兩個事務併發,順序如下
transaction a transaction b
begin begin
query1 from table a
....... modify1 to table a(insert/update/delete)
commit
query2 from table a
commit
那麼在事務a中,query1跟query2查詢出來的結果是否一樣呢?這就跟事務隔離級別有關了。
sql的標準定義裡面,一共有四種級別:
read uncommited讀取未提交的資料 就是其他事務求提交的資料,都可以讀取出來
read commited讀取已提交的資料 query2會跟query1讀取的資料不一樣
repeatable read可重複讀取,即query1跟query2讀取的資料是一樣的
serializable 序列化,
sql 標準用三個必須在並行的事務之間避免的現象定義了四個級別的事務隔離。 這些不希望發生的現象是:
髒讀(dirty reads)
乙個事務讀取了另乙個未提交的並行事務寫的資料。
不可重複讀(non-repeatable reads)
乙個事務重新讀取前面讀取過的資料, 發現該資料已經被另乙個已提交的事務修改過。
幻讀(phantom read)
乙個事務重新執行乙個查詢,返回一套符合查詢條件的行, 發現這些行因為其他最近提交的事務而發生了改變。
隔離級別 髒讀(dirty read) 不可重複讀(nonrepeatable read) 幻讀(phantom read)
讀未提交(read uncommitted) 可能 可能 可能
讀已提交(read committed) 不可能 可能 可能
可重複讀(repeatable read) 不可能 不可能 可能
可序列化(serializable ) 不可能 不可能 不可能
sqlserver
我們首先在sqlserver上做了實驗,sqlserver一共支援四種隔離級別,read uncommited跟read commited我們沒有實驗,我們直接先實驗
repeatable read,如果事務a定義了如下級別,那麼當事務b執行到modify1這條語句時,如果modify1是update的話,就被鎖起來,一直等
到事務a提交完以後,鎖才會被釋放,而如果是insert的話,剛可以順利進行下去,然後在事務a中,query2查到的資料,是已經被事務b
修改過的資料,如果將級別定義在serializable的話,則在modify1語句中,update,insert或者delete都會被鎖掉。
也就是說,sqlserver對這些級別的支援,是通過鎖來做到的,雖然可以保證事務正常進行,但是並行的效能卻很差。
oracle
oracle只支援兩個級別,read commited跟serializable,結果這裡就不用詳細說明,實驗的結果是,oracle的serializable是通過版本
控制來完成的,而不是通過鎖機制,這就保證了並行的效能。oracle的預設級別是read commited
mysql
mysqlserver也支援四個級別,而且mysql也是通過版本控制而非鎖機制來完成的。
事務隔離級別
1 serializable 最嚴格的spring事務隔離級別,事務序列執行,資源消耗最大 3 read committed 大多數主流資料庫的預設spring事務隔離等級,保證了乙個事務不會讀到另乙個並行事務已修改但未提交的資料,避免了 髒讀取 該級別適用於大多數系統。4 read uncommi...
事務隔離級別
四種隔離級別 隔離級別 髒 讀不可重複讀取 幻 像讀操作未提交 read uncommitted 是是 是讀操作已提交 read committed 否是 是可重複讀 repeatable read 否否 是快照否否 否可序列讀 serializable 否否 否 sql server 還支援使用行...
事務隔離級別
需要防止的現象和事務隔離級別 ansi iso sql 標準 sql92 定義了四種事務隔離級別 transaction isolation level 這四種隔離級別所能提供的事務處理能力各不相同。這些事務隔離級別是針對三種現象定義的,在併發事務執行時,需要阻止這三種現象 中的一種或多種發生。三種...