Oracle事务(transaction)详解 |
一、数据异常因为Oracle中支持多个事务并发执行,所以会出现下面的数据异常 。
事务中遇到的这些异常与事务的隔离性设置有关,事务的隔离性设置越多,异常就出现的越少,但并发效果就越低,事务的隔离性设置越少,异常出现的越多,并发效果越高 。 二、隔离级别:针对读取数据时可能产生的不一致现象,在SQL92标准中定义了4个事务的隔离级别:
Oracle默认的隔离级别是read committed 。 Oracle支持SQL92标准的READ_COMMITED、SERIALIZABLE,自身特有的Read only和Read write隔离级别 。
1、设置隔离级别设置一个事务的隔离级别: SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET TRANSACTION READ ONLY; SET TRANSACTION READ WRITE; 注意:这些语句是互斥的,不能同时设置两个或两个以上的选项 。 设置单个会话的隔离级别: ALTER SESSION SET TRANSACTION ISOLATION LEVEL READ COMMITTED; ALTER SESSION SET TRANSACTION ISOLATION SERIALIZABLE; 三、数据库锁:在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁) 。
为了保证性能:乐观锁,悲观锁
在Oracle中最主要的锁是DML锁(data locks,数据锁),DML锁的目的在于保证并发情况下的数据完整性 。在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁 。 1、Oracle中的锁锁有“共享锁”、“排它锁”,“共享排它锁”等多种类型,而且每种类型又有“行级锁” (一次锁住一条记录),“页级锁” (一次锁住一页,即数据库中存储记录的最小可分配单元),“表级锁” (锁住整个表) 。 (1)共享锁(S锁) lock table in share mode (2)排他锁(X锁) lock table in exclusive mode (3)行级共享锁(RS锁) select … from for update (4)行级排他锁(RX锁) (5)共享行级排他锁(SRX锁) lock table in share row exclusive mode 上述几种锁模式中,RS锁是限制最少的锁,X锁是限制最多的锁 。当程序对所做的修改进行提交(Commit)或回滚(Rollback)后,锁住的资源便会得到释放,从而允许其他用户进行操作 。如果两个事务,分别锁定一部分数据,而都在等待对方释放锁才能完成事务操作,这种情况下就会发生死锁 。 下图列出产生锁定模式的SQL语句: 四、事务组成:一条或者多条DML,[一条DDL]和一条DCL 。 五、事务的分类:1、显式事务:
2、隐式事务:
六、事务控制命令1、提交事务在执行使用 2、回滚事务保存点(savepoint):是事务中的一点,用于取消部分事务,当结束事务时,会自动的删除该事务所定义的所有保存点 。当执行ROLLBACK时,通过指定保存点可以回退到指定的点 。 设置保存点: Savepoint a; 删除保存点: Release Savepoint a; 回滚部分事务: Rollback To a; 回滚全部事务: Rollback; 七、示例银行转帐的例子是最经典的事务示例: -- 从账户一向账户二转账 DECLARE v_money NUMBER(8, 2); -- 转账金额 v_balance account.balance%TYPE; -- 账户余额 BEGIN v_money := &转账金额; -- 输入转账金额 -- 从账户一减钱 UPDATE account SET balance = balance - v_money WHERE id = &转出账户 RETURNING balance INTO v_balance; IF SQL%notfound THEN raise_application_error(-20001, '没有该账户:' || &转出账户); END IF; IF v_balance < 0 THEN raise_application_error(-20002, '账户余额不足'); END IF; -- 向账户二加钱 UPDATE account SET balance = balance + v_money WHERE id = &转入账户; IF SQL%notfound THEN raise_application_error(-20001, '没有该账户:' || &转入账户); END IF; -- 如果没有异常,则提交事务 COMMIT; dbms_output.put_line('转账成功'); EXCEPTION WHEN OTHERS THEN ROLLBACK; -- 出现异常则回滚事务 dbms_output.put_line('转账失败:'); dbms_output.put_line(sqlerrm); END; 到此这篇关于Oracle事务(transaction)的文章就介绍到这了 。希望对大家的学习有所帮助,也希望大家多多支持 。 |