转://Oracle 事务探索与实例(一)

时间:2022-09-25 20:41:19

数据库版本

SYS@LEO1>select* from v$version;

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise EditionRelease 11.2.0.1.0 - 64bit Production

PL/SQLRelease 11.2.0.1.0 - Production

CORE    11.2.0.1.0      Production

TNS forLinux: Version 11.2.0.1.0 - Production

NLSRTLVersion 11.2.0.1.0 - Production

事务那些事儿

1.什么是事务:事务是一组操作序列,这些操作要么都完成,要么都不完成,它是一个不可分割的操作单元。关系型数据库最核心的价值体现。说白了为了完成一件事而做的n个步骤,这n个步骤是有前后顺序的,必须按照A->B->C->D的逻辑顺序来执行,事务是数据库维护数据一致性的单位,例如多个会话同时读取同一数据的问题。

关系型数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。

场景:银行转账结算购物订票系统

非关系型数据库中,一个事务可以是一个操作,但操作之间没有关系,相互独立的。

比如:推荐系统日志分析网站搜索

用例子说明事务的四个属性和自动提交功能

事务的属性ACID

原子性(Atomicity):一个事务是一个不可分割的整体,事务中的操作要么都完成,要么都失败。

实例

SYS@LEO1>conn leo1/leo1

Connected.

LEO1@LEO1>drop table leo1 purge;                  清理环境

Table dropped.

LEO1@LEO1>create table leo1 (x number,ynumber);     创建表

Table created.

LEO1@LEO1>insert into leo1 values(1,1);               执行DML操作

1 row created.

LEO1@LEO1>update leo1 set x=2 where x=1;

1 row updated.

LEO1@LEO1>delete from leo1 where y=1;

1 row deleted.

LEO1@LEO1>commit;

Commit complete.

上面我们执行了三条sql语句,都属于一个事务,当commit的时候表示事务完成,这三条sql全部生效,如果rollback这三条sql全部失败,不存在有的完成有的失败,因为它们是一个不可再分割的整体。

一致性(Consistency):指数据库的一种状态的一致性,具体来说不可违反约束,不可违反规则,所谓的一致性就是一种人为规则,例如定义一个主键,插入2条一样的数据就违反了一致性条件。

实例

LEO1@LEO1>drop table leo2 purge;                                            清理环境

Table dropped.

LEO1@LEO1>create table leo2 (x number,ynumber,constraint pk_leo2 primary key(x));  x列有主键

Table created.

LEO1@LEO1>insert into leo2 values(1,1);

1 row created.

LEO1@LEO1>insert into leo2 values(1,2);                     当插入的值一样时违反了一致性

insert into leo2 values(1,2)

*

ERROR at line 1:

ORA-00001: unique constraint (LEO1.PK_LEO2)violated

隔离性(isolation):未提交的事务其他会话不可见。

实例

会话一

LEO1@LEO1>select * from leo2;               表里只有1条记录

X          Y

---------- ------------------- ----------

1          1

LEO1@LEO1>insert into leo2 values(2,2);        新插入一条

1 row created.

LEO1@LEO1>select * from leo2;               此时表里有2条记录,但未有提交

X          Y

---------- ------------------- ----------

1          1

2          2

会话二

[oracle@leonarding1 flashback_area]$sqlplus leo1/leo1    连接新会话

LEO1@LEO1>select * from leo2;      只能看到已提交事务的数据,未提交的事务看不到

X          Y

---------- ----------

1          1

持久性(Durability):事务一旦提交就不可更改,永久有效。

实例

LEO1@LEO1>drop table leo3 purge;

Table dropped.

LEO1@LEO1>create table leo3 (x number,ynumber);

Table created.

LEO1@LEO1>insert into leo3 values(1,1);

1 row created.

LEO1@LEO1>commit;

Commit complete.

LEO1@LEO1>select * from leo3;

X          Y

---------- ----------

1          1

LEO1@LEO1>rollback;

Rollback complete.

LEO1@LEO1>select * from leo3;

X          Y

---------- ----------

1          1

事务一旦commit,你再rollback也是无效的,已经插进去了。

事务是以第一个DML语句作为开始

以下面其中之一作为结束

(1)commit or rollback

(2)DDL or DCL

(3) 用户session正常结束退出sqlplus

(4) 系统正常结束or终止

事务自动提交,我们可以设置oracle自动提交事务

实例

LEO1@LEO1>show autocommit;                  默认是不启动自动提交的

autocommit OFF

LEO1@LEO1>set autocommit on;                 手工启动

LEO1@LEO1>show autocommit;

autocommit IMMEDIATE

LEO1@LEO1>insert into leo3 values(2,2);           当插入数据的同时就提交

1 row created.

Commit complete.

