事务¶
事务为保证数据的完整性,数据的一致性和程序语义的正确性提供了一种机制.事务机制中主要包括提交模式,事务隔离级别和保存点三部分.神通数据库和神通数据库 .NET DATA PROVIDER 驱动程序,对这三部分给出了较好的实现方法.在本章中,我们将依次介绍它们的特性和使用方法.
对于缺省情况下,DML操作(INSERT,UPDATE,DELETE)一旦被执行,将自动被提交.当然可以自己来改变
commit
模式,比如需要执行多条语句,这些语句要求在一个事务里面,那么这时候就必须创建一个
OscarTransaction 对象.可以通过调用Connection 对象的
BeginTransaction() 方法来获得 OscarTransaction 对象.创建一个事务
Transaction,然后就可以提交 Commit 或者回滚 Rollback
多条语句.
事务处理格式¶
- 创建事务对象(transaction = connect.BeginTransaction())
...
- 执行操作
...
- 保存到数据库 (transaction.Commit())
...
- 放弃操作 (transaction.Rollback())
在执行事务中,抛出异常自动回滚.
示例
using (var connect = new OscarConnection("Server=10.1.1.66;Port=2003;User Id=SYSDBA;Password=szoscar55;Database=OSRDB;"))
{
connect.Open();
using (var transaction = connect.BeginTransaction())
{
try
{
using (var command = connect.CreateCommand())
{
command.CommandText = "CREATE TABLE MY_TABLE (ID INT, NAME VARCHAR(16), AGE INT, SEX BOOLEAN, MARK TIMESTAMP)";
command.ExecuteNonQuery();
command.CommandText = "INSERT INTO MY_TABLE VALUES (@id,@name,@age,@sex,@mark)";
command.Parameters.Add(new OscarParameter("id", OscarDbType.Int) { Value = 1 });
command.Parameters.Add(new OscarParameter("name", OscarDbType.VarChar) { Value = "小张" });
command.Parameters.Add(new OscarParameter("age", OscarDbType.Int) { Value = 20 });
command.Parameters.Add(new OscarParameter("sex", OscarDbType.Boolean) { Value = true });
command.Parameters.Add(new OscarParameter("mark", OscarDbType.TimeStamp) { Value = DateTime.Now });
var result = command.ExecuteNonQuery();
command.Parameters.Clear();
transaction.Commit();
// transaction.Rollback();
command.CommandText = "SELECT * FROM MY_TABLE";
using (OscarDataReader reader = command.ExecuteReader())
{
Console.WriteLine("ID NAME AGE SEX MARK");
while (reader.Read())
{
var vals = new object[5];
reader.GetValues(vals);
Console.WriteLine("{0} {1} {2} {3} {4}", vals);
}
}
command.CommandText = "DROP TABLE MY_TABLE";
command.ExecuteNonQuery();
}
}
catch (Exception ex)
{
transaction.Rollback();
Console.WriteLine(ex.Message);
}
finally
{
}
}
}
提交模式¶
应用程序创建一个连接时,该连接默认事务自动提交,即每执行一次SQL语句,该SQL语句就被认为是一个事务,而被自动提交了.如果用户需要将多条语句包含在一个事务中,那么用户就要改变自动提交模式.用户可以在 Connection 对象中开始一个事务,并且可以提供事务提交模式.
OscarConnection conn = new OscarConnection(ConnectionString);
OscarTransaction trans = conn.BeginTransaction(IsolationLevel.Value);
...some code
trans.Commit(); // 或者是回滚事务 trans.Rollback();
OscarTransaction
对象.在事务结束时,应该调用事务的 Commit 方法将事务提交或者
Rollback 方法将事务回滚.OscarConnection 的 BeginTransaction
方法可以不带参数,则默认的事务隔离级别为
IsolationLevel.ReadCommitted ; 也可以在 BeginTransaction
方法时作为参数给出.在非自动提交模式下,用户在一个事务执行完成之后需要显式调用
OscarTransaction 对象的 commit() 方法来提交事务.
方法如下: trans.Commit();
当该事务需要回滚时,则需要显式调用 OscarTransaction 对象的
Rollback() 方法.
trans.Rollback();
当事务执行完被提交或回滚后,驱动程序将自动地释放事务对象,如果要再开启一个事务,则需要重复上面的步骤.如果事务对象没有显示的调用Commit方法或者Rollback方法,在该Connection关闭的时候(Close方法的时候),会自动调用事务对象的Commit方法进行提交.
隔离级别¶
神通数据库支持的事务隔离级别
- TRANSACTION_READUNCOMMITTED(以TRANSACTION_READCOMMITTED来支持该级别)
- TRANSACTION_READCOMMITTED
- TRANSACTION_REPEATABLE_READ(以TRANSACTION_SERIALIZABLE来支持该级别)
- TRANSACTION_SERIALIZABLE
默认的事务隔离级别为TRANSACTION_READ_COMMITTED.用户可以通过通过
Connection 接口中的 BeginTransaction
方法来开始一个事务,并设置事务隔离级别.由于事务隔离级别升高时,数据库系统为了保证语义的正确性,会加入更多的锁.当锁加得过多时,会降低程序的性能.因此在确定事务隔离级别的时候,用户应充分考虑数据一致性和性能要求之间的平衡.
保存点(SAVEPOINT)¶
保存点(Savepoint)提供了对事务更小粒度的控制方法,它代表一个逻辑事务点.在非自动提交模式下,一个事务中可以设置多个保存点,这样在回滚的时候,可以回滚到指定的保存点,从事务开始到该保存点之间的操作依然有效.这就为事务处理提供了更多的灵活性.保存点方法为事务对象的Save方法.
保存点方法必须为保存点命名。下面的例子演示了保存点的使用:
// Rollback方法用于回滚当前事务,Rollback方法既可以回滚整个事务,也可以回滚到某个savepoint。
// 使用rollback方法回滚整个事务
conn = new OscarConnection(connStr);
conn.Open();
txn = conn.BeginTransaction();
txn.Rollback();
txn.Dispose();
// 使用rollback方法回滚到某个特定的savepoint
txn = conn.BeginTransaction();
txn.Save("SavePoint1");
txn.Save("SavePoint2");
txn.Rollback("SavePoint2");
txn.Rollback("SavePoint1");
txn.Rollback();
txn.Dispose();
// 离开活动事务范围后调用Rollback会报错
txn = conn.BeginTransaction();
txn.Rollback();
gotIt = false;
try {
txn.Rollback();
}catch(OscarException e){
gotIt = true;
}
// 这里gotIt的值会为true
//Assert.IsTrue(gotIt);
Console.WriteLine(gotlt.ToString());
txn.Dispose();
// 指定错误的savepoint,后台报错
txn = conn.BeginTransaction();
txn.Save("SavePoint3");
gotIt = false;
try {
txn.Rollback("SavePoint4");
}catch(OscarException e){
gotIt = true;
}
//Assert.IsTrue(gotIt);
Console.WriteLine(gotlt.ToString());
txn.Dispose();
conn.Close();
这里应用的保存点和 Rollback
方法(以保存点名为参数)配合使用,可以使事务回滚到某一个点上.
用户也可以调用 Rollback
方法(无参数)来回滚全事务(无视保存点的存在).一旦回滚,事务对象立即变为null,所有保存点也将无效,试图引用也会导致异常.这里要注意另外一种情况,比如按顺序设置了保存点sp1,sp2,sp3,那么当用户回滚到sp2时,那么sp3保存点将不复存在,对sp3的释放或回滚操作将导致PROVIDER驱动程序抛出异常.