事务是对数据库执行的一个操作单位。
事务的本质特征:所有的事务都有开始和结束;事务可以被保存或撤销;如果事务在中途失败,事务中的任何部分都不会被记录到数据库控制事务
当一个事务被执行并成功完成时,虽然从输出结果来看目标表已经被修改了,但实际上目标表并不是立即被修改。当事务成功完成时,利用事务控制命令最终认可这个事务,可以把事务所做的修改保存到数据库,也可以撤销事务所做的修改。commit命令commit命令用于把事务所做的修改保存到数据库,它把上一个commit或rollback命令之后的全部事务都保存到数据库。在执行 commit transaction语句后不能回滚事务。rollback命令rollback命令用于撤销还没有保存到数据库的命令,它只能用于撤销上一个commit或rollback命令之后的事务savepoint命令(在sql中为save tran或save transaction)保存点是事务过程中的一个逻辑点,我们可以把事务回退到这个点,而不必回退整个事务。语法:savepoint savepoint_name这个命令就是事务语句之间创建一个保存点。rollback命令可以撤销一组事务操作,而保存点可以将大量事务操作划分为较小的、更易于管理的组。 begin transactioninsert into score values( ' F002 ' , ' M006 ' , 99 ) save tran sp1insert into score values( ' F009 ' , ' M007 ' , 100 ) rollback tran sp1commit //结果数据库中添加了第一条语句,而第二条语句还未保存到数据库
rollback to savepoint命令(Oracle数据库、DB2数据库 )语法:rollback to savepoint_namerelease savepoint命令(Oracle数据库、DB2数据库)
这个命令用于删除创建的保存点。在某个保存点被释放后,就不能在利用rollback命令来撤销这个保存点之后的事务操作。利用这个命令可以避免意外地回退到某个不再需要的保存点。语法:release savepoint savepoint_nameset transaction命令这个命令用于初始化数据库事务,可以指定事务的特性。我们知道在线程中常常会出现竞态或死锁的问题,其实在数据库中也会出现并发的问题。那么如何解决数据库并发问题呢?解决此问题的办法就是为数据库加锁,以防止多个组件读取数据,通过锁住事务所用的数据,能保证开锁之前,只有本事务才能访问数据库。这样就避免了交叉存取的问题。在sql server数据库中没有READ ONLY(只读锁)和READ WRITE(写入锁),但是在这里简单介绍一下。只读锁是非独占的,多个并发的事务都能获得只读锁,只进行查询事务,很适合生成报告,而且能够提高事务完成的速度;写入锁是独占的,任意时间只能有一个事务可以获得写入锁,可以对数据库进行查询和操作数据的事务。如果事务是READ WRITE类型的,数据库必须对数据库对象进行加锁,从而在多个事务同时发生时保持数据完整性。如果事务是READ ONLY类型的,数据库就不会建立锁定,这样就会提高事务的性能。语法: SET TRANSACTION {READ ONLY} |{READ WRITE} | { ISOLATION LEVEL 【 READ COMMITTED | READ UNCOMMITTED | REPEATABLE READ | SERIALIZABLE 】 }
四种事务的隔离级别
要理解这些隔离级别的差异,首先了解如下几个概念:脏读、不可重复读、幻影读取。脏读:假设同一个A和B两个同时并发操作数据库,A和B执行的任务如下:从数据库读取整数N,将N再加上10,将新的N更新回数据库。这两个并发执行的实例可能发生下面的执行顺序。1.A从数据库中读取整数N,当前数据库中N=0;2.N加上10,并将其更新到数据库中,当前数据库中N=10,然而A的事务还没有提交,所以数据库更新还没有称之为持久性的。3.B从数据库中读取整数N,当前数据库中N=0;4.A回滚了事务,所以N恢复到了N=0;5.B将N加上了10,并将其更新到数据库中,当前数据库中N=20。这里出现了B在A提交前读取了A所更新的数据,由于A回滚了事务,所以数据库中出现了错误的数据20,尽管A回滚了事务,但是A更新的数据还是间接的通过B被更新到了数据库中。这种读取了未提交的数据的方法就叫脏读问题。不可重复读:当一个用户从数据库中读取数据的时候,另外一个用户修改了这条数据,所以数据发送了改变,当再次读取的时候就出现了不可重复读的问题。幻影读取:在两次数据库操作读取操作之间,一组新的数据会出现在数据库中,1.A从数据库中检索到了一些数据;2.B通过Insert插入一些新的数据;3.A再次查询的时候,新的数据就会出现。了解了这几个概念,下面来看一下四种事务的隔离级别的区别:READ UNCOMMITTED最低隔离级,允许脏读或 0 级隔离锁定,这表示不发出共享锁并忽略所以锁,也不接受排它锁。READ COMMITTED当数据正被读取时,可以控制共享锁。不允许脏读,但数据可在事务结束前更改,从而产生不可重复读取或幻像数据。该选项是 SQL Server 的默认值。REPEATABLE READ锁定查询中使用的所有数据以防止其他用户更新、删除数据等,但是其他用户可以将新的幻像行插入数据集,且可以读取。因为并发低于默认隔离级别,所以应只在必要时才使用该选项。SERIALIZABLE事务的最高隔离级,锁定整个数据集,以防止其他用户在事务完成之前更新数据集或将行插入数据集内。因为并发级别较低,所以应只在必要时才使用该选项。该选项的作用与在事务内所有 SELECT 语句中的所有表上设置 HOLDLOCK 相同。事务的一个例子: SET TRANSACTION ISOLATION LEVEL REPEATABLE READbegin transactionsave tran sp1insert into score values( ' F002 ' , ' M006 ' , 99 ) save tran sp2insert into score values( ' F009 ' , ' M007 ' , 100 ) save tran sp3delete from score where sid >= 39 rollback tran sp2commit