什么是事务?简单的说,就是你要做的或所做的事情。用术语表述是指访问并可能更新数据库中各种数据项的一个程序执行单元。
在数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。
举个很经典的例子:从A账户向B账户转账。这个过程需要完成两个步骤:1)从A账户中减去钱;2)在B账户中加上相应的钱数。很简单,这两个步骤缺一不可。如果一旦出错,后果不堪设想。怎么办呢?这就引出了事务的用处。
sql语句如下,当不出错时,提交事务转账成功。如果出错了,就执行回滚。数据库设计也很简单,一张money表,两个字段bankName(账户名)和totalMoney(总资产)。
begin try
begin tran --开始事务
update money set totalMoney=totalMoney-100 where bankName='A' --A账户减100
update money set totalMoney=totalMoney+100 where bankName='B'--B账户加100
commit tran --提交事务
End try
begin catch
rollback tran --事务回滚
end catch
还以转账为例,从A向B转账。
具体代码如下:
private void button1_Click(object sender, EventArgs e)
{
SqlTransaction sqlTrans = null;
SqlConnection con = new SqlConnection("server=.;database=bank;uid=sa;pwd=123456;");
try
{
con.Open();
//开始事务
sqlTrans = con.BeginTransaction();
SqlCommand cmd = new SqlCommand("", con, sqlTrans);
cmd.CommandTimeout = 120;
cmd.CommandType = System.Data.CommandType.Text;
string cutA = "update money set totalMoney=totalMoney-@count where bankName='A'";
string addB = "update money set totalMoney=totalMoney+@count where bankName='B'";
//给参数赋值
SqlParameter paras = new SqlParameter("@count", txtMoney.Text);
cmd.Parameters.Add(paras);
cmd.CommandText = cutA;
cmd.ExecuteNonQuery();
cmd.CommandText = addB;
cmd.ExecuteNonQuery();
//throw new Exception("test exception.the transaction must rollback"); 用以测试事务回滚
//提交事务
sqlTrans.Commit();
}
catch (Exception ex)
{
//事务回滚
sqlTrans.Rollback();
Console.Write(ex.Message);
}
finally
{
if (con.State != System.Data.ConnectionState.Closed)
con.Close();
}
Console.ReadLine();
}
现在看一下事务回滚时的情况:将上面注视掉的一行代码恢复正常,再次运行。减少A账户钱和增加B账户的钱,两个操作都没有执行,这样虽然即使出错了,也不会造成更严重的后果,只是让程序恢复到执行前的状态。
看了上面的例子,就能跟好的理解事务的属性了,分别有原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
1)atomicity 原子性。这说明事务是一个不可分割的工作单位,事务中包括的所有操作要么都做,要么都不做。这也是核心之处。
2)consistency 一致性。事务必须是使数据库从一个一致性状态变到另一个一致性状态。这一点和原子性很像。
3)isolation 隔离性。一个事务的执行不能被其他事务干扰。
4)durability 持久性。指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。若转账成功,就将数据更新到数据库。
感想:事务,这个名词很早就听说过了。之所以到现在才去了解它实践它,是因为感觉它很难。以至于遇到类似的内容总是绕着走开,也错过了很多学习的机会。越早了解,就有越多动手实践的机会。