前幾天同事講了Transaction isolation level,并且大家一起在SQLServer,Oracle跟MySQL數(shù)據(jù)庫上實(shí)驗(yàn)了一下,發(fā)覺這些知識(shí)還是挺重要的。
假如有兩個(gè)事務(wù)并發(fā),順序如下
Transaction A Transaction B
begin begin
query1 from table A
....... modify1 to table A(insert/update/delete)
commit
query2 from table A
commit
那么在事務(wù)A中,query1跟query2查詢出來的結(jié)果是否一樣呢?這就跟事務(wù)隔離級(jí)別有關(guān)了。
SQL的標(biāo)準(zhǔn)定義里面,一共有四種級(jí)別:
read uncommited讀取未提交的數(shù)據(jù) 就是其他事務(wù)求提交的數(shù)據(jù),都可以讀取出來
read commited讀取已提交的數(shù)據(jù) query2會(huì)跟query1讀取的數(shù)據(jù)不一樣
repeatable read可重復(fù)讀取,即query1跟query2讀取的數(shù)據(jù)是一樣的
serializable 序列化,
SQL 標(biāo)準(zhǔn)用三個(gè)必須在并行的事務(wù)之間避免的現(xiàn)象定義了四個(gè)級(jí)別的事務(wù)隔離。 這些不希望發(fā)生的現(xiàn)象是:
臟讀(dirty reads)
一個(gè)事務(wù)讀取了另一個(gè)未提交的并行事務(wù)寫的數(shù)據(jù)。
不可重復(fù)讀(non-repeatable reads)
一個(gè)事務(wù)重新讀取前面讀取過的數(shù)據(jù), 發(fā)現(xiàn)該數(shù)據(jù)已經(jīng)被另一個(gè)已提交的事務(wù)修改過。
幻讀(phantom read)
一個(gè)事務(wù)重新執(zhí)行一個(gè)查詢,返回一套符合查詢條件的行, 發(fā)現(xiàn)這些行因?yàn)槠渌罱峤坏氖聞?wù)而發(fā)生了改變。
隔離級(jí)別 臟讀(Dirty Read) 不可重復(fù)讀(NonRepeatable Read) 幻讀(Phantom Read)
讀未提交(Read uncommitted) 可能 可能 可能
讀已提交(Read committed) 不可能 可能 可能
可重復(fù)讀(Repeatable read) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能
SQLServer
我們首先在SQLServer上做了實(shí)驗(yàn),SQLServer一共支持四種隔離級(jí)別,read uncommited跟read commited我們沒有實(shí)驗(yàn),我們直接先實(shí)驗(yàn)
repeatable read,如果事務(wù)A定義了如下級(jí)別,那么當(dāng)事務(wù)B執(zhí)行到modify1這條語句時(shí),如果modify1是update的話,就被鎖起來,一直等
到事務(wù)A提交完以后,鎖才會(huì)被釋放,而如果是insert的話,剛可以順利進(jìn)行下去,然后在事務(wù)A中,query2查到的數(shù)據(jù),是已經(jīng)被事務(wù)B
修改過的數(shù)據(jù),如果將級(jí)別定義在serializable的話,則在modify1語句中,update,insert或者delete都會(huì)被鎖掉。
也就是說,SQLServer對(duì)這些級(jí)別的支持,是通過鎖來做到的,雖然可以保證事務(wù)正常進(jìn)行,但是并行的性能卻很差。
Oracle
oracle只支持兩個(gè)級(jí)別,read commited跟serializable,結(jié)果這里就不用詳細(xì)說明,實(shí)驗(yàn)的結(jié)果是,oracle的serializable是通過版本
控制來完成的,而不是通過鎖機(jī)制,這就保證了并行的性能。Oracle的默認(rèn)級(jí)別是read commited
MySQL
MySQLServer也支持四個(gè)級(jí)別,而且MySQL也是通過版本控制而非鎖機(jī)制來完成的。
文章來源:http://blog.csdn.net/Wingel/archive/2006/11/26/1414839.aspx