Oracle事务实例分析(oracle,开发技术)

时间:2024-05-03 00:58:11 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

一、数据异常

因为Oracle中支持多个事务并发执行,所以会出现下面的数据异常。

  • 脏读(Dirty Read):事务T1更新了一行数据,还没有提交所做的修改,T2读取更新后的数据,T1回滚,T2读取的数据无效,这种数据称为脏读数据。

  • 不可重复读(UNrepeatable Read):事务T1读取一行数据,T2修改了T1刚刚读取的记录,T1再次查询,发现与第一次读取的记录不相同,称为不可重复读。

  • 幻读(Phantom Read):事务T1读取一条带WHERE条件的语句,返回结果集,T2插入一条新纪录,恰好也是T1的WHERE条件,T1再次查询,结果集中又看到T2的记录,新纪录就叫做幻读。

事务中遇到的这些异常与事务的隔离性设置有关,事务的隔离性设置越多,异常就出现的越少,但并发效果就越低,事务的隔离性设置越少,异常出现的越多,并发效果越高。

二、隔离级别:

针对读取数据时可能产生的不一致现象,在SQL92标准中定义了4个事务的隔离级别:

  • NO_TRANSACTION 不支持事务

  • READ_UNCOMMITED 允许脏读、不可重复读、幻读

  • READ_COMMITED 允许不可重复读、幻读,不允许脏读

  • REPEATABLE 允许幻读,不允许脏读、不可重复读

  • SERIALIZABLE 脏读、不可重复读、幻读都不允许

Oracle默认的隔离级别是read committed。

Oracle支持SQL92标准的READ_COMMITED、SERIALIZABLE,自身特有的Read only和Read write隔离级别。

  • Read only:事务中不能有任何修改数据库中数据的操作语句,是Serializable的一个子集。

  • Read write:它是默认设置,该选项表示在事务中可以有访问语句、修改语句,但不经常使用。

1、设置隔离级别

设置一个事务的隔离级别:

SETTRANSACTIONISOLATIONLEVELREADCOMMITTED;SETTRANSACTIONISOLATIONLEVELSERIALIZABLE;SETTRANSACTIONREADONLY;SETTRANSACTIONREADWRITE;

注意:这些语句是互斥的,不能同时设置两个或两个以上的选项。

设置单个会话的隔离级别:

ALTERSESSIONSETTRANSACTIONISOLATIONLEVELREADCOMMITTED;ALTERSESSIONSETTRANSACTIONISOLATIONSERIALIZABLE;

三、数据库锁:

在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。

  • 排它锁:(X锁,eXclusive Locks)
    当有DML语句执行的时候,设计的行都会加上排它锁,其他事物不能进行读取修改。

  • 共享锁:(S锁,Shared Locks)
    加了共享锁的数据,可以被其他事物读取,但不能修改。如select语句。

为了保证性能:乐观锁,悲观锁

  • 悲观锁:每次都是假设数据肯定会冲突,数据开始读取时就把数据给锁住。

  • 乐观锁:每次都是假设一般情况下不会发生数据冲突,只有数据更新提交的时候,才会对数据的冲突与否进行检测,如果发生冲突,返回错误信息让用户处理。

在Oracle中最主要的锁是DML锁(data locks,数据锁),DML锁的目的在于保证并发情况下的数据完整性。在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。

1、Oracle中的锁

锁有“共享锁”、“排它锁”,“共享排它锁”等多种类型,而且每种类型又有“行级锁” (一次锁住一条记录),“页级锁” (一次锁住一页,即数据库中存储记录的最小可分配单元),“表级锁” (锁住整个表)。

(1)共享锁(S锁)
添加该S锁。在该锁定模式下,不允许任何用户更新表。但是允许其他用户发出select …from for update命令对表添加RS锁。

locktableinsharemode

(2)排他锁(X锁)
添加X锁。在该锁定模式下,其他用户不能对表进行任何的DML和DDL操作,该表上只能进行查询。

locktableinexclusivemode

