参考资料:
Transactions
对于 Oracle 事务的总结
什么是事务?
事务 (Transaction) 是拜访并可能更新数据库中各种数据项的一个程序执行单元 (unit)。事务由事务开始(begin transaction) 和事务完结 (end transaction) 之间执行的整体操作组成。
事务的属性 -ACID
- 原子性(Atomicity)- 事务的原子性强调了一个事物是一个逻辑工作单元,是一个整体,是不可分割的。一个事务所蕴含的操作要么全副做,要不全副不做。
- 一致性(Consistency)- 一个事务执行一项数据库操作,事务使数据库从一种一致性的状态变换成另一种一致性状态。
- 隔离性(Isolation)- 在事务未提交前,它操作的数据,对其余用户不可见。
-
持久性(Durability)- 一旦事务胜利实现,该事务对数据库所施加的所有更新都是永恒的。
- redo 日志 – 提交的事务被永恒的记录到 redo 日志中。
<!–more–>
数据库事务的开始和完结
以第一个 DML 语句的执行作为开始
以上面的其中之一作为完结:
- commit 或 rollback 语句
- DDL 或 DCL 语句(主动提交)
- 用户会话失常完结 –commit
- 零碎异样完毕 –rollback
并发与数据的读取
当多个会话同时拜访(操作)雷同的数据时,将会呈现一些意想不到的后果。包含:
-
脏读 –dirty reads
一个事务读取了另一个事务未提交的数据, 而这个数据是有可能回滚
-
不可反复读 –non-repeatable reads
在数据库拜访中,一个事务范畴内两个雷同的查问却返回了不同数据。这是因为查问时零碎中其余事务批改的提交而引起的。
-
幻读 –Phantom(空幻的)reads
事务 1 读取记录时事务 2 减少了记录并提交,事务 1 再次读取时能够看到事务 2 新增的记录。对事物 1 而言就如同呈现了幻觉一样。
事务的隔离等级
ANSI 定义的事务的隔离等级:
事务隔离等级 | 脏读 | 不可反复读 | 幻读 |
---|---|---|---|
Read uncommited(读未提交的) | Y | Y | Y |
Read commited(读提交的) | N | Y | Y |
Repeatable read | N | N | Y |
Serializable | N | N | N |
Oracle 定义的事务隔离等级:
事务隔离等级 | 影响 |
---|---|
Read commited | Oracle 默认的隔离等级,对一条 SQL,能够保证数据的一致性,对于一个事务,无奈做到 repeatable read。 |
Serializable | 只能看到事务开始时所有提交的扭转以及本身的扭转 |
Read-only | 只能看到事务开始时所有提交的扭转,本身不容许 DML 操作 |
事务的并发管制 - 锁
Oracle 的锁定机制
- Oracle 尽可能的缩小锁定的应用
- Oracle 的读操作不会对表加锁,一些数据库会应用查问锁定(共享锁,排它锁)
- Oracle 通过回滚机制,保障读不会受到阻塞
- Oracle 没有锁管理器
- Oracle 中锁作为数据块的一种属性存在
Oracle 和 Sql Server 锁的区别
Sql Server | Oracle |
---|---|
并发和读一致性不可兼得,必须就义一方 | 可兼得 |
因为锁实现形式,事务代价低廉 | 没有真正的锁,事务没有资源代价 |
提倡尽快提交 | 主张依照业务需要确定事务边界 |
事务的管制 -savepoint
通过在事务两头设置检查点,能够更加精密的管制事务,避免一部分错误操作导致整个事务从新运行。演示如下:
SQL> create table t(id int);
表已创立。SQL> insert into t values(1);
已创立 1 行。SQL> savepoint s1;
保留点已创立。SQL> select * from t;
ID
----------
1
SQL> update t set id=2;
已更新 1 行。SQL> savepoint s2;
保留点已创立。SQL> select * from t;
ID
----------
2
SQL> rollback to s1;
回退已实现。SQL> select * from t;
ID
----------
1
一旦返回到保留点 s1 之后 s2 就失去了成果,因为曾经回到 s1 了,这时候 s2 还不存在。
自治事务
自治事务容许在一个事务中存在独立的事务,它的操作不会对以后事务产生影响。
语法:
pragma autonomous_transaction
对于自治事务的应用能够参考:ORACLE 中的自治事务
试验演示如下:(演示用例来自参考资料 Oracle 中的自治事务)
首先是不应用自治事务
SQL> create table msg (msg varchar2(120));
SQL> set serveroutput on
SQL> declare
2 cnt number := -1; --} Global variables
3 procedure local is
4 begin
5 select count(*) into cnt from msg;
6 dbms_output.put_line('local: # of rows is'||cnt);
7
8 insert into msg values ('New Record');
9 commit;
10 end;
11 begin
12 delete from msg ;
13 commit;
14 insert into msg values ('Row 1');
15 local;
16 select count(*) into cnt from msg;
17 dbms_output.put_line('main: # of rows is'||cnt);
18 rollback;
19
20 local;
21 insert into msg values ('Row 2');
22 commit;
23
24 local;
25 select count(*) into cnt from msg;
26 dbms_output.put_line('main: # of rows is'||cnt);
27 end;
28 /
local: # of rows is 1 -> 子程序 local 中能够’看到’主匿名块中的 uncommitted 记录
main: # of rows is 2 -> 主匿名块能够’看到’2 条记录(它们都是被 local commit 掉的)
local: # of rows is 2 -> 子程序 local 首先’看到’2 条记录, 而后又 commit 了第三条记录
local: # of rows is 4 -> 子程序 local 又’看到’了新减少的记录(它们都是被 local commit 掉的), 而后又 commit 了第五条记录
main: # of rows is 5 -> 主匿名块最初’看到’了所有的记录.
PL/SQL 过程已胜利实现。
从这个例子中, 咱们看到 COMMIT 和 ROLLBACK 的地位无论是在主匿名块中或者在子程序中, 都会影响到整个以后事务.
当初如果将 procedure local 改成自治事务, 在 procedure local 前面加上:
pragma AUTONOMOUS_TRANSACTION;
成果如下:
SQL> declare
2 cnt number := -1; --} Global variables
3 procedure local is
4 pragma AUTONOMOUS_TRANSACTION;
5 begin
6 select count(*) into cnt from msg;
7 dbms_output.put_line('local: # of rows is'||cnt);
8
9 insert into msg values ('New Record');
10 commit;
11 end;
12 begin
13 delete from msg ;
14 commit;
15 insert into msg values ('Row 1');
16 local;
17 select count(*) into cnt from msg;
18 dbms_output.put_line('main: # of rows is'||cnt);
19 rollback;
20
21 local;
22 insert into msg values ('Row 2');
23 commit;
24
25 local;
26 select count(*) into cnt from msg;
27 dbms_output.put_line('main: # of rows is'||cnt);
28 end;
29 /
local: # of rows is 0 -> 子程序 local 中无奈能够’看到’主匿名块中的 uncommitted 记录 (因为它是独立的)
main: # of rows is 2 -> 主匿名块能够’看到’2 条记录, 但只有一条是被 commited.
local: # of rows is 1 -> 子程序 local 中能够’看到’它前一次 commit 的记录, 然而主匿名块中的记录曾经被提前 rollback 了
local: # of rows is 3 -> 子程序 local 中能够’看到’3 条记录包含主匿名块 commit 的记录
main: # of rows is 4 -> 主匿名块最初’看到’了所有的记录.
PL/SQL 过程已胜利实现。
分布式事务
- 产生在多台数据库之间的事务。
- 通过 dblink 形式进行事务处理。
- 分布式事务要比单机事务要简单的多。
- 可能的危险:软件,服务器,网络。
分布式事务的组成
角色 | 形容 |
---|---|
client | 调用其它数据库信息的节点 |
database | 承受来自其它节点申请的节点 |
Global coordinate | 发动分布式事务的节点(全局调度者) |
Local coordinate | 解决本地事务,并和其它节点通信的节点(本地调度者) |
Commit point site | 被 global coordinate 指定第一个提交或回滚事务的节点 |
commit Point Strength
Oracle 选取 Commit Point Strength(相当于权重)最大的数据库作为 Commit point。
Oracle 分布式事务的机制 - 两阶段提交
2PC-two phase commit
- prepare phase
- commit phase
筹备阶段 prepare phase
为了实现筹备阶段,除了 commit point 机器外,其它的数据库机器依照以下步骤执行:
- 每个节点查看本人是否被其它节点所援用,如果有,就告诉这些节点筹备提交(进入 prepare 阶段)
- 每个节点查看本人运行的事务,如果发现本地运行的事务不做批改数据操作,则跳过前面的步骤,间接返回一个 read only 给全局协调过程。
- 如果事务须要批改数据,为事务调配相应的资源用于保障批改的失常进行。
- 对事物做的批改,记录 redo 信息。
- 本地 redo 保障事务失败后的回滚。
- 当下面的工作都胜利后,给全局协调过程返回准备就绪的信息,反之,返回失败的信号。
提交阶段 commit phase
提交阶段按上面的步骤进行:
- 全局协调器告诉 commit point 进行提交
- commit point 提交实现。
- commit point 服务器告诉全局协调器提交实现
- 全局协调器告诉其它节点进行提交
- 其它节点提交本地的事务,开释资源(提交先后顺序依据 Commit Point Strength)
- 其它节点在 redo 上记录相应的 redo 日志,并标注提交实现
- 其它节点告诉全局协调器提交实现。
分布式事务的完结
分布式事务的完结就是全局协调器和 commit point 两者之间开释资源的程序。
- 全局协调器告诉 commit point 数据库所有节点提交实现。
- commit point 数据库开释和事务相干的所有资源,而后告诉全局协调器。
- 全局协调器开释本人持有的资源
- 分布式事务完结
分布式事务的安全性
2PC 是否真的能够保障分布式事务的一致性?
- 实践上是不可能保障分布式事务的一致性。
对于 CAP 实践能够参见:CAP 实践
记得帮我点赞哦!
精心整顿了计算机各个方向的从入门、进阶、实战的视频课程和电子书,依照目录正当分类,总能找到你须要的学习材料,还在等什么?快去关注下载吧!!!
朝思暮想,必有回响,小伙伴们帮我点个赞吧,非常感谢。
我是职场亮哥,YY 高级软件工程师、四年工作教训,回绝咸鱼争当龙头的斜杠程序员。
听我说,提高多,程序人生一把梭
如果有幸能帮到你,请帮我点个【赞】,给个关注,如果能顺带评论给个激励,将不胜感激。
职场亮哥文章列表:更多文章
自己所有文章、答复都与版权保护平台有单干,著作权归职场亮哥所有,未经受权,转载必究!