SQL Server 2000+ADO.NET 实现并发控制...(二)
2.3 事务隔离级别
尽管数据库理论对并发一致性问题提供了完善的解决机制,但让程序员自
己去控制如何加锁以及加锁、解锁的时机显然是很困难的事情。索性绝大多数
数据库以及开发工具都提供了事务隔离级别,让用户以一种更轻松的方式处理
并发一致性问题。常见的事务隔离级别包括:
ReadUnCommitted、ReadCommitted、RepeatableRead 和
Serializable 四种。不同的隔离级别下对数据库的访问方式以及数据库的返回
结果有可能是不同的。我们将通过几个实验深入了解事务隔离级别以及 SQL
Server 在后台是如何将它们转换成锁的。
2.3.1 ReadUnCommitted 与 ReadCommitted
ReadUnCommitted 是最低的隔离级别,这个级别的隔离允许读入别人
尚未提交的脏数据,除此之外,在这种事务隔离级别下还存在不可重复读的问
题。
ReadCommitted 是许多数据库的缺省级别,这个隔离级别上,不会出现
读取未提交的数据问题,但仍然无法避免不可重复读(包括幻影读)的问题。
当你的系统对并发控制的要求非常严格时,这种默认的隔离级别可能无法提供
数据有效的保护,但对于决大多数应用来讲,这种隔离级别就够用了。
我们使用下面的实验来进行测试:
首先配置 SQL Server 2000 数据库,附加 DBApp 数据库。然后在
Visual Studio .net 中建立一管理控制台应用程序,添加必要的命名空间引用:
using System;using System.Data;using System.Data.SqlClient;using
System.Con#guration;
然后建立两个数据库链接,并分别采用不同的事务隔离级别:
private static SqlConnection conn1;private static SqlConnection
conn2;private static SqlTransaction tx1;private static SqlTransaction
tx2;private static void Setup(){conn1 = new
SqlConnection(connectionString);conn1.Open();tx1 =
conn1.BeginTransaction(IsolationLevel.ReadUncommitted);conn2 =
new SqlConnection(connectionString);conn2.Open();tx2 =
conn2.BeginTransaction(IsolationLevel.ReadCommitted);}
其中事务 1 允许读入未提交的数据,而事务 2 只允许读入已提交数据。
在主程序中,我们模拟两个人先后的不同操作,以产生并发一致性问题:
public static void Main()
{Setup();try{ReadUnCommittedDataByTransaction1();UnCommitted
UpdateByTransaction2();ReadUnCommittedDataByTransaction1();tx
2.Rollback();Console.WriteLine("-- Transaction 2 rollbacked!\
n");ReadUnCommittedDataByTransaction1();tx1.Rollback();}catch{
……}}
第一步,使用 ReadUnCommittedDataByTransaction1 方法利用事务
1 从数据库中读入 id 值为 1 的学生信息。此时的信息是数据库的初始信息。