数据库事物

来源:互联网 发布:网站源码网 编辑:程序博客网 时间:2024/04/23 22:41

事务是对数据库执行的一个操作单位。
事务的本质特征:
所有的事务都有开始和结束;
事务可以被保存或撤销;
如果事务在中途失败,事务中的任何部分都不会被记录到数据库

控制事务
当一个事务被执行并成功完成时,虽然从输出结果来看目标表已经被修改了,但实际上目标表并不是立即被修改。
当事务成功完成时,利用事务控制命令最终认可这个事务,可以把事务所做的修改保存到数据库,也可以撤销事
务所做的修改。
commit命令
commit命令用于把事务所做的修改保存到数据库,它把上一个commit或rollback命令之后的全部事务都保存到
数据库。在执行 commit transaction语句后不能回滚事务。
rollback命令
rollback命令用于撤销还没有保存到数据库的命令,它只能用于撤销上一个commit或rollback命令之后的事务
savepoint命令(在sql中为save tran或save transaction)
保存点是事务过程中的一个逻辑点,我们可以把事务回退到这个点,而不必回退整个事务。
语法:savepoint savepoint_name
这个命令就是事务语句之间创建一个保存点。rollback命令可以撤销一组事务操作,而保存点可以将大量事务操作
划分为较小的、更易于管理的组。 

begin transaction
insert into score values(
'F002','M006',99
save tran sp1
insert into score values(
'F009','M007',100
rollback tran sp1
commit                                      //结果数据库中添加了第一条语句,而第二条语句还未保存到数据库

rollback to savepoint命令(Oracle数据库、DB2数据库 )
语法:rollback to savepoint_name
release savepoint命令(Oracle数据库、DB2数据库
这个命令用于删除创建的保存点。在某个保存点被释放后,就不能在利用rollback命令来撤销这个保存点之后的事务
操作。利用这个命令可以避免意外地回退到某个不再需要的保存点。
语法:release savepoint savepoint_name
set 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 READ
begin transaction
save tran sp1
insert into score values(
'F002','M006',99
save tran sp2
insert into score values(
'F009','M007',100
save tran sp3
delete from score 
where sid>=39
rollback tran sp2
commit
复制代码
0 0
原创粉丝点击