【17】事务

1. 事务

  • 事务(Transaction)是并发控制的基本单位。

  • 事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。

    例如,银行转账工作:从一个账号扣款并使另一个账号增款,这两个操作要么都执行,要么都不执行。所以,应该把它们看成一个事务。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性。

  • 事务的提出主要是为了解决并发情况下保持数据一致性的问题。

2. 事务基本特征

  • Atomic(原子性):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成功,要么全部失败。
  • Consistency(一致性):只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初状态。
  • Isolation(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。
  • Durability(持久性):事务结束后,事务处理的结果必须能够得到固化。

3. 事务操作的语句

  • 开始事物:BEGIN TRANSACTION
  • 提交事物:COMMIT TRANSACTION
  • 回滚事务:ROLLBACK TRANSACTION

4. 事务的保存点

  • SAVE TRANSACTION 保存点名称 : 自定义保存点的名称和位置
  • ROLLBACK TRANSACTION 保存点名称 : 回滚到自定义的保存点

5. 事务组成

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

6. 事务的分类

  • 显式事务:
    要去显式的调用DCL。
    只有用到COMMIT以后才会真正写入数据库,也持久化了。
  • 隐式事务:
    如果人工要使用隐式事务,SET AUTOCOMMIT ON (只针对一个连接)
    以下情况为自动提交:
    • 正常执行完成的DDL语句:create、alter、drop
    • 正常执行完场的DCL语句GRANT、REVOKE
    • 正常退出的SQLPlus或者SQL Developer等客户端

7. 回滚:

RollBack只能对未提交的数据撤销,已经Commit的数据是无法撤销的,因为commit之后已经持久化到数据库中。

8. 事务与存储过程连用,实现转账

	CREATE OR REPLACE
	    PROCEDURE "zhuanZhang" AS
			BEGIN
				-- 存储过程,默认自动开启事务
				update bank set balance = balance + 800 where name = 'Jerry'; 
				update bank set balance = balance - 800 where name = 'Tom'; 
				DBMS_OUTPUT.PUT_LINE('转账成功');
				commit;-- 提交事务
				exception -- 异常
					when others then 
							DBMS_OUTPUT.PUT_LINE('转账失败');
							rollback; -- 回滚事务 
			END;

9. 数据异常

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

9.1 脏读

当一个事务修改数据时,另一事务读取了该数据,但是第一个事务由于某种原因取消对数据修改,使数据返回了原状态,这是第二个事务读取的数据与数据库中数据不一致,这就叫脏读。

如:事务T1修改了一条数据,但是还未提交,事务T2恰好读取到了这条修改后了的数据,此时T1将事务回滚,这个时候T2读取到的数据就是脏数据。

9.2 不可重复读

是指一个事务读取数据库中的数据后,另一个事务则更新了数据,当第一个事务再次读取其中的数据时,就会发现数据已经发生了改变,这就是不可重复读取。不可重复读取所导致的结果就是一个事务前后两次读取的数据不相同。

如:事务T1读取一行记录,紧接着事务T2修改了T1刚刚读取的记录,然后T1再次查询,发现与第一次读取的记录不同。

9.3 幻读

如果一个事务基于某个条件读取数据后,另一个事务则更新了同一个表中的数据,这时第一个事务再次读取数据时,根据搜索的条件返回了不同的行,这就是幻读。

如:事务T1读取一条指定where条件的语句,返回结果集。此时事务T2插入一行新记录,恰好满足T1的where条件。然后T1使用相同的条件再次查询,结果集中可以看到T2插入的记录,这条新纪录就是幻读。

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

10. 事务隔离级别

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

隔离级别 脏读 不可重复读 幻读
Read uncommitted(读未提交)
Read committed(读已提交)
Repeatable read(可重复读)
Serializable(串行读)
  • Oracle默认的隔离级别是read committed。

Oracle支持上述四种隔离级别中的两种:read committed 和serializable。除此之外,Oralce中还定义Read only和Read write隔离级别。

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

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

  • 设置隔离级别

    • 设置一个事务的隔离级别:
      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;

11. 锁

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

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

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

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

猜你喜欢

转载自blog.csdn.net/Spectre_win/article/details/88557773
17