参考资料:程序员
Transactionssql
事务(Transaction)是访问并可能更新数据库中各类数据项的一个程序执行单元(unit)。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操做组成。安全
原子性(Atomicity)-事务的原子性强调了一个事物是一个逻辑工做单元,是一个总体,是不可分割的。一个事务所包含的操做要么所有作,要不所有不作。服务器
一致性(Consistency)-一个事务执行一项数据库操做,事务使数据库从一种一致性的状态变换成另外一种一致性状态。网络
隔离性(Isolation)-在事务未提交前,它操做的数据,对其余用户不可见。并发
持久性(Durability)-一旦事务成功完成,该事务对数据库所施加的全部更新都是永久的。oracle
以第一个DML语句的执行做为开始分布式
如下面的其中之一做为结束:ide
当多个会话同时访问(操做)相同的数据时,将会出现一些意想不到的结果。包括:
脏读 --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 |
---|---|
并发和读一致性不可兼得,必须牺牲一方 | 可兼得 |
由于锁实现方式,事务代价昂贵 | 没有真正的锁,事务没有资源代价 |
提倡尽快提交 | 主张按照业务需求肯定事务边界 |
经过在事务中间设置检查点,能够更加精细的控制事务,防止一部分错误操做致使整个事务从新运行。演示以下:
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 过程已成功完成。
角色 | 描述 |
---|---|
client | 调用其它数据库信息的节点 |
database | 接受来自其它节点请求的节点 |
Global coordinate | 发起分布式事务的节点(全局调度者) |
Local coordinate | 处理本地事务,并和其它节点通讯的节点(本地调度者) |
Commit point site | 被global coordinate指定第一个提交或回滚事务的节点 |
commit Point Strength
Oracle选取Commit Point Strength(至关于权重)最大的数据库做为Commit point。
2PC-two phase commit
准备阶段prepare phase
为了完成准备阶段,除了commit point机器外,其它的数据库机器按照如下步骤执行:
每一个节点检查本身是否被其它节点所引用,若是有,就通知这些节点准备提交(进入prepare阶段)
每一个节点检查本身运行的事务,若是发现本地运行的事务不作修改数据操做,则跳事后面的步骤,直接返回一个read only给全局协调进程。
若是事务须要修改数据,为事务分配相应的资源用于保证修改的正常进行。
对事物作的修改,记录redo信息。
本地redo保证事务失败后的回滚。
当上面的工做都成功后,给全局协调进程返回准备就绪的信息,反之,返回失败的信号。
提交阶段commit phase
提交阶段按下面的步骤进行:
分布式事务的结束就是全局协调器和commit point二者之间释放资源的顺序。
2PC是否真的能够保证分布式事务的一致性?
关于CAP理论能够参见:CAP理论
记得帮我点赞哦!
精心整理了计算机各个方向的从入门、进阶、实战的视频课程和电子书,按照目录合理分类,总能找到你须要的学习资料,还在等什么?快去关注下载吧!!!
念念不忘,必有回响,小伙伴们帮我点个赞吧,很是感谢。
我是职场亮哥,YY高级软件工程师、四年工做经验,拒绝咸鱼争当龙头的斜杠程序员。
听我说,进步多,程序人生一把梭
若是有幸能帮到你,请帮我点个【赞】,给个关注,若是能顺带评论给个鼓励,将不胜感激。
职场亮哥文章列表:更多文章
本人全部文章、回答都与版权保护平台有合做,著做权归职场亮哥全部,未经受权,转载必究!