Oracle 事务详解(transaction)

1 概述

1.1 事务的特性 ACID

事务特性描述
原子性(Atomicity)原子工作单元,不可分割
一致性(Consistency)事务结束前后,数据 整体不变
隔离性(Isolation)多个事务独立运行,互不干扰
持久性(Durability)事务一旦提交,对数据的改变 永久有效

举例:【银行转账】张三 向 李四 银行转账 100 元

-- 步骤1:张三 的账户金额 - 100 元
update account 
   set money = money - 100 
 where name = '张三';
-- 步骤2:李四 的账户金额 + 100 元
update account 
   set money = money + 100 
 where name = '李四';
-- 特性解释:
原子性:上述 2sql 语句的执行,要么全部成功,要么全部失败
一致性:账户总金额不变
隔离性:张三、李四 看不到彼此的账户信息
持久性:事务提交后,账户金额被永久保存

1.2 事务的状态

在这里插入图片描述

事务进入中止状态后,系统一般有如下两种选择:
① 重启事务
② 杀死事务

2 并发

事务的并发控制,可能会带来如下问题

问题描述
脏读事务A 读到了 事务B 修改但未提交 的数据
幻读在同一事务中,两次读取同一数据,得到的记录行数不同
不可重复读在同一事务中,两次读取同一数据,得到的数据内容不同
-- 基础数据准备
create table scott.emp_bak as select * from scott.emp;

-- 查询基础数据
select * from scott.emp_bak;

在这里插入图片描述

2.1 脏读 Dirty Read

描述:假如 事务B 回退,则 事务A 读取的是 “无效” 的数据(“脏数据”)

事务A						事务B
----------------------------------------------------
							update scott.emp_bak t2
							   set t2.job = 'TEST'
							 where t2.empno = 7369;
----------------------------------------------------
select t1.job -- Test
  from scott.emp_bak t1
 where t1.empno = 7369;
----------------------------------------------------
							rollback;

2.2 幻读 Phantom Read

描述:事务A 两次读取 事务B 的记录行数不一样,感觉发生了 “幻觉”
注意:侧重 记录行数 不一样,如:insert、delete 操作

事务A						事务B
----------------------------------------------------
select t1.job
  from scott.emp_bak t1
 where t1.empno = 7369;
---------------------------------------------------- 
							insert into scott.emp_bak(empno, job)
							values(7369, 'Test2');
							commit;
---------------------------------------------------- 
select t1.job -- 多了 Test2
  from scott.emp_bak t1
 where t1.empno = 7369;

2.3 不可重复读 Nonrepeatable Read

描述:事务A 两次读取 事务B 的数据内容不一样
注意:侧重 数据内容 不一样,如:update 操作

事务A						事务B
----------------------------------------------------
select t1.job
  from scott.emp_bak t1
 where t1.empno = 7369;
---------------------------------------------------- 
							update scott.emp_bak t2
							   set t2.job = 'Test2'
							 where t2.empno = 7369;
							commit;
---------------------------------------------------- 
select t1.job -- 变成了 Test2
  from scott.emp_bak t1
 where t1.empno = 7369;

3 隔离

3.1 隔离级别

隔离级别(由低到高)脏读不可重复读幻读数据库默认
读未提交 (Read Uncommitted)
读已提交 (Read Commited)×Oracle
重复读取(Repeatable Read)××Mysql
序列化 (Serializable)×××

说明:

  1. 引入事务隔离级别的目的:解决 事务的并发问题
  2. 隔离级别并非越高越好。越高意味着需要更多的 锁 来保证事务的正确性,效率就越低

3.2 查询和设置

-- 1. 首先创建一个事务(若有,可忽略)
declare
  trans_id varchar2(100);
begin
  trans_id := dbms_transaction.local_transaction_id(true);
end;

-- 2. 查询 事务隔离级别
select (case bitand(t.flag, power(2, 28))
         when 0 then
          'READ COMMITTED'
         else
          'SERIALIZABLE'  
       end) 事务隔离级别,
       s.username,
       s.sid,
       s.serial#,
       s.*
  from v$transaction t,
       v$session     s
 where s.taddr = t.addr;

-- 3. 设置 事务隔离级别 (Oracle 仅支持以下两种)
set transaction isolation level [read committed | serializable];
  • 9
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼丸丶粗面

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值