LEO1@LEO1>select * from leo3;

X          Y

---------- ----------

1         1

2          2

LEO1@LEO1>rollback;                           此时回滚已无效

Rollback complete.

LEO1@LEO1>select * from leo3;

X          Y

---------- ----------

1          1

2          2

LEO1@LEO1>set autocommit off;                  我们不建议开启事务自动提交功能

Oracle下演示Nonrepeatable Read PhantomRead的例子,给出SQL演示过程。

Non-repeatable Read不可重复读:在一个事务中,同样的数据被2次读取,得到不同的结果集

实例

Leo帮tiger一起买2张飞机表去肯尼亚看大象

LEO1@LEO1>drop table leo6 purge;

Table dropped.

LEO1@LEO1>create table leo6 (namevarchar2(10),ticket_type varchar2(20),price number);

Table created.

LEO1@LEO1>insert into leo6values('leo','plane_ticket',100);

1 row created.

LEO1@LEO1>insert into leo6values('tiger','plane_ticket',100);

1 row created.

LEO1@LEO1>commit;

Commit complete.

LEO1@LEO1>select * from leo6;

NAME      TICKET_TYPE               PRICE

---------- -------------------- ----------

leo         plane_ticket                100

tiger        plane_ticket                100

飞机票的价格都是100$,2个人一共200$

Leo查询的价格

LEO1@LEO1>select sum(price) both_pricefrom leo6;

BOTH_PRICE

------------------

200

在过行李安检的时候,发现tiger行李超重,原来tiger非常有爱心,给大象带了花生+毛豆,根据规定超重行李是要补交托运费的。

机场又加了100元托运费

LEO1@LEO1>update leo6 set price=200where name='tiger';

1 row updated.

LEO1@LEO1>select * from leo6;

NAME      TICKET_TYPE               PRICE

---------- -------------------- ----------

leo        plane_ticket                100

tiger       plane_ticket                200

LEO1@LEO1>commit;

Commit complete.

Leo再次查询价格时,总价变成300了

LEO1@LEO1>select sum(price) both_pricefrom leo6;

BOTH_PRICE

------------------

300

不可重复读在数据库中是可能出现的,所以要注意一下,上面leo和机场是两个独立会话

Phantom Read幻读:在一个事务中,同样的sql被2次执行,得到不同的结果集。

实例

翻山越岭跋山涉水终于来到了广阔的非洲大草原真是大象遍地走春风吹又生,tiger肴有兴致的数起了大象

Tiger 查询的结果

LEO1@LEO1>drop table leo7 purge;

Table dropped.

LEO1@LEO1>create table leo7 (namevarchar2(10),num number);

Table created.

LEO1@LEO1>insert into leo7values('a',1);

1 row created.

LEO1@LEO1>insert into leo7values('b',1);

1 row created.

LEO1@LEO1>commit;

Commit complete.

LEO1@LEO1>select count(*) from leo7;                    第一天发现了2只

COUNT(*)

-----------------

2

傍晚有一只小象跑了过来

LEO1@LEO1>insert into leo7values('c',1);

1 row created.

LEO1@LEO1>commit;

Commit complete.

第二天tiger又查询了一遍,这次发现了3只

LEO1@LEO1>select count(*) from leo7;

COUNT(*)

-----------------

3

小结:上述两个生动的例子展现了Non-repeatableRead不可重复读和Phantom Read幻读的过程,大家一定要好好体会里面的含义,理解这两种不同的数据读取方式。

Oracle设计一个场景,会导致Non-repeatableRead,然后选择一种事务隔离等级来避免它的发生,给出SQL演示过程。

场景:tiger在游玩非洲大草原之后,选择从海路回家,在走到索马里海岸的时候,有幸被海盗光顾,请他上岸吃海鲜,这次海盗拿出了不劳而获的敬业精神,赎金10000$,三天之内交换人质,一手交钱,一手交货。由于历来海盗的诚信记录并不是很光彩照人,我们模拟了一下可能的突发事件。

首先海盗提出条件,赎金10000$,还为此特意做了一个排行榜

LEO1@LEO1>create table leo8 (namevarchar2(20),cost int);          排行榜清单

Table created.

LEO1@LEO1>insert into leo8values('tiger',10000);                  插入tiger信息

1 row created.

LEO1@LEO1>commit;

Commit complete.

LEO1@LEO1>select * from leo8 whererownum<=1;                 我们看到tiger排在第一位

NAME                    COST

---------------------------------------------------------------

tiger                     10000

上面的信息是我们自己查询的情况,突然海盗得知tiger是中国知名的IT专家,国家的财富和人才。本着生意人的精明头脑,高价值的人当然换取的条件也水涨船高,海盗偷偷修改了赎金数,变成20000$

海盗

