【Oracle】5.事务

来源:互联网 发布:正规淘宝代刷信誉平台 编辑:程序博客网 时间:2024/06/16 09:03

定义

事务是工作的逻辑单元,一个事务由一个或多个完成一组相关行为的SQL语句组成。管理SQL事务就是确保这一组SQL语句所做的操作要么完成成功地执行,完成整个工作单元的操作;要么一点儿也不执行。一组SQL语句组成了一组操作行为,这一组行为要成为一个事务,必须满足事务的ACID特性(下面会进行相关解释)。在SQL中,事务是有一组事务控制语句定义的。

                                      基本事务流程图

特性

事务的主要作用就是保证数据库的完整性。因此,从保证数据库完整性出发,必须维护事务的四个性质:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),简称为ACID。

原子性(Atomicity):事务是一个完整的操作。

一致性(Consistency):当事务完成时,数据必须处于一致状态。

隔离性(Isolation):对数据进行修改的所有并发事务是彼此隔离的。

持久性(Durability):事务完成后,它对于系统的影响是永久性的。

创建事务

T-SQL中管理事务的语句:

1 开始事务: begin transaction

2 提交事务:commit transaction

3 回滚事务: rollback transaction

分类

 显式事务:用begin transaction明确指定事务的开始。

 隐性事务:打开隐性事务:set implicit_transactions on,当以隐性事务模式操作时,SQL将在提交或回滚事务后自动启动新事务。无法描述事务的开始,只需要提交或回滚事务。

 自动提交事务:SQL Server的默认模式,它将每条单独的T-SQL语句视为一个事务。如果成功执行,则自动提交,否则回滚。

Demo

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">张静转1K元到李婷帐户上。  use friDB --创建帐户表bank--ifexists(select* from sysobjects where name='bank')    drop table bankcreatetable bank(    customerName char(10),    --顾客姓名    currentMoney money       --当前余额) /**//*--添加约束,帐户不能少于元--*/altertable bank add        constraint CK_currentMoneycheck(currentMoney>=1000)/**//*--插入测试数据--*/insertinto bank(customerName,currentMoney)select ‘张静’,1000 unionselect '李婷',1 select *from bank/**//*--使用事务--*/use sfriDB --恢复原来的数据--updatebank set currentMoney=currentMoney-1000 where customerName='张静'setnocount on    --不显示受影响的行数print '查看转帐事务前的余额'select *from bank/**//*--开始事务--*/begintransactiondeclare@errorSum int    --定义变量,用于累计事务执行过程中的错误/**//*--转帐--*/updatebank set currentMoney=currentMoney-800 where customerName='张静'set@errorSum=@errorSum+@@error    --累计是否有错误updatebank set currentMoney=currentMoney+800 where customerName='李婷'set@errorSum=@errorSum+@@error --累计是否有错误 print '查看转帐事务过程中的余额'select *from bank /**//*--根据是否有错误,确定事务是提交还是回滚--*/if@errorSum>0    begin        print '交易失败,回滚事务.'        rollback transaction    endelse    begin        print '交易成功,提交事务,写入硬盘,永久保存!'        commit transaction    end print '查看转帐后的余额'select *from bank</span></span></span>

隔离级别

隔离级别解决并发问题的能力。

共享锁

共享锁(S锁)允许并发事务在封闭式并发控制下读取(SELECT)资源。

当查询(SELECT)某条记录时,SQLSERVER会尝试取得该条记录的上存在共享锁(S锁),或无法获取,就必须等待别人释放对该记录中某几种与共享锁互斥的锁,才能在设置共享锁之后,获取该条记录。

举例来说:当某人查询某张表的一条记录时,就会在该记录上放置共享锁,在而其他人也要查询这张表的此记录时,因为共享锁彼此不互斥,所以也可以再次放置共享锁,也就是说SQLSERVER允许不同连接同时读取相同的数据。如果此时有人要更新此记录,因为独占锁与共享锁互斥,所以无法放置独占锁,要等到所有读取此记录的人都读取完毕,释放了共享锁,更新数据的人才能对该记录设置独占锁,并进一步更新数据。一般情况下,在默认的事务隔离级别下,当数据读取完毕,SQLSERVER就会释放共享锁,除非有特别的设置。

排他锁(也可称为独占锁)

排他锁(独占锁)(X锁)可以防止并发事务对资源进行访问。使用排他锁(X锁)时,任何其他事务都无法修改数据;仅在使用NOLOCK提示或未提交读隔离级别时才会进行读取操作。

对数据进行添加、修改、删除操作时(如INSERT、UPDATE和DELETE),语句在执行所需的操作之前首先执行读取操作以获取数据。因此,需先对所在的资源放置排他锁,以确保以上操作未完成时,不受到干扰,独占锁在开启事务之后,一直保留到事务结束。例如,UPDATE语句可能根据与一个表的联接修改另一个表中的行。在此情况下,除了请求更新行上的排他锁之外,UPDATE语句还将请求在联接表中读取的行上的共享锁。

乐观锁和悲观锁

为了预防死锁的发生,根据对数据加锁时的加锁策略,锁可以分为乐观锁和悲观锁。

乐观锁假设没有发生可能造成死锁的冲突,然后读取数据,处理事务,执行更新,最后检查是否发生冲突。如果不存在冲突,就完成了。如果存在冲突,则重复事务直到没有冲突为止。

而采用悲观锁时,它总是假设存在冲突,使用一个锁定,处理事务,然后解锁。

Demo

(乐观锁)

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">LOCKORLDUCT  {对表PRODUCT上锁}SELECT 名称,数量         FROM PRODUCT         WHERE Name = ‘铅笔’01dQuabtity= PRODUCT.数量SetNewQuantity = PRODUCT.数量– 5UPDATEPRODUCTSET.PRODUCT数量 = NewQuabtity         WHERE PRODUCT.名称 = ’铅笔’                   AND.PRODUCT.数量 = 01dQuantity{解除PRODUCT表上的锁}UNLOCKPRODUCT(悲观锁)LOCKORLDUCTSELECT 名称,数量         FROM PRODUCT         WHERE Name = ‘铅笔’01dQuabtity= PRODUCT.数量SetNewQuantity = PRODUCT.数量– 5LOCTPRODUCT{对表PRODUCT上锁}UPDATEPRODUCTSET.PRODUCT数量 = NewQuabtity         WHERE PRODUCT.名称 = ’铅笔’                   AND.PRODUCT.数量 = 01dQuantity{解除PRODUCT表上的锁}UNLOCKPRODUCT</span></span></span>

乐观锁定的优点是仅当事务处理完成后才获取锁。这样,锁定的时间比悲观锁定的要短。如果事务复杂或是客户机的速度慢,锁定时间就会少很多。如果锁定粒度(例如整个PRODUCT表),这个优点显得更为重要。

乐观锁定的缺点是如果铅笔同时有很多操作时,事务就可能必须重复执行很多次。如果事务要对一个资源执行很多操作时就不适合使用乐观锁定。

业务思想

事务是数据库中很重要的一点,正是因为事务的存在保证了数据库的完成性,我们可以很安全的访问我们所需要的数据,而不发生任何的差异化。

事务的概念被很多人所诠释。他们要么不做,要做就做的很成功,很值得我们借鉴。去做一项事务,把自己装入其中,用最努力的方式,取得最优的结果集,祝愿每一个人!



2 0
原创粉丝点击