一、看似一个之前接触过的名词,但是当问起来事务是什么的时候,你会怎么答呢?
事务(Transaction),是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言书写的用户程序的执行所引起的,并用形如Begin transaction和end Transaction语句(或函数调用)来界定。事务由事务开始和事务结束之间执行的全体操作组成。
二、有了它的概念,我们得清楚他的性格,下面了解一下事务的特性:
传说中的‘酸’就出场了,ACID就是事务的特性。
1、原子性(atomicity)
一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
2、一致性(comsistency)
事务必须是使数据库从一个一致性状态变到另一个一致性状态。如果成功转换就是保持了一致性,如果中途断了,没有转换到应该到的目标,就是不一致。
3、隔离性(isolation)
一个事务的执行不能被其他事务干扰。一个事务内部操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事物之间不能相互干扰。
4、持久性(durability)
持久性,也叫永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,接下来的其他操作或故障不应该对期有任何影响,也就是事务提交之后,就永久的存在了数据库上。
咱们在来准确的认识一下事务:
它就是作为单个逻辑工作单元执行的一系列操作,要么完全执行,要么完全不执行。一个逻辑工作单元要成为事务,必须满足他的特性ACID属性。
三、 我们为什么要用事务呢?
通过将一组相关操作组合成为一个要么全部成功,要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。SQL server能将逻辑相关的一组操作绑定在一起,以便服务器保持数据的完整性。
四、 怎么使用事务呢?
一种是在数据库里写事务,一种是在程序里写。
在数据库里写事务举例:
A要转给B100元的钱,如果程序出错的时候还回,不执行
begin tran
update 表
set A=A+100 where 姓名='A'
update 表
set B=B-100 where 姓名='B'
if @@error<>0
rollback
else
commit
在程序里写事务:
举例~
string[] sqls = .....
OleDbConnection conn;
OleDbCommand cmd;
OleDbTransaction trans;
conn = .........;
cmd = conn.CreateCommand();
trans = conn.BeginTransaction();
cmd.Transaction = trans;
try
{
for (int i = 0; i < sqls.length; i++)
{
cmd.CommandText = sqls[i];
cmd.ExecuteNonQuery();
}
trans.Commit();
}
catch (Exception ex) { trans.Rollback(); }
finally
{
conn.Close();
}
五、事务的隔离机制
在数据库操作中,为了有效保证并发读取数据的正确性,提出了事务隔离级别,就是我们采用什么规则来处理并发操作。
SQL Server中的隔离级别及其实现机制
Read Uncommitted :未提交读。
一个会话可以读取A事务未提交的更新的结果,如果这个A事务最后以回滚结束,这时这个会话读取结果可能是错误的,所以多数数据库应用都不会使用这种隔离级别。就是在执行了一系列的update等操作之后,还没有执行commite的时候,就有其他会话能来读取数据了。
Read Committed:提交读
这是是sqlserver的缺省的隔离级别,设置为这种隔离级别的事务只能读取其他事务已经提交的更新结果,否则,等待发生,但是其他会话可以修改这个事务中被读取的记录,而不必等待事务结束,显然,在这种隔离级别下,一个事务中的两个相同的读取操作,结果可能不同。
Read Repeatable:可重复读
在一个事务中,如果在两次相同条件的读取操作之间没有添加记录的操作,也没有其他更新操作导致在这个查询条件下记录数的增多,则两次读取结果相同。也就是说,在一个事务中第一次读取的记录保证不会在这个事务期间发生改变。sqlserver通过在整个事务期间给读取的记录加锁实现这种隔离级别的,这样,在这个事务结束结束前,其他会话不能修改事务中读取的记录,只能等待事务结束,但sqlserver不会阻碍其他会话向表中添加记录,也不阻碍其他会话修改其他记录。也就是不能修改当前读的记录,但是可以添加数据(幻想读)
我们多使用此隔离级别。
Serializable:可串行读
在一个事务中,读取操作的结果是在这个事务开始之前其他事务都都已经提交的记录,就是一个做完,另一个才能开始做。保证了在一个事务中2次读取操作的结果肯定是相同的。
六、数据并发的问题
1、脏读(dirty read)
A 事务读取B事务尚未提交的更改数据,并在这个数据的基础上操作,如果B回滚了,那么A事务读到的数据就是不被承认的,脏数据。
2、不可重复读(unrepeatable read)
这是由于查询时系统中其他事务修改的提交而引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
A要读2次,2次结果不重复。
3、幻想读(phantom read)
A事务读取B事务提交的新增数据,这时A事务将出现幻象读的问题。幻象读一般发生在计算统计数据的事务中,举一个例子,假设银行系统在同一个事务中,两次统计存款账户的总金额,在两次统计过程中,刚好新增了一个存款账户,并存入100元,这时,两次统计的总金额将不一致.
A 以为出现幻觉了,多了一条数据。
幻象读和不可重复读是两个容易混淆的概念,前者是指读到了其它已经提交事务的新增数据,而后者是指读到了已经提交事务的更改数据(更改或删除),为了避免这两种情况,采取的对策是不同的,防止读取到更改数据,只需要对操作的数据添加行级锁,阻止操作中的数据发生变化,而防止读取到新增数据,则往往需要添加表级锁——将整个表锁定,防止新增数据。
事务就写到这里了,每一次积累都是进步,愿我们一步一步,踏踏实实的实现自己的梦想。