LEO1@LEO1>update leo8 set cost=20000where cost=10000;

1 row updated.

LEO1@LEO1>commit;

Commit complete.

当我们交钱的时候发现tiger升值了,哎呦我去~ 这不打劫嘛!

LEO1@LEO1>select * from leo8 whererownum<=1;

NAME                    COST

---------------------------------------------------------------

tiger                     20000

为了防止这种事情发生,我们可以使用Oracle的Read-only事务隔离等级和Serializable事务隔离等级来避免这种事情发生,这两种事务隔离等级非常相似,因此我们选择较常用的Serializable来给大家演示。

Read-only事务隔离等级:只能看到事务开始时所有提交的改变,自身不允许DML操作。

Serializable事务隔离等级:只能看到事务开始时所有提交的改变和自身的改变。

当海盗告知我们赎金是10000$的时候,我们先开出了清单

LEO1@LEO1>drop table leo8 purge;

Table dropped.

LEO1@LEO1>create table leo8 (namevarchar2(20),cost int);     tiger清单

Table created.

LEO1@LEO1>insert into leo8values('tiger',10000);

1 row created.

LEO1@LEO1>commit;

Commit complete.

LEO1@LEO1>set transaction isolationlevel serializable;         我们设置好了隔离等级

Transaction set.

LEO1@LEO1>select * from leo8 whererownum<=1;             没错是10000$

NAME                    COST

---------------------------------------------------------------

tiger                     10000

海盗又故伎重演,想把价格提高到20000$,这是另一个会话

LEO1@LEO1>update leo8 set cost=20000where cost=10000;      已经更新

1 row updated.

LEO1@LEO1>commit;

Commit complete.

到了较赎金的时候,我们又查询了一次

LEO1@LEO1>select * from leo8 whererownum<=1;

NAME                    COST

---------------------------------------------------------------

tiger                     10000

good,完美封杀了海盗邪恶企图,数据没有变化,但并不是说数据没有被修改,由于启动事务隔离策略,其他事务所做的修改我们是看不到的。Serializable只对当前事务有效,不对另外事务有效。

小结:Oracle中所有事务隔离等级都是依赖undo实现的。什么时候使用Serializable隔离等级好呢,当修改操作比较短的事务,事务中存在多条sql需要数据从事务开始时就保持一致,这样的场景适合。

用示例比较OracleRead committed Serializable 事务隔离等级的区别,给出SQL演示过程。

Read committed读已提交事务隔离等级:Oracle 默认隔离等级,支持不可重复读和幻读。这两种数据读写方式在第四题中已经完全阐述了,这里不在重复。

Serializable 事务隔离等级:只能看到事务开始时所有提交的改变和自身的改变,不支持不可重复读和幻读,事务开始是什么样子,结果就是什么样子,其他用户影响不了这个事务。

会话A

LEO1@LEO1>create table leo9(x int,yint);                 创建表

Table created.

LEO1@LEO1>insert into leo9values(100,100);              插入一行

1 row created.

LEO1@LEO1>commit;                                  提交

Commit complete.

LEO1@LEO1>set transaction isolationlevel serializable;       启动Serializable 事务隔离等级

Transaction set.

LEO1@LEO1>select * from leo9;

X          Y

---------- ----------------- ----------

100       100

会话B,我们用另一个会话不管怎么修改leo9表,都不会影响会话A事务

LEO1@LEO1>insert into leo9values(200,200);

1 row created.

LEO1@LEO1>commit;

Commit complete.

LEO1@LEO1>insert into leo9values(300,300);

1 row created.

LEO1@LEO1>commit;

Commit complete.

会话A,还是一条数据

LEO1@LEO1>select * from leo9;

X          Y

---------- ----------------- ----------

100       100

会话A自己修改的内容在事务中是生效的

LEO1@LEO1>insert into leo9values(400,400);          我们插入一条记录

1 row created.

LEO1@LEO1>select * from leo9;                     在本事务中是可以看到的

X          Y

---------- ----------

400        400

100        100

LEO1@LEO1>commit;                              一旦事务结束,Serializable 事务隔离等级就会失效

Commit complete.

会话A,又可以看到所有的记录了

LEO1@LEO1>select * from leo9;

X          Y

---------- ----------

400        400

100        100

200        200

300        300

两种事务隔离等级的比较

Read committed                       V.S                      Serializable   Transactions

支持SQL92标准支持SQL92标准

读取物化视图维护语句级一致性维护事务级一致性

事务一致性支持语句级支持事务级

行级锁支持支持

读锁定写不支持不支持

写锁定读不支持不支持

非行级锁不支持不支持

行级锁支持支持

事务锁等待支持支持

小结:Serializable事务隔离等级作用域是一个事务,超出这个事务就无效了。