(3)行级共享锁(RS锁)
通常是通过语句添加的,同时该方法也是我们用来手工锁定某些记录的主要方法。比如,当我们在查询某些记录的过程中,不希望其他用户对查询的记录进行更新操作,则可以发出这样的语句。当数据使用完毕以后,直接发出rollback命令将锁定解除。当表上添加了RS锁定以后,不允许其他事务对相同的表添加排他锁,但是允许其他的事务通过DML语句或lock命令锁定相同表里的其他数据行。

select…fromforupdate

(4)行级排他锁(RX锁)
当进行DML操作时会自动在被更新的表上添加RX锁,或者也可以通过执行lock命令显式的在表上添加RX锁。在该锁定模式下,允许其他的事务通过DML语句修改相同表里的其他数据行,或通过lock命令对相同表添加RX锁定,但是不允许其他事务对相同的表添加排他锁(X锁)。

(5)共享行级排他锁(SRX锁)
添加SRX锁。该锁定模式比行级排他锁和共享锁的级别都要高,这时不能对相同的表进行DML操作,也不能添加共享锁。

locktableinsharerowexclusivemode

上述几种锁模式中,RS锁是限制最少的锁,X锁是限制最多的锁。当程序对所做的修改进行提交(Commit)或回滚(Rollback)后,锁住的资源便会得到释放,从而允许其他用户进行操作。如果两个事务,分别锁定一部分数据,而都在等待对方释放锁才能完成事务操作,这种情况下就会发生死锁。

下图列出产生锁定模式的SQL语句:

Oracle事务实例分析

四、事务组成:

一条或者多条DML,[一条DDL]和一条DCL。

五、事务的分类:

1、显式事务:

  • 显式的调用DCL。

  • 只有用到COMMIT以后才会真正写入数据库,也持久化了。

2、隐式事务:

  • 如果人工要使用隐式事务,SET AUTOCOMMIT ON (只针对一个连接)

  • 以下情况为自动提交:
    1)正常执行完成的DDL语句:create、alter、drop
    2)正常执行完场的DCL语句GRANT、REVOKE
    3)正常退出的SQLPlus或者SQL Developer等客户端

六、事务控制命令

1、提交事务

在执行使用COMMIT语句可以提交事务,当执行了COMMIT语句后,会确认事务的变化,结束事务,删除保存点,释放锁。当使用COMMIT语句结束事务之后,其他会话将可以查看到事务变化后的新数据。

2、回滚事务

保存点(savepoint):是事务中的一点,用于取消部分事务,当结束事务时,会自动的删除该事务所定义的所有保存点。当执行ROLLBACK时,通过指定保存点可以回退到指定的点。

设置保存点:

Savepointa;

删除保存点:

ReleaseSavepointa;

回滚部分事务:

RollbackToa;

回滚全部事务:

Rollback;

七、示例

银行转帐的例子是最经典的事务示例:

--从账户一向账户二转账DECLAREv_moneyNUMBER(8,2);--转账金额v_balanceaccount.balance%TYPE;--账户余额BEGINv_money:=&转账金额;--输入转账金额--从账户一减钱UPDATEaccountSETbalance=balance-v_moneyWHEREid=&转出账户RETURNINGbalanceINTOv_balance;IFSQL%notfoundTHENraise_application_error(-20001,'没有该账户:'||&转出账户);ENDIF;IFv_balance<0THENraise_application_error(-20002,'账户余额不足');ENDIF;--向账户二加钱UPDATEaccountSETbalance=balance+v_moneyWHEREid=&转入账户;IFSQL%notfoundTHENraise_application_error(-20001,'没有该账户:'||&转入账户);ENDIF;--如果没有异常,则提交事务COMMIT;dbms_output.put_line('转账成功');EXCEPTIONWHENOTHERSTHENROLLBACK;--出现异常则回滚事务dbms_output.put_line('转账失败:');dbms_output.put_line(sqlerrm);END;
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:Oracle事务实例分析的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Oracle官方工具SQL Developer如何使用下一篇:

13 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18