2023年6月21日发(作者:)
TransactionScope事务简介在.NET 1.0/1.1 版本我们使⽤SqlTransaction.处理事务string connString = tionStrings["db"].ConnectionString;using (var conn = new SqlConnection(connString)){ (); using (IDbTransaction tran = ransaction()) { try { // using (SqlCommand cmd = Command()) { dText = "INSERT INTO Data(Code) VALUES('A-100');"; ction = tran as SqlTransaction; eNonQuery(); } (); } catch(Exception ex) { ck(); throw; } }}到了.NET2.0微软提供了TransactionScopeusing (var scope = new TransactionScope()){ //transctional code… te();}TransactionScope使⽤起来简单,只需要把代码写在⼤括号⾥,最后加上te();就可以了
接下来主要介绍TransactionScope的简单使⽤TransactionScope有三个属性:IsolationLevel,Timeout,TransactionScopeOptionPropertyDefault ValueAvailable OptionsSerializable, ReadIsolationLevel(隔离等级)SerializableCommitted, Read UnCommitted,Repeatable ReadTimeout(超时)1 MinuteMaximum 10 MinutesTransactionScopeOption(选项)RequiredRequired, RequiredNew, Suppress⽤以下代码可以看到他们属性的值using (var scope = new ctionScope()){ ionLevel isolationLevel = ionLevel; TimeSpan defaultTimeout = tTimeout; TimeSpan maximumTimeout = mTimeout;}由图可以看到,TransactionScope默认情况下的隔离等级为Serializable,超时时间为1分钟
Dirty Read(脏读):脏读就是指当⼀个事务正在访问数据,并且对数据进⾏了修改,⽽这种修改还没有提交到数据库中,这时,另外⼀个事务也访问这个数据,然后使⽤了这个数据。Non Repeatable Read(不可重复读):是指在⼀个事务内,多次读同⼀数据。在这个事务还没有结束时,另外⼀个事务也访问该同⼀数据。那么,在第⼀个事务中的两次读数据之间,由于第⼆个事务的修改,那么第⼀个事务两次读到的的数据可能是不⼀样的。这样就发⽣了在⼀个事务内两次读到的数据是不⼀样的,因此称为是不可重复读。(即不能读到相同的数据内容)Phantom Read(幻读):是指当事务不是独⽴执⾏时发⽣的⼀种现象,例如第⼀个事务对⼀个表中的数据进⾏了修改,这种修改涉及到表中的全部数据⾏。同时,第⼆个事务也修改这个表中的数据,这种修改是向表中插⼊⼀⾏新数据。那么,以后就会发⽣操作第⼀个事务的⽤户发现表中还有没有修改的数据⾏,就好象发⽣了幻觉⼀样。隔离等级的四种选择:Serializable(序列化):它在读/写操作时锁定数据。由于这个原因,很多时候它会创建⼀个死锁,因此你可能会得到⼀个超时异常。可以将此隔离级别⽤于⾼度安全的事务性应⽤程序(如⾦融应⽤程序)。缺点是性能低Repeatable Read(可重复读):同为Serializable,除了允许幻读。可以使⽤在⾦融中的应⽤或严重事务性应⽤,但需要知道幻读创造的场景是不存在的。Read Committed(读提交):⼤多数应⽤程序都可以使⽤它。SQLServer默认隔离级别是这个。不会有脏读Read Un-Committed(读不提交):这些应⽤程序不需要⽀持并发事务。
TransactionScope使⽤:对CommonTest_ExamInfo_ExamStudents表中的⼀个学⽣进⾏修改操作,隔离等级为Read Committedvar option = new TransactionOptions(); ionLevel = mmitted; t = nutes(1); using (var scope = new TransactionScope(ed, option)) { String sql = @"UPDATE Students SET sStuName = @sStuName WHERE sID = @sID AND sIdentityID = @sIdentityID "; SqlParameter[] args = new SqlParameter[3]; args[0] = new SqlParameter("@sStuName", "张三"); args[1] = new SqlParameter("@sTID", "2"); args[2] = new SqlParameter("@sIdentityID", "362831"); if (eSqlCommand(sql, args) > 0) { te(); return true; } else { return false; }}当执⾏完代码红⾊那⾏后,可以看到,SQLserver启动了隔离等级为Read Committed的事务,然后执⾏修改操作。 此时,如果执⾏SELECT TOP 1000 * FROM [dbo].[Students] SQL语句,如正在修改的数据也包括在内,则不能被查出来,修改操作也是如此。直到跳出using括号后,查询语句才能被真正执⾏。但是,此时数据库可以执⾏与事务修改操作⽆关的数据,如执⾏SELECT * FROM StudentsWHERE sTID = '2' AND sIdentityID = '362831' SQL语句,可以顺利查询到数据此外,还有⼀点需要说明,当连续执⾏两次相同的修改操作,即第⼆次其实是没有真正修改数据库数据的,此时可以对操作的数据⾏查询场次安排不使⽤事务和使⽤TransactionScope的Read Committed进⾏对⽐
不使⽤事务如下:using (TransactionScope scope = new TransactionScope(ed, new TransactionOptions { IsolationLevel = cti{ if ( != ) { (); //打开Connection连接
} if(!sert
} return false; } if (!sert
} return false; } if ( != ) { (); //关闭Connection连接
} var testInfo = (p => == sTID).FirstOrDefault(); if (nSaveType == 1) { tate = 14; } else { tate = 13; } anges(); te(); return true; } eSqlCommand("delete from estList where sTID=@sTid;delete from udents where sTID=@sTid;", new添加TransactionScope事务:以上两图显⽰他们性能上并⽆明显区别。
总结:可以使⽤TransactionScope的Read Committed隔离等级进⾏⼀系列事务操作,性能没有太⼤影响。⼀般不使⽤TransactionScope默认的Serializable隔离等级,因为它需要开很多锁,性能会因此⽽下降。使⽤TransactionScope应注意尽量让using⼤括号⾥⾯的代码都短⼀些,这样它出错的⼏率更⼩,事务回滚的⼏率也会减少。所以出于数据的⼀致性考虑,⼀系列对数据库的操作可添加TransactionScope的Read Committed隔离等级的事务。
2023年6月21日发(作者:)
TransactionScope事务简介在.NET 1.0/1.1 版本我们使⽤SqlTransaction.处理事务string connString = tionStrings["db"].ConnectionString;using (var conn = new SqlConnection(connString)){ (); using (IDbTransaction tran = ransaction()) { try { // using (SqlCommand cmd = Command()) { dText = "INSERT INTO Data(Code) VALUES('A-100');"; ction = tran as SqlTransaction; eNonQuery(); } (); } catch(Exception ex) { ck(); throw; } }}到了.NET2.0微软提供了TransactionScopeusing (var scope = new TransactionScope()){ //transctional code… te();}TransactionScope使⽤起来简单,只需要把代码写在⼤括号⾥,最后加上te();就可以了
接下来主要介绍TransactionScope的简单使⽤TransactionScope有三个属性:IsolationLevel,Timeout,TransactionScopeOptionPropertyDefault ValueAvailable OptionsSerializable, ReadIsolationLevel(隔离等级)SerializableCommitted, Read UnCommitted,Repeatable ReadTimeout(超时)1 MinuteMaximum 10 MinutesTransactionScopeOption(选项)RequiredRequired, RequiredNew, Suppress⽤以下代码可以看到他们属性的值using (var scope = new ctionScope()){ ionLevel isolationLevel = ionLevel; TimeSpan defaultTimeout = tTimeout; TimeSpan maximumTimeout = mTimeout;}由图可以看到,TransactionScope默认情况下的隔离等级为Serializable,超时时间为1分钟
Dirty Read(脏读):脏读就是指当⼀个事务正在访问数据,并且对数据进⾏了修改,⽽这种修改还没有提交到数据库中,这时,另外⼀个事务也访问这个数据,然后使⽤了这个数据。Non Repeatable Read(不可重复读):是指在⼀个事务内,多次读同⼀数据。在这个事务还没有结束时,另外⼀个事务也访问该同⼀数据。那么,在第⼀个事务中的两次读数据之间,由于第⼆个事务的修改,那么第⼀个事务两次读到的的数据可能是不⼀样的。这样就发⽣了在⼀个事务内两次读到的数据是不⼀样的,因此称为是不可重复读。(即不能读到相同的数据内容)Phantom Read(幻读):是指当事务不是独⽴执⾏时发⽣的⼀种现象,例如第⼀个事务对⼀个表中的数据进⾏了修改,这种修改涉及到表中的全部数据⾏。同时,第⼆个事务也修改这个表中的数据,这种修改是向表中插⼊⼀⾏新数据。那么,以后就会发⽣操作第⼀个事务的⽤户发现表中还有没有修改的数据⾏,就好象发⽣了幻觉⼀样。隔离等级的四种选择:Serializable(序列化):它在读/写操作时锁定数据。由于这个原因,很多时候它会创建⼀个死锁,因此你可能会得到⼀个超时异常。可以将此隔离级别⽤于⾼度安全的事务性应⽤程序(如⾦融应⽤程序)。缺点是性能低Repeatable Read(可重复读):同为Serializable,除了允许幻读。可以使⽤在⾦融中的应⽤或严重事务性应⽤,但需要知道幻读创造的场景是不存在的。Read Committed(读提交):⼤多数应⽤程序都可以使⽤它。SQLServer默认隔离级别是这个。不会有脏读Read Un-Committed(读不提交):这些应⽤程序不需要⽀持并发事务。
TransactionScope使⽤:对CommonTest_ExamInfo_ExamStudents表中的⼀个学⽣进⾏修改操作,隔离等级为Read Committedvar option = new TransactionOptions(); ionLevel = mmitted; t = nutes(1); using (var scope = new TransactionScope(ed, option)) { String sql = @"UPDATE Students SET sStuName = @sStuName WHERE sID = @sID AND sIdentityID = @sIdentityID "; SqlParameter[] args = new SqlParameter[3]; args[0] = new SqlParameter("@sStuName", "张三"); args[1] = new SqlParameter("@sTID", "2"); args[2] = new SqlParameter("@sIdentityID", "362831"); if (eSqlCommand(sql, args) > 0) { te(); return true; } else { return false; }}当执⾏完代码红⾊那⾏后,可以看到,SQLserver启动了隔离等级为Read Committed的事务,然后执⾏修改操作。 此时,如果执⾏SELECT TOP 1000 * FROM [dbo].[Students] SQL语句,如正在修改的数据也包括在内,则不能被查出来,修改操作也是如此。直到跳出using括号后,查询语句才能被真正执⾏。但是,此时数据库可以执⾏与事务修改操作⽆关的数据,如执⾏SELECT * FROM StudentsWHERE sTID = '2' AND sIdentityID = '362831' SQL语句,可以顺利查询到数据此外,还有⼀点需要说明,当连续执⾏两次相同的修改操作,即第⼆次其实是没有真正修改数据库数据的,此时可以对操作的数据⾏查询场次安排不使⽤事务和使⽤TransactionScope的Read Committed进⾏对⽐
不使⽤事务如下:using (TransactionScope scope = new TransactionScope(ed, new TransactionOptions { IsolationLevel = cti{ if ( != ) { (); //打开Connection连接
} if(!sert
} return false; } if (!sert
} return false; } if ( != ) { (); //关闭Connection连接
} var testInfo = (p => == sTID).FirstOrDefault(); if (nSaveType == 1) { tate = 14; } else { tate = 13; } anges(); te(); return true; } eSqlCommand("delete from estList where sTID=@sTid;delete from udents where sTID=@sTid;", new添加TransactionScope事务:以上两图显⽰他们性能上并⽆明显区别。
总结:可以使⽤TransactionScope的Read Committed隔离等级进⾏⼀系列事务操作,性能没有太⼤影响。⼀般不使⽤TransactionScope默认的Serializable隔离等级,因为它需要开很多锁,性能会因此⽽下降。使⽤TransactionScope应注意尽量让using⼤括号⾥⾯的代码都短⼀些,这样它出错的⼏率更⼩,事务回滚的⼏率也会减少。所以出于数据的⼀致性考虑,⼀系列对数据库的操作可添加TransactionScope的Read Committed隔离等级的事务。
发布评论