事务属性   Phantom Read   Non-repeatableRead   Read committed   Serializable

转://Oracle 事务探索与实例(一)的更多相关文章

  1. 转&colon;&sol;&sol;Oracle 事务探索与实例&lpar;二&rpar;

    一数据库版本 SYS@LEO1>select * from v$version; BANNER ------------------------------------------------- ...

  2. spring事务传播机制实例讲解

    http://kingj.iteye.com/blog/1680350   spring事务传播机制实例讲解 博客分类:   spring java历险     天温习spring的事务处理机制,总结 ...

  3. Oracle之索引&lpar;Index&rpar;实例解说 - 基础

    Oracle之索引(Index)实例解说 - 基础 索引(Index)是关系数据库中用于存放表中每一条记录位置的一种对象.主要目的是加快数据的读取速度和数据的完整性检查.索引的建立是一项技术性要求很高 ...

  4. Mysql事务探索及其在Django中的实践(二)

    继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...

  5. Oracle事务

    Oracle事务的ACID特性 原子性Atomicity:事务中的所有动作要么都发生,要么都不发生. 一致性Consistency:事务将数据库从一种状态转变为下一种一致状态. 隔离性Isolatio ...

  6. 浅谈Oracle事务【转载竹沥半夏】

    浅谈Oracle事务[转载竹沥半夏] 所谓事务,他是一个操作序列,这些操作要么都执行,要么都不执行,是一个不可分割的工作单元.通俗解释就是事务是把很多事情当成一件事情来完成,也就是大家都在一条船上,要 ...

  7. Oracle事务之一:锁和隔离

    Oracle事务之一:锁和隔离 一. 事务概述 事务管理是数据库处理的核心.数据库既要保证用户能并发地执行事务,还要保证数据库的一致性. 当第一条可执行的SQL开始执行,就隐形地开始了一个事务,直到遇 ...

  8. linux 系统下开机自动启动oracle 监听和实例 (亲测有效)

    [oracle@oracle11g ~]$ dbstartORACLE_HOME_LISTNER is not SET, unable to auto-start Oracle Net Listene ...

  9. oracle事务和锁

    数据库事务概括 1. 说明 一组SQL,一个逻辑工作单位,执行时整体修改或者整体回退. 2.事务相关概念 1)事务的提交和回滚:COMMIT/ROLLBACK 2)事务的开始和结束 开始事务:连接到数 ...

随机推荐

  1. gcc编译器用法(自学总结)

    GCC仅仅意味着GNU C Compiler. gcc工作四个步骤:预处理,编译,汇编,连接. 1.预处理: 编译器将C源代码中的包含的头文件如stdio.h编译进来,用户可以使用gcc的选项&quo ...

  2. window&period;frameElement的使用

    window.frameElement的使用: 返回嵌入当前window对象的元素(比如 <iframe> 或者 <object>),如果当前window对象已经是顶层窗口,则 ...

  3. redis中setbit的用法

    原文地址:http://www.zhihu.com/question/27672245 在redis中,存储的字符串都是以二级制的进行存在的.举例:设置一个 key-value ,键的名字叫“andy ...

  4. 当我们安装使用时,会出现eclipse启动不了,出现&OpenCurlyDoubleQuote;Java was started but returned exit code&equals;13&period;&period;&period;&period;&period;&period;”的问题

    安装win8.1后,启动eclipse,也会提示 "java was started but returned exit code=13" 可能是eclipse.ini配置文件错误 ...

  5. 使用git Rebase让历史变得清晰

    当多人协作开发一个分支时,历史记录通常如下方左图所示,比较凌乱.如果希望能像右图那样呈线性提交,就需要学习git rebase的用法. “Merge branch”提交的产生 我们的工作流程是:修改代 ...

  6. 重置sqlserver自增长列的种子

    重置sqlserver自增长列的种子 转自:http://hi.baidu.com/zbphot/item/41c55982c2d02dd05e0ec184 如果表中的数据不要了,用下面的语句:  t ...

  7. Python自动化开发 - 堡垒机实例

    本节内容 一.堡垒机介绍 1. SSHClient 2. SFTPClient 3. Transport 二.堡垒机实现 一.堡垒机介绍 1. SSHClient 用户连接远程服务器并执行基本命令 1 ...

  8. eclipse git 忽略文件

    ps:git中只有.gitignore文件需要先加索引再提交,其它的都可以直接提交

  9. consul集群docker版本脚本

    https://blog.csdn.net/fenglailea/article/details/79098246 docker run -d --name node1 -e 'CONSUL_LOCA ...

  10. Python 读取文件中unicode编码转成中文显示问题

    Python读取文件中的字符串已经是unicode编码,如:\u53eb\u6211,需要转换成中文时有两种方式 1.使用eval: eval("u"+"\'" ...